General documentation improvements
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
target/
|
||||
*target*
|
||||
*.pem
|
||||
gurty.toml
|
||||
certs
|
||||
search_indexes
|
||||
config.toml
|
||||
.vscode
|
||||
57
README.md
57
README.md
@@ -1,35 +1,36 @@
|
||||
gurted (verb)
|
||||
# Gurted
|
||||
|
||||
Gurted (verb)
|
||||
> “to do something smart, but also dangerous”
|
||||
|
||||
wayfinder (noun)
|
||||
Wayfinder (noun)
|
||||
> “a person helping others navigate”
|
||||
|
||||
In traditional web, you might be familiar with the term "browser." A **wayfinder** is that, but for the **GURT** protocol.
|
||||
Gurted is an ecosystem similar to the World Wide Web, it features:
|
||||
- It's own **Viewfinder** (a custom browser named Flumi) written in Rust and GDScript with [Godot](https://godotengine.org/),
|
||||
- A custom HTML, CSS and ***Lua*** engine (We do **not like javascript**)
|
||||
- A custom **DNS** that allows users to create domains with TLDs such as `.based`, `.delulu`, `.aura`, `.twin` and many more.
|
||||
- A search engine called **Ringle**.
|
||||
|
||||
TODO:
|
||||
1. Write a new **selection system**. Godot's built-in `RichTextLabel` selection is limited by the node's boundaries. In normal web, holding click and dragging your mouse across the screen will select text across multiple nodes. Godot doesn't have a "set_selected_text" property, despite having one for "get_selected_text".
|
||||
2. **Right-click Dropdown** for basic text operations (Copy, Paste, Cut). Download options for images
|
||||
3. **Select-all CTRL+A shortcut**
|
||||
4. **Scrolling** in the website container
|
||||
5. **Store** tab containers so switching tabs won't erase previous tab.
|
||||
6. **GIF** support
|
||||
7. **Video** support via [GDE GoZen](https://github.com/VoylinsGamedevJourney/gde_gozen)
|
||||
8. **Required** attribute for inputs
|
||||
9. Installer should register **gurt://** as a valid protocol thru the registry.
|
||||
10. < input type=**datetime** />, essentially a type "date" but with a vertical separator, then `mm | ss | FORMAT` layout for time.
|
||||
11. **< table >** component. [🔗 Related Godot proposal](https://github.com/godotengine/godot-proposals/issues/97)
|
||||
12. **< canvas >** component should be theoretically impossible by exposing Godot `_draw()` APIs to Lua.
|
||||
13. `grid` display property for CSS, using `GridContainer` in Godot.
|
||||
14. Position `absolute` can be achieved by wrapping inside a Control node with a 0,0 size (so it's ignored by the layout), and moving the inner child according to CSS.
|
||||

|
||||
|
||||
Issues:
|
||||
1. **< br />** counts as 1 element in **WebsiteContainer**, therefore despite being (0,0) in size, it counts as double in spacing
|
||||
2. **Tween** API doesn't modify CSS, it operates independently at Godot level.
|
||||
3. Certain properties like `scale` and `rotate` don't apply to the `active` pseudo-class because they rely on mouse_enter and mouse_exit events
|
||||
4. `<div style="bg-[#3b82f6] w-[100px] h-[100px] flex hover:scale-110 transition hover:rotate-45">Box</div>` something like this has the "Box" text (presumably the PanelContainer) as the target of the hover, not the div itself (which has the w/h size)
|
||||
5. font in button doesn't comply with CSS, its the projects default
|
||||
6. The HTML, or Lua, doesn't support non-UTF8 characters. The HTML parser relies on `PackedByteArray` (for the XMLParser, from my memory).
|
||||
# File structure
|
||||
- `/dns` - The source code for the **DNS** (Domain Name System)
|
||||
- `/docs` - The source code for the **Documentation page** available at https://docs.gurted.com
|
||||
- `/flumi` - The source code for the **Wayfinder** Flumi, used to view gurt:// sites
|
||||
- `/protocol` - Source code for all gurt related things, like the gdextension and the rust library
|
||||
- `/search-engine` - The Source code for the official **search engine** (Ringle)
|
||||
|
||||
Notes:
|
||||
- **< input />** is sort-of inline in normal web. We render it as a block element (new-line).
|
||||
- Fonts use **Flash of Unstyled Text (FOUT)** as opposed to **Flash of Invisible Text (FOIT)**, meaning the text with custom fonts will render with a generic font (sans-serif) while the custom ones downloads.
|
||||
# Download and install
|
||||
|
||||
## Windows
|
||||
Grab the installer from the [releases page](https://github.com/outpoot/gurted/releases) and run it as an administrator or download the binary and run it
|
||||
|
||||
## Linux
|
||||
Download the binary from [releases page](https://github.com/outpoot/gurted/releases) and run it.
|
||||
|
||||
## MacOS
|
||||
Download the binary from the [releases page](https://github.com/outpoot/gurted/releases) and copy it to your applications folder.
|
||||
|
||||
# Compiling
|
||||
The process is identycal to compiling a godot game, however if you modified the protocol library or the gdextension you have to rebuild the gurted gdextension library by running build.sh in `/protocol/gdextension` and copy `/protocol/gdextension/target/x86_64-unknown-linux-gnu/release/libgurt_godot.so` (or the windows/macos library) to `flumi/addons/gurt-protocol/bin/linux` or `flumi/addons/gurt-protocol/bin/windows` for windows.
|
||||
@@ -1,15 +1,6 @@
|
||||
# Domain Management API
|
||||
# Domain Name System
|
||||
|
||||
This is a Domain Management API built with Rust (Actix Web) and PostgreSQL. It provides user authentication, domain registration with Discord approval workflow, and invite-based registration limits.
|
||||
|
||||
## Features
|
||||
|
||||
- 🔐 **JWT Authentication** - Secure user registration and login
|
||||
- 📝 **Domain Registration** - Submit domains for approval with usage limits
|
||||
- 🤖 **Discord Integration** - Automatic approval workflow via Discord bot
|
||||
- 📧 **Invite System** - Users can share registration slots via invite codes
|
||||
- 🛡️ **Rate Limiting** - Protection against abuse
|
||||
- 📊 **PostgreSQL Database** - Reliable data storage with migrations
|
||||
The gurted DNS is built with Rust (Actix Web) and PostgreSQL. It provides endpoints to create, read, update, and delete domain information, along with rate limiting for certain operations.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
@@ -19,24 +10,24 @@ This is a Domain Management API built with Rust (Actix Web) and PostgreSQL. It p
|
||||
- [GET /auth/me](#get-authme)
|
||||
- [POST /auth/invite](#post-authinvite)
|
||||
- [POST /auth/redeem-invite](#post-authredeem-invite)
|
||||
- [GET /auth/domains](#get-authdomains) 🔒
|
||||
- [GET /auth/domains](#get-authdomains) *
|
||||
- [Domain Endpoints](#domain-endpoints)
|
||||
- [GET /](#get-)
|
||||
- [POST /domain](#post-domain) 🔒
|
||||
- [POST /domain](#post-domain) *
|
||||
- [GET /domain/:name/:tld](#get-domainnametld)
|
||||
- [PUT /domain/:name/:tld](#put-domainnametld) 🔒
|
||||
- [DELETE /domain/:name/:tld](#delete-domainnametld) 🔒
|
||||
- [PUT /domain/:name/:tld](#put-domainnametld) *
|
||||
- [DELETE /domain/:name/:tld](#delete-domainnametld) *
|
||||
- [GET /domains](#get-domains)
|
||||
- [GET /tlds](#get-tlds)
|
||||
- [POST /domain/check](#post-domaincheck)
|
||||
|
||||
🔒 = Requires authentication
|
||||
* = Requires authentication
|
||||
|
||||
## Authentication Endpoints
|
||||
|
||||
### POST /auth/register
|
||||
|
||||
Register a new user account. New users start with 3 domain registrations.
|
||||
Register a new user account. New users have a limit of 3 domain registrations by default.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
@@ -84,7 +75,7 @@ Login with existing credentials.
|
||||
}
|
||||
```
|
||||
|
||||
### GET /auth/me 🔒
|
||||
### GET /auth/me *
|
||||
|
||||
Get current user information. Requires `Authorization: Bearer <token>` header.
|
||||
|
||||
@@ -98,9 +89,9 @@ Get current user information. Requires `Authorization: Bearer <token>` header.
|
||||
}
|
||||
```
|
||||
|
||||
### POST /auth/invite 🔒
|
||||
### POST /auth/invite *
|
||||
|
||||
Create an invite code that can be redeemed for 3 additional domain registrations. Requires authentication but does NOT consume any of your registrations.
|
||||
Create an invite code that can be redeemed for 3 additional domain registrations. Requires authentication but does NOT consume any of the registrations of the inviting user.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
@@ -109,7 +100,7 @@ Create an invite code that can be redeemed for 3 additional domain registrations
|
||||
}
|
||||
```
|
||||
|
||||
### POST /auth/redeem-invite 🔒
|
||||
### POST /auth/redeem-invite *
|
||||
|
||||
Redeem an invite code to get 3 additional domain registrations. Requires authentication.
|
||||
|
||||
@@ -128,9 +119,9 @@ Redeem an invite code to get 3 additional domain registrations. Requires authent
|
||||
}
|
||||
```
|
||||
|
||||
### GET /auth/domains 🔒
|
||||
### GET /auth/domains *
|
||||
|
||||
Get all domains owned by the authenticated user, including their status. Requires `Authorization: Bearer <token>` header.
|
||||
Get all domains owned by the authenticated user, including their status. Requires authentication.
|
||||
|
||||
**Query Parameters:**
|
||||
- `page` - Page number (default: 1)
|
||||
@@ -191,9 +182,9 @@ GET /tlds.
|
||||
Ratelimits are as follows: 10 requests per 60s.
|
||||
```
|
||||
|
||||
### POST /domain 🔒
|
||||
### POST /domain *
|
||||
|
||||
Submit a domain for approval. Requires authentication and consumes one registration slot. The domain will be sent to Discord for manual approval.
|
||||
Submit a domain for approval. Requires authentication and consumes one registration slot. The request will be sent to the moderators via discord for verification.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
@@ -222,9 +213,9 @@ Fetch an approved domain by name and TLD. Only returns domains with 'approved' s
|
||||
}
|
||||
```
|
||||
|
||||
### PUT /domain/:name/:tld 🔒
|
||||
### PUT /domain/:name/:tld *
|
||||
|
||||
Update the IP address of your approved domain. You can only update domains you own.
|
||||
Update the IP address of the user's approved domain.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
@@ -240,17 +231,17 @@ Update the IP address of your approved domain. You can only update domains you o
|
||||
}
|
||||
```
|
||||
|
||||
### DELETE /domain/:name/:tld 🔒
|
||||
### DELETE /domain/:name/:tld *
|
||||
|
||||
Delete your domain. You can only delete domains you own.
|
||||
Delete a domain owned by the account.
|
||||
|
||||
**Response:**
|
||||
- `200 OK` - Domain deleted successfully
|
||||
- `404 Not Found` - Domain not found or not owned by you
|
||||
- `404 Not Found` - Domain not found or not owned by the requesting account
|
||||
|
||||
### GET /domains
|
||||
|
||||
Fetch all approved domains with pagination support. Only shows domains with 'approved' status.
|
||||
Fetch all approved domains with pagination support.
|
||||
|
||||
**Query Parameters:**
|
||||
- `page` (or `p`) - Page number (default: 1)
|
||||
@@ -304,11 +295,11 @@ Check if domain name(s) are available.
|
||||
|
||||
## Discord Integration
|
||||
|
||||
When a user submits a domain registration, it's automatically sent to a configured Discord channel with:
|
||||
When a user submits a domain registration, it's automatically sent to the configured Discord channel with:
|
||||
|
||||
- 📝 Domain details (name, TLD, IP, user info)
|
||||
- ✅ **Approve** button - Marks domain as approved
|
||||
- ❌ **Deny** button - Opens modal asking for denial reason
|
||||
- ❌ **Deny** button - Opens a modal for inputing a denial reason
|
||||
|
||||
Discord admins can approve or deny registrations directly from Discord.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Website
|
||||
# Gurted documentation
|
||||
|
||||
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
|
||||
The documentation is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
slug: first-blog-post
|
||||
title: First Blog Post
|
||||
authors: [slorber, yangshun]
|
||||
tags: [hola, docusaurus]
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet...
|
||||
|
||||
<!-- truncate -->
|
||||
|
||||
...consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
slug: long-blog-post
|
||||
title: Long Blog Post
|
||||
authors: yangshun
|
||||
tags: [hello, docusaurus]
|
||||
---
|
||||
|
||||
This is the summary of a very long blog post,
|
||||
|
||||
Use a `<!--` `truncate` `-->` comment to limit blog post size in the list view.
|
||||
|
||||
<!-- truncate -->
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
slug: mdx-blog-post
|
||||
title: MDX Blog Post
|
||||
authors: [slorber]
|
||||
tags: [docusaurus]
|
||||
---
|
||||
|
||||
Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
|
||||
|
||||
:::tip
|
||||
|
||||
Use the power of React to create interactive blog posts.
|
||||
|
||||
:::
|
||||
|
||||
{/* truncate */}
|
||||
|
||||
For example, use JSX to create an interactive button:
|
||||
|
||||
```js
|
||||
<button onClick={() => alert('button clicked!')}>Click me!</button>
|
||||
```
|
||||
|
||||
<button onClick={() => alert('button clicked!')}>Click me!</button>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 94 KiB |
@@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cni08ewpfei11"
|
||||
path="res://.godot/imported/docusaurus-plushie-banner.jpeg-fc2973b97ba5e43ee011baee4b7e1018.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://docs/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg"
|
||||
dest_files=["res://.godot/imported/docusaurus-plushie-banner.jpeg-fc2973b97ba5e43ee011baee4b7e1018.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@@ -1,29 +0,0 @@
|
||||
---
|
||||
slug: welcome
|
||||
title: Welcome
|
||||
authors: [slorber, yangshun]
|
||||
tags: [facebook, hello, docusaurus]
|
||||
---
|
||||
|
||||
[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
|
||||
|
||||
Here are a few tips you might find useful.
|
||||
|
||||
<!-- truncate -->
|
||||
|
||||
Simply add Markdown files (or folders) to the `blog` directory.
|
||||
|
||||
Regular blog authors can be added to `authors.yml`.
|
||||
|
||||
The blog post date can be extracted from filenames, such as:
|
||||
|
||||
- `2019-05-30-welcome.md`
|
||||
- `2019-05-30-welcome/index.md`
|
||||
|
||||
A blog post folder can be convenient to co-locate blog post images:
|
||||
|
||||

|
||||
|
||||
The blog supports tags as well!
|
||||
|
||||
**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
|
||||
@@ -1,25 +0,0 @@
|
||||
yangshun:
|
||||
name: Yangshun Tay
|
||||
title: Ex-Meta Staff Engineer, Co-founder GreatFrontEnd
|
||||
url: https://linkedin.com/in/yangshun
|
||||
image_url: https://github.com/yangshun.png
|
||||
page: true
|
||||
socials:
|
||||
x: yangshunz
|
||||
linkedin: yangshun
|
||||
github: yangshun
|
||||
newsletter: https://www.greatfrontend.com
|
||||
|
||||
slorber:
|
||||
name: Sébastien Lorber
|
||||
title: Docusaurus maintainer
|
||||
url: https://sebastienlorber.com
|
||||
image_url: https://github.com/slorber.png
|
||||
page:
|
||||
# customize the url of the author page at /blog/authors/<permalink>
|
||||
permalink: '/all-sebastien-lorber-articles'
|
||||
socials:
|
||||
x: sebastienlorber
|
||||
linkedin: sebastienlorber
|
||||
github: slorber
|
||||
newsletter: https://thisweekinreact.com
|
||||
@@ -1,19 +0,0 @@
|
||||
facebook:
|
||||
label: Facebook
|
||||
permalink: /facebook
|
||||
description: Facebook tag description
|
||||
|
||||
hello:
|
||||
label: Hello
|
||||
permalink: /hello
|
||||
description: Hello tag description
|
||||
|
||||
docusaurus:
|
||||
label: Docusaurus
|
||||
permalink: /docusaurus
|
||||
description: Docusaurus tag description
|
||||
|
||||
hola:
|
||||
label: Hola
|
||||
permalink: /hola
|
||||
description: Hola tag description
|
||||
2757
docs/bun.lock
Normal file
2757
docs/bun.lock
Normal file
File diff suppressed because it is too large
Load Diff
@@ -458,5 +458,14 @@ Gurted provides sensible defaults for all HTML elements:
|
||||
- **Code**: `text-xl font-mono`
|
||||
- **Mark**: `bg-[#FFFF00]` (yellow highlight)
|
||||
- **Small**: `text-xl` (smaller than base)
|
||||
|
||||
And more.
|
||||
- **Pre**: `text-xl font-mono`
|
||||
- **B**: `font-bold`
|
||||
- **I**: `font-italic`
|
||||
- **U**: `underline`
|
||||
- **Images**: `object-fill`
|
||||
- **Select**: `text-[16px] bg-[#1b1b1b] rounded-md text-white hover:bg-[#2a2a2a] active:bg-[#101010] px-3 py-1.5`
|
||||
- **Color input**: `w-32`
|
||||
- **Range input**: Same as above
|
||||
- **Text input**: `text-[16px] w-64`
|
||||
- **Number input**: `w-32 text-[16px] bg-transparent border border-[#000000] rounded-[3px] text-[#000000] hover:border-[3px] hover:border-[#000000] px-3 py-1.5`
|
||||
- **Date input**: `w-28 text-[16px] bg-[#1b1b1b] rounded-md text-white hover:bg-[#2a2a2a] active:bg-[#101010] px-3 py-1.5`
|
||||
|
||||
1267
docs/docs/lua.md
1267
docs/docs/lua.md
File diff suppressed because it is too large
Load Diff
21
docs/docs/lua/audio.md
Normal file
21
docs/docs/lua/audio.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Audio API
|
||||
|
||||
Work with audio elements for sound playback.
|
||||
|
||||
```lua
|
||||
local audio = gurt.select('#my-audio')
|
||||
|
||||
audio:play() -- Start playback
|
||||
audio:pause() -- Pause playback
|
||||
audio:stop() -- Stop and reset
|
||||
|
||||
audio.currentTime = 30.0 -- Seek to 30 seconds
|
||||
audio.volume = 0.8 -- Set volume (0.0 - 1.0)
|
||||
audio.loop = true -- Enable looping
|
||||
audio.src = 'gurt://new-audio.mp3' -- Change source
|
||||
|
||||
local duration = audio.duration
|
||||
local currentPos = audio.currentTime
|
||||
local isPlaying = audio.playing
|
||||
local isPaused = audio.paused
|
||||
```
|
||||
235
docs/docs/lua/canvas.md
Normal file
235
docs/docs/lua/canvas.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# Canvas API
|
||||
|
||||
Gurted features a 2D canvas API similar to HTML5 Canvas, plus shader support.
|
||||
|
||||
## Context
|
||||
|
||||
```lua
|
||||
local canvas = gurt.select('#my-canvas')
|
||||
|
||||
local ctx = canvas:withContext('2d')
|
||||
local shaderCtx = canvas:withContext('shader')
|
||||
```
|
||||
|
||||
## 2D Drawing Context
|
||||
|
||||
### Rectangle
|
||||
|
||||
```lua
|
||||
-- Fill a solid rectangle
|
||||
ctx:fillRect(x, y, width, height, color)
|
||||
ctx:fillRect(50, 50, 100, 75, '#ff0000') -- Red filled rectangle
|
||||
|
||||
-- Draw rectangle outline
|
||||
ctx:strokeRect(x, y, width, height, color, strokeWidth)
|
||||
ctx:strokeRect(200, 50, 100, 75, '#00ff00', 3) -- Green outline, 3px thick
|
||||
|
||||
-- Clear a rectangular area
|
||||
ctx:clearRect(x, y, width, height)
|
||||
ctx:clearRect(80, 80, 40, 40) -- Clear 40x40 area
|
||||
```
|
||||
|
||||
### Circle
|
||||
|
||||
```lua
|
||||
-- Draw filled or outlined circles
|
||||
ctx:drawCircle(x, y, radius, color, filled)
|
||||
ctx:drawCircle(150, 100, 30, '#0000ff', true) -- Filled blue circle
|
||||
ctx:drawCircle(200, 100, 30, '#ff00ff', false) -- Outlined magenta circle
|
||||
```
|
||||
|
||||
### Text
|
||||
|
||||
```lua
|
||||
ctx:drawText(x, y, text, color)
|
||||
ctx:drawText(20, 250, 'Hello Canvas!', '#ffffff')
|
||||
ctx:drawText(20, 280, 'Default Font Only', '#ffff00')
|
||||
|
||||
-- Font size can be set with setFont (size only, not family)
|
||||
ctx:setFont('20px sans-serif') -- Only size matters
|
||||
ctx:drawText(20, 300, 'Larger text', '#00ff00')
|
||||
|
||||
local metrics = ctx:measureText('Sample Text')
|
||||
local textWidth = metrics.width
|
||||
```
|
||||
|
||||
### Path-Based Drawing
|
||||
|
||||
For complex shapes, use path-based drawing methods:
|
||||
|
||||
```lua
|
||||
ctx:beginPath()
|
||||
|
||||
-- Move to starting point without drawing
|
||||
ctx:moveTo(100, 100)
|
||||
|
||||
-- Draw line to point
|
||||
ctx:lineTo(200, 150)
|
||||
ctx:lineTo(150, 200)
|
||||
ctx:lineTo(50, 200)
|
||||
|
||||
-- Close the path (connects back to start)
|
||||
ctx:closePath()
|
||||
|
||||
-- Draw the path
|
||||
ctx:stroke() -- Draw outline
|
||||
-- or
|
||||
ctx:fill() -- Fill the shape
|
||||
```
|
||||
|
||||
### Advanced Path Methods
|
||||
|
||||
#### Arc and Circle Paths
|
||||
|
||||
```lua
|
||||
-- Draw arc (part of circle)
|
||||
ctx:arc(x, y, radius, startAngle, endAngle, counterclockwise)
|
||||
|
||||
-- Example: Draw a quarter circle
|
||||
ctx:beginPath()
|
||||
ctx:arc(200, 200, 50, 0, math.pi/2, false) -- 0 to 90 degrees
|
||||
ctx:stroke()
|
||||
|
||||
-- Full circle path
|
||||
ctx:beginPath()
|
||||
ctx:arc(300, 200, 40, 0, 2 * math.pi, false) -- 0 to 360 degrees
|
||||
ctx:fill()
|
||||
```
|
||||
|
||||
#### Curve Methods
|
||||
|
||||
```lua
|
||||
-- Quadratic curve (one control point)
|
||||
ctx:quadraticCurveTo(controlX, controlY, endX, endY)
|
||||
|
||||
-- Example: Smooth curve
|
||||
ctx:beginPath()
|
||||
ctx:moveTo(50, 300)
|
||||
ctx:quadraticCurveTo(150, 250, 250, 300) -- Control point at (150,250)
|
||||
ctx:stroke()
|
||||
|
||||
-- Bezier curve (two control points)
|
||||
ctx:bezierCurveTo(cp1x, cp1y, cp2x, cp2y, endX, endY)
|
||||
|
||||
-- Example: S-curve
|
||||
ctx:beginPath()
|
||||
ctx:moveTo(50, 350)
|
||||
ctx:bezierCurveTo(100, 300, 200, 400, 250, 350)
|
||||
ctx:stroke()
|
||||
```
|
||||
|
||||
## Styling and Properties
|
||||
|
||||
### Setting Draw Styles
|
||||
|
||||
```lua
|
||||
-- Set stroke (outline) color
|
||||
ctx:setStrokeStyle('#ff0000') -- Red outline
|
||||
ctx:setStrokeStyle('rgba(255, 0, 0, 0.5)') -- Semi-transparent red
|
||||
ctx:setStrokeStyle('red-500') -- Tailwind color names
|
||||
ctx:setStrokeStyle('blue') -- Named colors
|
||||
|
||||
-- Set fill color
|
||||
ctx:setFillStyle('#00ff00') -- Green fill
|
||||
ctx:setFillStyle('#33aa88') -- Teal fill
|
||||
ctx:setFillStyle('slate-800') -- Tailwind colors
|
||||
ctx:setFillStyle('transparent') -- Named transparent
|
||||
|
||||
-- Set line width for strokes
|
||||
ctx:setLineWidth(5) -- 5 pixel wide lines
|
||||
ctx:setLineWidth(0.5) -- Thin lines
|
||||
|
||||
-- Set font for text (size only, not family)
|
||||
ctx:setFont('20px sans-serif') -- Only size matters
|
||||
ctx:setFont('16px Arial') -- Font family ignored
|
||||
ctx:setFont('14px monospace') -- Uses default font at 14px
|
||||
```
|
||||
|
||||
**Color Support**: Canvas color parsing is identical to CSS styling - supports hex colors (`#ff0000`), RGB/RGBA (`rgba(255,0,0,0.5)`), Tailwind color names (`red-500`, `slate-800`), and basic named colors (`red`, `blue`, `transparent`).
|
||||
|
||||
### Using Styles in Drawing
|
||||
|
||||
```lua
|
||||
-- Set up styles first
|
||||
ctx:setFillStyle('#ff6b6b')
|
||||
ctx:setStrokeStyle('#4ecdc4')
|
||||
ctx:setLineWidth(3)
|
||||
|
||||
-- Then draw with those styles
|
||||
ctx:fillRect(50, 50, 100, 100) -- Uses fill style
|
||||
ctx:strokeRect(200, 50, 100, 100) -- Uses stroke style and line width
|
||||
|
||||
-- Styles persist until changed
|
||||
ctx:setFillStyle('#45b7d1')
|
||||
ctx:fillRect(50, 200, 100, 100) -- Now uses blue fill
|
||||
```
|
||||
|
||||
## Transformations
|
||||
|
||||
Canvas transformations allow you to modify the coordinate system for drawing operations.
|
||||
|
||||
### Basic Transformations
|
||||
|
||||
```lua
|
||||
ctx:save()
|
||||
ctx:translate(100, 50)
|
||||
ctx:rotate(math.pi / 4)
|
||||
ctx:scale(2.0, 1.5)
|
||||
ctx:fillRect(0, 0, 50, 50)
|
||||
ctx:restore()
|
||||
ctx:fillRect(0, 0, 50, 50)
|
||||
```
|
||||
|
||||
### Transformation Examples
|
||||
|
||||
```lua
|
||||
ctx:save()
|
||||
ctx:translate(200, 200)
|
||||
ctx:rotate(math.pi / 6)
|
||||
ctx:drawText(-25, 0, 'Rotated', 'Arial', '#000000')
|
||||
ctx:restore()
|
||||
|
||||
for i = 1, 5 do
|
||||
ctx:save()
|
||||
ctx:scale(i * 0.3, i * 0.3)
|
||||
ctx:strokeRect(100, 100, 50, 50)
|
||||
ctx:restore()
|
||||
end
|
||||
|
||||
for angle = 0, 360, 30 do
|
||||
ctx:save()
|
||||
ctx:translate(200, 200)
|
||||
ctx:rotate(math.rad(angle))
|
||||
ctx:fillRect(50, -5, 40, 10)
|
||||
ctx:restore()
|
||||
end
|
||||
```
|
||||
|
||||
## Shader Context
|
||||
|
||||
For advanced visual effects, use the shader context:
|
||||
|
||||
```lua
|
||||
local canvas = gurt.select('#shader-canvas')
|
||||
local shaderCtx = canvas:withContext('shader')
|
||||
|
||||
shaderCtx:source([[
|
||||
shader_type canvas_item;
|
||||
|
||||
uniform float time : hint_range(0.0, 10.0) = 1.0;
|
||||
uniform vec2 resolution;
|
||||
|
||||
void fragment() {
|
||||
vec2 uv = UV;
|
||||
|
||||
// Create animated rainbow effect
|
||||
vec3 color = vec3(
|
||||
0.5 + 0.5 * cos(time + uv.x * 6.0),
|
||||
0.5 + 0.5 * cos(time + uv.y * 6.0 + 2.0),
|
||||
0.5 + 0.5 * cos(time + (uv.x + uv.y) * 6.0 + 4.0)
|
||||
);
|
||||
|
||||
COLOR = vec4(color, 1.0);
|
||||
}
|
||||
]])
|
||||
```
|
||||
315
docs/docs/lua/elements.md
Normal file
315
docs/docs/lua/elements.md
Normal file
@@ -0,0 +1,315 @@
|
||||
# Elements
|
||||
|
||||
Elements returned by `gurt.select()`, `gurt.create()`, etc. have the following properties and methods:
|
||||
|
||||
## Properties
|
||||
|
||||
### element.text
|
||||
|
||||
Gets or sets the text content of an element.
|
||||
|
||||
```lua
|
||||
local p = gurt.select('p')
|
||||
p.text = 'New paragraph content'
|
||||
local currentText = p.text
|
||||
```
|
||||
|
||||
### element.value
|
||||
|
||||
Gets or sets the value of form elements.
|
||||
|
||||
```lua
|
||||
local input = gurt.select('#username')
|
||||
input.value = 'john_doe'
|
||||
local username = input.value
|
||||
|
||||
local checkbox = gurt.select('#agree')
|
||||
checkbox.value = true -- Check the checkbox
|
||||
```
|
||||
|
||||
### element.visible
|
||||
|
||||
Gets or sets element visibility.
|
||||
|
||||
```lua
|
||||
local modal = gurt.select('#modal')
|
||||
modal.visible = false -- Hide element
|
||||
modal.visible = true -- Show element
|
||||
|
||||
if modal.visible then
|
||||
trace.log('Element is visible')
|
||||
end
|
||||
```
|
||||
|
||||
### element.children
|
||||
|
||||
Gets an array of child elements.
|
||||
|
||||
```lua
|
||||
local container = gurt.select('.container')
|
||||
local children = container.children
|
||||
|
||||
for i = 1, #children do
|
||||
local child = children[i]
|
||||
trace.log('Child ' .. i .. ': ' .. child.text)
|
||||
end
|
||||
```
|
||||
|
||||
## DOM Traversal
|
||||
|
||||
### element.parent
|
||||
|
||||
Gets the parent element.
|
||||
|
||||
```lua
|
||||
local button = gurt.select('#my-button')
|
||||
local container = button.parent
|
||||
```
|
||||
|
||||
### element.nextSibling / element.previousSibling
|
||||
|
||||
Gets adjacent sibling elements.
|
||||
|
||||
```lua
|
||||
local current = gurt.select('#current-item')
|
||||
local next = current.nextSibling
|
||||
local prev = current.previousSibling
|
||||
```
|
||||
|
||||
### element.firstChild / element.lastChild
|
||||
|
||||
Gets first or last child element.
|
||||
|
||||
```lua
|
||||
local list = gurt.select('ul')
|
||||
local firstItem = list.firstChild
|
||||
local lastItem = list.lastChild
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
### element:on(eventName, callback)
|
||||
|
||||
Adds an event listener. Returns a subscription object.
|
||||
|
||||
```lua
|
||||
local button = gurt.select('#my-button')
|
||||
|
||||
-- Click event
|
||||
local subscription = button:on('click', function()
|
||||
trace.log('Button clicked!')
|
||||
end)
|
||||
|
||||
-- Mouse events
|
||||
button:on('mouseenter', function()
|
||||
button.classList:add('hover-effect')
|
||||
end)
|
||||
|
||||
button:on('mouseexit', function()
|
||||
button.classList:remove('hover-effect')
|
||||
end)
|
||||
|
||||
-- Input events (for form elements)
|
||||
local input = gurt.select('#username')
|
||||
input:on('change', function(event)
|
||||
trace.log('Input changed to: ' .. event.value)
|
||||
end)
|
||||
|
||||
-- Focus events
|
||||
input:on('focusin', function()
|
||||
trace.log('Input focused')
|
||||
end)
|
||||
|
||||
input:on('focusout', function()
|
||||
trace.log('Input lost focus')
|
||||
end)
|
||||
|
||||
-- Unsubscribe from event
|
||||
subscription:unsubscribe()
|
||||
```
|
||||
|
||||
### element:append(childElement)
|
||||
|
||||
Adds a child element.
|
||||
|
||||
```lua
|
||||
local container = gurt.select('.container')
|
||||
local newDiv = gurt.create('div', { text = 'New content' })
|
||||
container:append(newDiv)
|
||||
```
|
||||
|
||||
### element:remove()
|
||||
|
||||
Removes the element from the DOM.
|
||||
|
||||
```lua
|
||||
local elementToRemove = gurt.select('#temporary')
|
||||
elementToRemove:remove()
|
||||
```
|
||||
|
||||
### element:insertBefore(newElement, referenceElement)
|
||||
|
||||
Inserts an element before another element.
|
||||
|
||||
```lua
|
||||
local container = gurt.select('.container')
|
||||
local newElement = gurt.create('div', { text = 'Inserted' })
|
||||
local reference = gurt.select('#reference')
|
||||
container:insertBefore(newElement, reference)
|
||||
```
|
||||
|
||||
### element:insertAfter(newElement, referenceElement)
|
||||
|
||||
Inserts an element after another element.
|
||||
|
||||
```lua
|
||||
local container = gurt.select('.container')
|
||||
local newElement = gurt.create('div', { text = 'Inserted' })
|
||||
local reference = gurt.select('#reference')
|
||||
container:insertAfter(newElement, reference)
|
||||
```
|
||||
|
||||
### element:replace(oldElement, newElement)
|
||||
|
||||
Replaces a child element with a new element.
|
||||
|
||||
```lua
|
||||
local container = gurt.select('.container')
|
||||
local oldElement = gurt.select('#old')
|
||||
local newElement = gurt.create('div', { text = 'Replacement' })
|
||||
container:replace(oldElement, newElement)
|
||||
```
|
||||
|
||||
### element:clone(deep)
|
||||
|
||||
Creates a copy of the element.
|
||||
|
||||
```lua
|
||||
-- Shallow clone (element only)
|
||||
local copy = element:clone(false)
|
||||
|
||||
-- Deep clone (element and all children)
|
||||
local deepCopy = element:clone(true)
|
||||
```
|
||||
|
||||
### element:getAttribute(name) / element:setAttribute(name, value)
|
||||
|
||||
Gets or sets element attributes.
|
||||
|
||||
```lua
|
||||
local img = gurt.select('img')
|
||||
local src = img:getAttribute('src')
|
||||
img:setAttribute('alt', 'Description text')
|
||||
|
||||
-- Remove attribute by setting empty value
|
||||
img:setAttribute('title', '')
|
||||
```
|
||||
|
||||
### element:show() / element:hide()
|
||||
|
||||
Shows or hides an element.
|
||||
|
||||
```lua
|
||||
local modal = gurt.select('#modal')
|
||||
modal:show() -- Makes element visible
|
||||
modal:hide() -- Hides element
|
||||
```
|
||||
|
||||
### element:focus() / element:unfocus()
|
||||
|
||||
Sets or removes focus from an element.
|
||||
|
||||
```lua
|
||||
local input = gurt.select('#search')
|
||||
input:focus() -- Focus the input
|
||||
input:unfocus() -- Remove focus
|
||||
```
|
||||
|
||||
## Class List Management
|
||||
|
||||
### element.classList
|
||||
|
||||
Provides methods for managing CSS classes.
|
||||
|
||||
```lua
|
||||
local button = gurt.select('#my-button')
|
||||
|
||||
-- Add classes
|
||||
button.classList:add('active')
|
||||
button.classList:add('btn-primary')
|
||||
|
||||
-- Remove classes
|
||||
button.classList:remove('disabled')
|
||||
|
||||
-- Toggle classes
|
||||
button.classList:toggle('selected')
|
||||
|
||||
-- Check if class exists
|
||||
if button.classList:contains('active') then
|
||||
trace.log('Button is active')
|
||||
end
|
||||
|
||||
-- Get specific class by index (1-based)
|
||||
local firstClass = button.classList:item(1)
|
||||
|
||||
-- Get number of classes
|
||||
local classCount = button.classList.length
|
||||
```
|
||||
|
||||
## Animations
|
||||
|
||||
### element:createTween()
|
||||
|
||||
Creates a tween animation for the element.
|
||||
|
||||
```lua
|
||||
local box = gurt.select('#animated-box')
|
||||
|
||||
-- Fade out
|
||||
box:createTween()
|
||||
:to('opacity', 0)
|
||||
:duration(1.0)
|
||||
:easing('out')
|
||||
:transition('linear')
|
||||
:play()
|
||||
|
||||
-- Move and scale
|
||||
box:createTween()
|
||||
:to('x', 200)
|
||||
:to('y', 100)
|
||||
:to('scale', 1.5)
|
||||
:duration(2.0)
|
||||
:easing('inout')
|
||||
:transition('cubic')
|
||||
:play()
|
||||
|
||||
-- Color animation
|
||||
box:createTween()
|
||||
:to('backgroundColor', '#ff0000')
|
||||
:duration(1.5)
|
||||
:easing('out')
|
||||
:transition('quad')
|
||||
:play()
|
||||
|
||||
-- Rotation
|
||||
box:createTween()
|
||||
:to('rotation', 360)
|
||||
:duration(3.0)
|
||||
:easing('inout')
|
||||
:transition('sine')
|
||||
:play()
|
||||
```
|
||||
|
||||
**Available Tween Properties:**
|
||||
- `opacity` - Element transparency (0-1)
|
||||
- `backgroundColor` - Background color (hex format)
|
||||
- `scale` - Element scale (1.0 = normal size)
|
||||
- `rotation` - Rotation in degrees
|
||||
- `x`, `y` - Position offset
|
||||
|
||||
**Easing Types:** `'in'`, `'out'`, `'inout'`, `'outin'`
|
||||
|
||||
**Transition Types:** `'linear'`, `'quad'`, `'cubic'`, `'quart'`, `'quint'`, `'sine'`, `'expo'`, `'circ'`, `'elastic'`, `'back'`, `'bounce'`
|
||||
|
||||

|
||||
Resource: [Reddit](https://www.reddit.com/r/godot/comments/frqzup/godot_tweening_cheat_sheet/)
|
||||
126
docs/docs/lua/handling.md
Normal file
126
docs/docs/lua/handling.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Handlers
|
||||
|
||||
## Event Handling
|
||||
|
||||
### Body Events
|
||||
|
||||
Global events that can be captured on the document body:
|
||||
|
||||
```lua
|
||||
-- Keyboard events
|
||||
gurt.body:on('keydown', function(event)
|
||||
trace.log('Key down: ' .. event.key)
|
||||
if event.ctrl and event.key == 's' then
|
||||
trace.log('Ctrl+S pressed - Save shortcut!')
|
||||
end
|
||||
end)
|
||||
|
||||
gurt.body:on('keyup', function(event)
|
||||
trace.log('Key up: ' .. event.key)
|
||||
end)
|
||||
|
||||
gurt.body:on('keypress', function(event)
|
||||
trace.log('Key pressed: ' .. event.key)
|
||||
-- Event properties: key, keycode, ctrl, shift, alt
|
||||
end)
|
||||
|
||||
-- Mouse events
|
||||
gurt.body:on('mousemove', function(event)
|
||||
trace.log('Mouse at: ' .. event.x .. ', ' .. event.y)
|
||||
-- Event properties: x, y, deltaX, deltaY
|
||||
end)
|
||||
|
||||
gurt.body:on('mouseenter', function()
|
||||
trace.log('Mouse entered page')
|
||||
end)
|
||||
|
||||
gurt.body:on('mouseexit', function()
|
||||
trace.log('Mouse left page')
|
||||
end)
|
||||
```
|
||||
|
||||
### Element Events
|
||||
|
||||
Events specific to DOM elements:
|
||||
|
||||
```lua
|
||||
local button = gurt.select('#my-button')
|
||||
|
||||
-- Mouse events
|
||||
button:on('click', function()
|
||||
trace.log('Button clicked!')
|
||||
end)
|
||||
|
||||
button:on('mousedown', function()
|
||||
trace.log('Mouse button pressed')
|
||||
end)
|
||||
|
||||
button:on('mouseup', function()
|
||||
trace.log('Mouse button released')
|
||||
end)
|
||||
|
||||
button:on('mouseenter', function()
|
||||
trace.log('Mouse entered button')
|
||||
end)
|
||||
|
||||
button:on('mouseexit', function()
|
||||
trace.log('Mouse left button')
|
||||
end)
|
||||
|
||||
button:on('mousemove', function(event)
|
||||
trace.log('Mouse moved over button: ' .. event.x .. ', ' .. event.y)
|
||||
end)
|
||||
|
||||
-- Focus events
|
||||
local input = gurt.select('#text-input')
|
||||
input:on('focusin', function()
|
||||
trace.log('Input gained focus')
|
||||
end)
|
||||
|
||||
input:on('focusout', function()
|
||||
trace.log('Input lost focus')
|
||||
end)
|
||||
|
||||
-- Form events
|
||||
input:on('change', function(event)
|
||||
trace.log('Input value changed to: ' .. event.value)
|
||||
end)
|
||||
|
||||
input:on('input', function(event)
|
||||
trace.log('Input text: ' .. event.value)
|
||||
end)
|
||||
|
||||
-- For file inputs
|
||||
local fileInput = gurt.select('#file-input')
|
||||
fileInput:on('change', function(event)
|
||||
trace.log('File selected: ' .. event.fileName)
|
||||
end)
|
||||
|
||||
-- For form submission
|
||||
local form = gurt.select('#my-form')
|
||||
form:on('submit', function(event)
|
||||
trace.log('Form submitted with data:')
|
||||
for key, value in pairs(event.data) do
|
||||
trace.log(key .. ': ' .. tostring(value))
|
||||
end
|
||||
end)
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### pcall for Protected Calls
|
||||
|
||||
Use Lua's `pcall` for error handling:
|
||||
|
||||
```lua
|
||||
local success, result = pcall(function()
|
||||
local data = JSON.parse('invalid json')
|
||||
return data
|
||||
end)
|
||||
|
||||
if success then
|
||||
trace.log('Parse successful: ' .. tostring(result))
|
||||
else
|
||||
trace.log('Parse failed: ' .. result) -- result contains error message
|
||||
end
|
||||
```
|
||||
306
docs/docs/lua/intro.md
Normal file
306
docs/docs/lua/intro.md
Normal file
@@ -0,0 +1,306 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Intro
|
||||
|
||||
Gurted provides a Lua API that enables dynamic web development with client-side scripting. The Lua runtime is integrated into the browser engine and provides access to DOM manipulation, network requests, animations, and more.
|
||||
|
||||
## Global: gurt
|
||||
|
||||
The main global object for DOM manipulation and core functionality.
|
||||
|
||||
### gurt.select(selector)
|
||||
|
||||
Selects the first element matching the CSS selector.
|
||||
|
||||
```lua
|
||||
local element = gurt.select('#my-id')
|
||||
local firstButton = gurt.select('button')
|
||||
local classElement = gurt.select('.my-class')
|
||||
```
|
||||
|
||||
### gurt.selectAll(selector)
|
||||
|
||||
Selects all elements matching the CSS selector, returns an array.
|
||||
|
||||
```lua
|
||||
local allButtons = gurt.selectAll('button')
|
||||
local listItems = gurt.selectAll('li')
|
||||
|
||||
-- Iterate through results
|
||||
for i = 1, #allButtons do
|
||||
local button = allButtons[i]
|
||||
button.text = 'Button ' .. i
|
||||
end
|
||||
```
|
||||
|
||||
### gurt.create(tagName, options)
|
||||
|
||||
Creates a new HTML element.
|
||||
|
||||
```lua
|
||||
-- Basic element
|
||||
local div = gurt.create('div')
|
||||
|
||||
-- Element with attributes and content
|
||||
local button = gurt.create('button', {
|
||||
text = 'Click me!',
|
||||
style = 'bg-blue-500 text-white px-4 py-2 rounded',
|
||||
id = 'my-button'
|
||||
})
|
||||
```
|
||||
|
||||
### gurt.body
|
||||
|
||||
Reference to the document body element.
|
||||
|
||||
```lua
|
||||
-- Add event listeners to body
|
||||
gurt.body:on('keydown', function(event)
|
||||
trace.log('Key pressed: ' .. event.key)
|
||||
end)
|
||||
|
||||
-- Append elements to body
|
||||
local newDiv = gurt.create('div', { text = 'Hello World!' })
|
||||
gurt.body:append(newDiv)
|
||||
```
|
||||
|
||||
### gurt.location
|
||||
|
||||
Browser location and navigation control.
|
||||
|
||||
### gurt.location.href
|
||||
|
||||
Gets the current URL.
|
||||
|
||||
```lua
|
||||
local currentUrl = gurt.location.href
|
||||
trace.log('Current URL: ' .. currentUrl)
|
||||
```
|
||||
|
||||
### gurt.location.reload()
|
||||
|
||||
Reloads the current page.
|
||||
|
||||
```lua
|
||||
gurt.location.reload()
|
||||
```
|
||||
|
||||
### gurt.location.goto(url)
|
||||
|
||||
Navigates to a new URL.
|
||||
|
||||
```lua
|
||||
gurt.location.goto('gurt://example.com/page')
|
||||
gurt.location.goto('https://external-site.com')
|
||||
```
|
||||
|
||||
### gurt.location.query
|
||||
|
||||
Query parameter access.
|
||||
|
||||
```lua
|
||||
-- Get a specific parameter
|
||||
local userId = gurt.location.query.get('user_id')
|
||||
|
||||
-- Check if parameter exists
|
||||
if gurt.location.query.has('debug') then
|
||||
trace.log('Debug mode enabled')
|
||||
end
|
||||
|
||||
-- Get all values for a parameter (for repeated params)
|
||||
local tags = gurt.location.query.getAll('tag')
|
||||
```
|
||||
## Global: trace
|
||||
|
||||
The global trace table for logging messages to the console.
|
||||
|
||||
### trace.log(message)
|
||||
Identical to `print()`, logs a message to the console.
|
||||
|
||||
```lua
|
||||
trace.log('Hello from Lua!')
|
||||
```
|
||||
|
||||
### trace.warn(message)
|
||||
Logs a warning message to the console.
|
||||
|
||||
```lua
|
||||
trace.warn('This is a warning!')
|
||||
```
|
||||
|
||||
### trace.error(message)
|
||||
Logs an error message to the console.
|
||||
|
||||
```lua
|
||||
trace.error('This is an error!')
|
||||
```
|
||||
|
||||
## Time API
|
||||
|
||||
### Time.now()
|
||||
|
||||
Gets current Unix timestamp.
|
||||
|
||||
```lua
|
||||
local timestamp = Time.now()
|
||||
trace.log('Current time: ' .. timestamp)
|
||||
```
|
||||
|
||||
### Time.format(timestamp, format)
|
||||
|
||||
Formats a timestamp using format strings.
|
||||
|
||||
```lua
|
||||
local now = Time.now()
|
||||
local formatted = Time.format(now, '%Y-%m-%d %H:%M:%S')
|
||||
trace.log('Formatted: ' .. formatted)
|
||||
|
||||
-- Format strings
|
||||
-- %Y - Full year (2024)
|
||||
-- %y - Two-digit year (24)
|
||||
-- %m - Month (01-12)
|
||||
-- %d - Day (01-31)
|
||||
-- %H - Hour 24-format (00-23)
|
||||
-- %I - Hour 12-format (01-12)
|
||||
-- %M - Minute (00-59)
|
||||
-- %S - Second (00-59)
|
||||
-- %p - AM/PM
|
||||
-- %A - Full weekday name
|
||||
-- %a - Abbreviated weekday name
|
||||
-- %B - Full month name
|
||||
-- %b - Abbreviated month name
|
||||
```
|
||||
|
||||
### Time.date(timestamp)
|
||||
|
||||
Gets date components as a table.
|
||||
|
||||
```lua
|
||||
local now = Time.now()
|
||||
local date = Time.date(now)
|
||||
|
||||
trace.log('Year: ' .. date.year)
|
||||
trace.log('Month: ' .. date.month)
|
||||
trace.log('Day: ' .. date.day)
|
||||
trace.log('Hour: ' .. date.hour)
|
||||
trace.log('Minute: ' .. date.minute)
|
||||
trace.log('Second: ' .. date.second)
|
||||
trace.log('Weekday: ' .. date.weekday) -- 0=Sunday, 6=Saturday
|
||||
```
|
||||
|
||||
### Time.sleep(seconds)
|
||||
|
||||
Pauses execution for a specified duration.
|
||||
|
||||
```lua
|
||||
trace.log('Starting...')
|
||||
Time.sleep(2.0) -- Wait 2 seconds
|
||||
trace.log('Done waiting!')
|
||||
```
|
||||
|
||||
:::note
|
||||
This blocks the entire Lua thread. Use with caution, we recommend using `setTimeout()` for non-blocking delays.
|
||||
:::
|
||||
|
||||
### Time.benchmark(function)
|
||||
|
||||
Measures function execution time.
|
||||
|
||||
```lua
|
||||
local elapsed, result = Time.benchmark(function()
|
||||
-- Some complex calculation
|
||||
local sum = 0
|
||||
for i = 1, 1000000 do
|
||||
sum = sum + i
|
||||
end
|
||||
return sum
|
||||
end)
|
||||
|
||||
trace.log('Function took ' .. elapsed .. ' seconds')
|
||||
trace.log('Result: ' .. result)
|
||||
```
|
||||
|
||||
### Time.timer()
|
||||
|
||||
Creates a timer object for measuring intervals.
|
||||
|
||||
```lua
|
||||
local timer = Time.timer()
|
||||
|
||||
-- Do some work...
|
||||
Time.sleep(1.5)
|
||||
|
||||
local elapsed = timer:elapsed()
|
||||
trace.log('Elapsed: ' .. elapsed .. ' seconds')
|
||||
|
||||
timer:reset() -- Reset timer
|
||||
```
|
||||
|
||||
### Time.delay(seconds)
|
||||
|
||||
Creates a delay object for non-blocking waits.
|
||||
|
||||
```lua
|
||||
local delay = Time.delay(3.0)
|
||||
|
||||
-- Check if delay is complete
|
||||
if delay:complete() then
|
||||
trace.log('Delay finished!')
|
||||
end
|
||||
|
||||
-- Get remaining time
|
||||
local remaining = delay:remaining()
|
||||
trace.log('Time left: ' .. remaining .. ' seconds')
|
||||
```
|
||||
|
||||
## Timeout and Interval Functions
|
||||
|
||||
### setTimeout(callback, milliseconds)
|
||||
|
||||
Executes a function after a delay.
|
||||
|
||||
```lua
|
||||
local timeoutId = setTimeout(function()
|
||||
trace.log('This runs after 2 seconds')
|
||||
end, 2000)
|
||||
|
||||
-- Cancel the timeout
|
||||
-- clearTimeout(timeoutId)
|
||||
```
|
||||
|
||||
### setInterval(callback, milliseconds)
|
||||
|
||||
Executes a function repeatedly at intervals.
|
||||
|
||||
```lua
|
||||
local intervalId = setInterval(function()
|
||||
trace.log('This runs every second')
|
||||
end, 1000)
|
||||
|
||||
setTimeout(function()
|
||||
clearInterval(intervalId)
|
||||
trace.log('Interval stopped')
|
||||
end, 5000)
|
||||
```
|
||||
|
||||
### clearTimeout(timeoutId) / clearInterval(intervalId)
|
||||
|
||||
Cancels scheduled timeouts or intervals.
|
||||
|
||||
```lua
|
||||
local id = setTimeout(function()
|
||||
trace.log('This will not run')
|
||||
end, 1000)
|
||||
|
||||
clearTimeout(id)
|
||||
```
|
||||
|
||||
## Clipboard API
|
||||
|
||||
Write to the system clipboard.
|
||||
|
||||
```lua
|
||||
Clipboard.write('Hello clipboard!')
|
||||
```
|
||||
154
docs/docs/lua/network.md
Normal file
154
docs/docs/lua/network.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Network API
|
||||
|
||||
### Fetch
|
||||
|
||||
#### fetch(url, options)
|
||||
|
||||
Makes HTTP requests with full control over method, headers, and body.
|
||||
|
||||
```lua
|
||||
-- Simple GET request
|
||||
local response = fetch('https://api.example.com/data')
|
||||
|
||||
-- POST request with data
|
||||
local response = fetch('https://api.example.com/users', {
|
||||
method = 'POST',
|
||||
headers = {
|
||||
['Content-Type'] = 'application/json',
|
||||
['Authorization'] = 'Bearer token123'
|
||||
},
|
||||
body = JSON.stringify({
|
||||
name = 'John Doe',
|
||||
email = 'john@example.com'
|
||||
})
|
||||
})
|
||||
|
||||
-- Check response
|
||||
if response:ok() then
|
||||
local data = response:json() -- Parse JSON response
|
||||
local text = response:text() -- Get as text
|
||||
|
||||
trace.log('Status: ' .. response.status)
|
||||
trace.log('Status Text: ' .. response.statusText)
|
||||
|
||||
-- Access headers
|
||||
local contentType = response.headers['content-type']
|
||||
else
|
||||
trace.log('Request failed with status: ' .. response.status)
|
||||
end
|
||||
```
|
||||
|
||||
**Supported Methods:** `GET`, `POST`, `PUT`, `DELETE`, `HEAD`, `OPTIONS`, `PATCH`
|
||||
|
||||
**Relative URLs** are automatically resolved to the current domain with `gurt://` protocol.
|
||||
|
||||
## WebSocket API
|
||||
|
||||
Real-time communication with WebSocket servers.
|
||||
|
||||
```lua
|
||||
local ws = WebSocket.new('ws://localhost:8080/chat')
|
||||
|
||||
ws:on('open', function()
|
||||
trace.log('WebSocket connected')
|
||||
ws:send('Hello server!')
|
||||
end)
|
||||
|
||||
ws:on('message', function(data)
|
||||
trace.log('Received: ' .. data)
|
||||
end)
|
||||
|
||||
ws:on('close', function(code, reason)
|
||||
trace.log('WebSocket closed: ' .. code .. ' - ' .. reason)
|
||||
end)
|
||||
|
||||
ws:on('error', function(error)
|
||||
trace.log('WebSocket error: ' .. error)
|
||||
end)
|
||||
|
||||
ws:send('Hello from client!')
|
||||
ws:send(JSON.stringify({ type = 'chat', message = 'Hello!' }))
|
||||
|
||||
ws:close()
|
||||
|
||||
if ws.readyState == WebSocket.OPEN then
|
||||
ws:send('Connected message')
|
||||
end
|
||||
```
|
||||
|
||||
**WebSocket States:**
|
||||
- `WebSocket.CONNECTING` (0) - Connection in progress
|
||||
- `WebSocket.OPEN` (1) - Connection established
|
||||
- `WebSocket.CLOSING` (2) - Connection closing
|
||||
- `WebSocket.CLOSED` (3) - Connection closed
|
||||
|
||||
## URL API
|
||||
|
||||
URL encoding and decoding utilities for handling special characters in URLs.
|
||||
|
||||
### urlEncode(string)
|
||||
|
||||
Encodes a string for safe use in URLs by converting special characters to percent-encoded format.
|
||||
|
||||
```lua
|
||||
local encoded = urlEncode('hello world!')
|
||||
trace.log(encoded) -- hello%20world%21
|
||||
|
||||
local params = urlEncode('name=John Doe&age=30')
|
||||
trace.log(params) -- name%3DJohn%20Doe%26age%3D30
|
||||
|
||||
-- Building query strings
|
||||
local searchTerm = 'cats & dogs'
|
||||
local url = 'gurt://search.com/api?q=' .. urlEncode(searchTerm)
|
||||
trace.log(url) -- gurt://search.com/api?q=cats%20%26%20dogs
|
||||
```
|
||||
|
||||
### urlDecode(string)
|
||||
|
||||
Decodes a percent-encoded URL string back to its original form.
|
||||
|
||||
```lua
|
||||
local decoded = urlDecode('hello%20world%21')
|
||||
trace.log(decoded) -- hello world!
|
||||
|
||||
local params = urlDecode('name%3DJohn%20Doe%26age%3D30')
|
||||
trace.log(params) -- name=John Doe&age=30
|
||||
|
||||
local queryParam = 'cats%20%26%20dogs'
|
||||
local searchTerm = urlDecode(queryParam)
|
||||
trace.log(searchTerm) -- cats & dogs
|
||||
```
|
||||
|
||||
## JSON API
|
||||
|
||||
### JSON.stringify(data)
|
||||
|
||||
Converts Lua data to JSON string.
|
||||
|
||||
```lua
|
||||
local data = {
|
||||
name = 'Alice',
|
||||
age = 30,
|
||||
hobbies = {'reading', 'coding'},
|
||||
active = true
|
||||
}
|
||||
|
||||
local jsonString = JSON.stringify(data)
|
||||
trace.log(jsonString) -- {"name":"Alice","age":30,"hobbies":["reading","coding"],"active":true}
|
||||
```
|
||||
|
||||
### JSON.parse(jsonString)
|
||||
|
||||
Parses JSON string to Lua data.
|
||||
|
||||
```lua
|
||||
local jsonString = '{"name":"Bob","score":95.5}'
|
||||
local data, error = JSON.parse(jsonString)
|
||||
|
||||
if data then
|
||||
trace.log('Name: ' .. data.name)
|
||||
trace.log('Score: ' .. data.score)
|
||||
else
|
||||
trace.log('Parse error: ' .. error)
|
||||
end
|
||||
```
|
||||
46
docs/docs/lua/regex.md
Normal file
46
docs/docs/lua/regex.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Regex API
|
||||
|
||||
Pattern matching and text processing with regular expressions.
|
||||
|
||||
## Regex.new(pattern)
|
||||
|
||||
Creates a new regex object from a pattern string.
|
||||
|
||||
```lua
|
||||
local emailPattern = Regex.new('[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]+')
|
||||
local phonePattern = Regex.new('\\(\\d{3}\\)\\s*\\d{3}-\\d{4}')
|
||||
```
|
||||
|
||||
## regex:test(text)
|
||||
|
||||
Tests if the pattern matches anywhere in the text. Returns `true` or `false`.
|
||||
|
||||
```lua
|
||||
local pattern = Regex.new('[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]+')
|
||||
|
||||
if pattern:test('user@example.com') then
|
||||
trace.log('Valid email format')
|
||||
end
|
||||
|
||||
if pattern:test('Contact us at admin@site.com') then
|
||||
trace.log('Found email in text')
|
||||
end
|
||||
```
|
||||
|
||||
## regex:match(text)
|
||||
|
||||
Finds the first match and returns capture groups as an array, or `nil` if no match found.
|
||||
|
||||
```lua
|
||||
local pattern = Regex.new('(\\w+)@(\\w+)\\.(\\w+)')
|
||||
local result = pattern:match('Contact: admin@site.com for help')
|
||||
|
||||
if result then
|
||||
trace.log('Full match: ' .. result[1]) -- admin@site.com
|
||||
trace.log('Username: ' .. result[2]) -- admin
|
||||
trace.log('Domain: ' .. result[3]) -- site
|
||||
trace.log('TLD: ' .. result[4]) -- com
|
||||
else
|
||||
trace.log('No match found')
|
||||
end
|
||||
```
|
||||
61
docs/docs/lua/utils.md
Normal file
61
docs/docs/lua/utils.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Additional utilities
|
||||
|
||||
Gurted includes several helpful utilities:
|
||||
|
||||
### print(...)
|
||||
We modify the global `print()` function to log to the browser console, and also convert any type (e.g. tables) to a readable string.
|
||||
|
||||
```lua
|
||||
print('Hello, world!')
|
||||
print({ name = 'Alice', age = 30, hobbies = {'reading', 'coding'} }) -- {age=30,hobbies={1="reading",2="coding"},name="Alice"}
|
||||
```
|
||||
|
||||
### table.tostring(table)
|
||||
|
||||
Converts a table to a readable string representation.
|
||||
|
||||
```lua
|
||||
local data = { name = 'John', age = 30, hobbies = {'reading', 'coding'} }
|
||||
local str = table.tostring(data) -- {age=30,hobbies={1="reading",2="coding"},name="John"}
|
||||
```
|
||||
|
||||
### string.replace(text, search, replacement)
|
||||
|
||||
Replaces the first occurrence of a string or regex pattern.
|
||||
|
||||
```lua
|
||||
local text = 'Hello world, hello universe'
|
||||
local result = string.replace(text, 'hello', 'hi')
|
||||
trace.log(result) -- Hello world, hi universe
|
||||
|
||||
local pattern = Regex.new('\\b\\w+@\\w+\\.\\w+\\b')
|
||||
local masked = string.replace('Email: john@test.com', pattern, '[EMAIL]')
|
||||
trace.log(masked) -- Email: [EMAIL]
|
||||
```
|
||||
|
||||
### string.replaceAll(text, search, replacement)
|
||||
|
||||
Replaces all occurrences of a string or regex pattern.
|
||||
|
||||
```lua
|
||||
local text = 'Hello world, hello universe'
|
||||
local result = string.replaceAll(text, 'hello', 'hi')
|
||||
trace.log(result) -- Hello world, hi universe
|
||||
|
||||
local pattern = Regex.new('\\b\\w+@\\w+\\.\\w+\\b')
|
||||
local text = 'Emails: john@test.com, jane@demo.org'
|
||||
local masked = string.replaceAll(text, pattern, '[EMAIL]')
|
||||
trace.log(masked) -- Emails: [EMAIL], [EMAIL]
|
||||
```
|
||||
|
||||
### string.trim(text)
|
||||
|
||||
Removes whitespace from the beginning and end of a string.
|
||||
|
||||
```lua
|
||||
local messy = ' Hello World '
|
||||
local clean = string.trim(messy)
|
||||
trace.log('"' .. clean .. '"') -- "Hello World"
|
||||
```
|
||||
|
||||
This is particularly useful for debugging and logging complex data structures.
|
||||
@@ -89,9 +89,8 @@ const config: Config = {
|
||||
position: 'left',
|
||||
label: 'Tutorial',
|
||||
},
|
||||
{to: '/blog', label: 'Blog', position: 'left'},
|
||||
{
|
||||
href: 'https://github.com/facebook/docusaurus',
|
||||
href: 'https://github.com/outpoot/gurted',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
|
||||
@@ -39,7 +39,21 @@ const sidebars: SidebarsConfig = {
|
||||
items: [
|
||||
'html',
|
||||
'css',
|
||||
'lua',
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Lua',
|
||||
items: [
|
||||
'lua/intro',
|
||||
'lua/elements',
|
||||
'lua/audio',
|
||||
'lua/canvas',
|
||||
'lua/network',
|
||||
'lua/regex',
|
||||
'lua/handling',
|
||||
'lua/utils'
|
||||
|
||||
],
|
||||
},
|
||||
'postprocess',
|
||||
],
|
||||
},
|
||||
|
||||
4
flumi/README.md
Normal file
4
flumi/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Flumi
|
||||
|
||||
The official wayfinder, written in godot.
|
||||
For more informations check out the [Gurted Documentation](https://docs.gurted.com).
|
||||
Binary file not shown.
41
flumi/export_presets.cfg
Normal file
41
flumi/export_presets.cfg
Normal file
@@ -0,0 +1,41 @@
|
||||
[preset.0]
|
||||
|
||||
name="Linux"
|
||||
platform="Linux"
|
||||
runnable=true
|
||||
advanced_options=false
|
||||
dedicated_server=false
|
||||
custom_features=""
|
||||
export_filter="all_resources"
|
||||
include_filter=""
|
||||
exclude_filter=""
|
||||
export_path="../../../Flumi.x86_64"
|
||||
patches=PackedStringArray()
|
||||
encryption_include_filters=""
|
||||
encryption_exclude_filters=""
|
||||
seed=0
|
||||
encrypt_pck=false
|
||||
encrypt_directory=false
|
||||
script_export_mode=2
|
||||
|
||||
[preset.0.options]
|
||||
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
debug/export_console_wrapper=1
|
||||
binary_format/embed_pck=false
|
||||
texture_format/s3tc_bptc=true
|
||||
texture_format/etc2_astc=false
|
||||
binary_format/architecture="x86_64"
|
||||
ssh_remote_deploy/enabled=false
|
||||
ssh_remote_deploy/host="user@host_ip"
|
||||
ssh_remote_deploy/port="22"
|
||||
ssh_remote_deploy/extra_args_ssh=""
|
||||
ssh_remote_deploy/extra_args_scp=""
|
||||
ssh_remote_deploy/run_script="#!/usr/bin/env bash
|
||||
export DISPLAY=:0
|
||||
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
|
||||
\"{temp_dir}/{exe_name}\" {cmd_args}"
|
||||
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
|
||||
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
|
||||
rm -rf \"{temp_dir}\""
|
||||
BIN
images/flumi.png
Normal file
BIN
images/flumi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
@@ -1,7 +1,7 @@
|
||||
The implementation of the GURT protocol.
|
||||
|
||||
- [cli](./cli) - Gurty, the command-line tool for managing GURT servers
|
||||
- [library](./library) - client/server GURT protocol library for Rust (the core, used in Flumi)
|
||||
- [gdextension](./gdextension) - the Godot bindings for the GURT protocol (used in Flumi)
|
||||
- [Cli](./cli) - Gurty, the command-line tool for managing GURT servers
|
||||
- [Library](./library) - client/server GURT protocol library for Rust (the core, used in Flumi)
|
||||
- [Gdextension](./gdextension) - the Godot bindings for the GURT protocol (used in Flumi)
|
||||
|
||||
For the full spec, see the [Gurted Documentation](https://docs.gurted.com).
|
||||
For the full spec, check the [Gurted Documentation](https://docs.gurted.com).
|
||||
@@ -1,5 +1,75 @@
|
||||
The official Gurted search engine, Ringle.
|
||||
# Ringle
|
||||
|
||||
Copy `config.template.toml` to `config.toml` and edit as needed.
|
||||
The official Gurted search engine.
|
||||
|
||||
Run with `cargo run`
|
||||
## Configuration
|
||||
```sh
|
||||
cp config.template.toml config.toml
|
||||
```
|
||||
### Values
|
||||
```toml
|
||||
[database]
|
||||
url = "postgres://..." # A valid postgres database url
|
||||
max_connections = 5 # The maximum amount of simultaneous connections to the database
|
||||
```
|
||||
```toml
|
||||
[server]
|
||||
address = "127.0.0.1" # The binding adress the server will listen to
|
||||
port = 4879 # The port the server will listen on
|
||||
cert_path = "certs/t.crt" # A path to the certificate
|
||||
key_path = "certs/t.key" # A path to the key for the certificate
|
||||
```
|
||||
|
||||
```toml
|
||||
[search]
|
||||
index_path = "./search_indexes" # The path where the indexed pages will be saved to
|
||||
crawl_interval_hours = 2 # How frequently should the search engine crawl (in hours)
|
||||
max_pages_per_domain = 1000 # Maximum amount of pages indexed per domain
|
||||
crawler_timeout_seconds = 30 # The maximum amount of seconds before a page times out and is skipped
|
||||
crawler_user_agent = "RingleBot/1.0" # The user agent the crawler should use
|
||||
max_concurrent_crawls = 5 # How many pages should the bot crawl concurrently
|
||||
content_size_limit_mb = 10 # The maximum amount of data a page can be
|
||||
index_rebuild_interval_hours = 48 # How often (in hours) should the index be rebuilt
|
||||
search_results_per_page = 20 # How many search results should be displayed per page
|
||||
max_search_results = 1000 # The maximum amount of results displayed
|
||||
|
||||
allowed_extensions = [ # Extensions allowed to be indexed
|
||||
"html", "htm", "txt", "md", "json", "xml", "rss", "atom"
|
||||
]
|
||||
|
||||
blocked_extensions = [ # Extension that should not be indexed
|
||||
"exe", "zip", "rar", "tar", "gz", "7z", "iso", "dmg",
|
||||
"pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx",
|
||||
"jpg", "jpeg", "png", "gif", "bmp", "svg", "webp",
|
||||
"mp3", "mp4", "avi", "mov", "wmv", "flv", "webm",
|
||||
"css", "js", "woff", "woff2", "ttf", "eot"
|
||||
]
|
||||
```
|
||||
|
||||
```toml
|
||||
[crawler]
|
||||
clanker_txt = true # Wheter or not should the crawler respect clanker.txt
|
||||
crawl_delay_ms = 1000 # The delay between each page crawl
|
||||
max_redirects = 5 # The maximum amount of redirects the crawler shoul follow
|
||||
follow_external_links = false # Crawl external links found in the page?
|
||||
max_depth = 10 # The maximum amount of nested pages
|
||||
|
||||
request_headers = [ # The headers the crawler will include in the request while crawling
|
||||
["Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],
|
||||
["Accept-Language", "en-US,en;q=0.5"],
|
||||
["Accept-Encoding", "gzip, deflate"],
|
||||
["DNT", "1"],
|
||||
]
|
||||
```
|
||||
|
||||
```toml
|
||||
[logging]
|
||||
level = "info" # How much should the search engine log, can be info, debug or trace
|
||||
format = "compact" # The format for the logs
|
||||
```
|
||||
|
||||
## Running
|
||||
Run with:
|
||||
```sh
|
||||
cargo run
|
||||
```
|
||||
@@ -13,7 +13,7 @@ index_path = "./search_indexes"
|
||||
crawl_interval_hours = 2
|
||||
max_pages_per_domain = 1000
|
||||
crawler_timeout_seconds = 30
|
||||
crawler_user_agent = "GurtedSearchBot/1.0"
|
||||
crawler_user_agent = "RingleBot/1.0"
|
||||
max_concurrent_crawls = 5
|
||||
content_size_limit_mb = 10
|
||||
index_rebuild_interval_hours = 48
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
# sv
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```sh
|
||||
# create a new project in the current directory
|
||||
npx sv create
|
||||
|
||||
# create a new project in my-app
|
||||
npx sv create my-app
|
||||
```
|
||||
# Gurted documentation
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
Once you've installed the required dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
@@ -27,12 +13,10 @@ npm run dev -- --open
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
To create a production version of the documentation page:
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
||||
|
||||
Reference in New Issue
Block a user