General documentation improvements

This commit is contained in:
creeperita09
2025-09-08 13:13:38 +02:00
parent f4fd000322
commit e71fdc70d1
33 changed files with 4232 additions and 1551 deletions

3
.gitignore vendored
View File

@@ -1,6 +1,7 @@
target/
*target*
*.pem
gurty.toml
certs
search_indexes
config.toml
.vscode

View File

@@ -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.
![Preview of Flumi, the official gurted wayfinder](https://raw.githubusercontent.com/outpoot/gurted/master/images/flumi.png)
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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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:
![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg)
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.

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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`

File diff suppressed because it is too large Load Diff

21
docs/docs/lua/audio.md Normal file
View 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
View 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
View 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'`
![CRT effect](../../static/img/docs/tween.png)
Resource: [Reddit](https://www.reddit.com/r/godot/comments/frqzup/godot_tweening_cheat_sheet/)

126
docs/docs/lua/handling.md Normal file
View 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
View 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
View 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
View 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
View 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.

View File

@@ -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',
},

View File

@@ -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
View File

@@ -0,0 +1,4 @@
# Flumi
The official wayfinder, written in godot.
For more informations check out the [Gurted Documentation](https://docs.gurted.com).

41
flumi/export_presets.cfg Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -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).

View File

@@ -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
```

View File

@@ -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

View File

@@ -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.