move tests to dedicated folder

This commit is contained in:
Face
2025-08-15 14:55:23 +03:00
parent 605bfb516f
commit 3578dc7334
21 changed files with 2838 additions and 2876 deletions

105
dns/frontend/index.html Normal file
View File

@@ -0,0 +1,105 @@
<head>
<title>Login</title>
<icon src="https://cdn-icons-png.flaticon.com/512/295/295128.png">
<meta name="theme-color" content="#1b1b1b">
<meta name="description" content="Login to your account">
<font name="roboto" src="https://fonts.gstatic.com/s/roboto/v48/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2" />
<style>
body { bg-[#1b1b1b] text-[#ffffff] font-roboto flex items-center justify-center p-4 }
.login-card { bg-[#2a2a2a] rounded-lg p-8 shadow-2xl mx-0 }
h1 { text-3xl font-bold text-center mb-6 text-[#ffffff] }
input {
bg-[#3b3b3b]
border-none
rounded-md
p-3
w-full
text-[#ffffff]
placeholder:text-[#999999]
outline-none
focus:ring-2
focus:ring-[#5b5b5b]
mb-4
}
button {
bg-[#4ade80]
text-[#1b1b1b]
font-bold
p-3
rounded-md
w-full
hover:bg-[#22c55e]
active:bg-[#15803d]
cursor-pointer
}
a { text-[#4ade80] hover:text-[#22c55e] cursor-pointer }
#log-output { text-white p-4 rounded-md mt-4 font-mono max-h-40 }
</style>
<script>
local submitBtn = gurt.select('#submit')
local username_input = gurt.select('#username')
local password_input = gurt.select('#password')
local log_output = gurt.select('#log-output')
function addLog(message)
gurt.log(message)
log_output.text = log_output.text .. message .. '\\n'
end
submitBtn:on('submit', function(event)
local username = event.data.username
local password = event.data.password
local request_body = JSON.stringify({
username = username,
password = password
})
print(request_body)
local url = 'http://localhost:8080/auth/login'
local headers = {
['Content-Type'] = 'application/json'
}
addLog('Attempting to log in with username: ' .. username)
log_output.text = ''
local response = fetch(url, {
method = 'POST',
headers = headers,
body = request_body
})
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
if response:ok() then
addLog('Login successful!')
local jsonData = response:json()
if jsonData then
addLog('Logged in as user: ' .. jsonData.user.username)
addLog('Token: ' .. jsonData.token:sub(1, 20) .. '...')
end
else
addLog('Request failed with status: ' .. response.status)
local error_data = response:text()
addLog('Error response: ' .. error_data)
end
end)
</script>
</head>
<body>
<div style="login-card">
<h1>Login</h1>
<form id="login-form">
<input id="username" type="text" placeholder="Username" required="true" />
<input id="password" type="password" placeholder="Password" required="true" />
<button type="submit" id="submit">Log In</button>
</form>
<p style="text-center mt-4 text-[#999999] text-base">Don't have an account? <a href="#">Register here</a></p>
<p id="log-output" style="min-h-24"></p>
</div>
</body>

0
dns/frontend/style.css Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
<head>
<title>Lua List Manipulation Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#000080">
<meta name="description" content="Adding and popping list items with GURT Lua API">
<style>
body { bg-[#f8f9fa] p-6 }
h1 { text-[#2563eb] text-4xl font-bold }
.container { flex flex-row bg-[#ffffff] p-4 rounded-lg shadow-lg }
.demo-button { bg-[#3b82f6] text-white px-4 py-2 rounded hover:bg-[#2563eb] cursor-pointer }
ul { list-disc pl-6 }
li { text-[#111827] py-1 }
</style>
<script>
local add_button = gurt.select('#add-button')
local pop_button = gurt.select('#pop-button')
local list = gurt.select('#item-list')
local counter = 1
gurt.log('List manipulation script started.')
add_button:on('click', function()
local new_item = gurt.create('li', {
text = 'Item #' .. counter
})
list:append(new_item)
counter = counter + 1
end)
pop_button:on('click', function()
local items = list.children
local last = items[#items]
if last then
last:remove()
counter = math.max(1, counter - 1)
end
end)
</script>
</head>
<body>
<h1 id="main-heading">List Manipulation with Lua</h1>
<div style="container">
<p>Use the buttons below to add or remove items from the list:</p>
<button id="add-button" style="demo-button inline-block mr-2">Add Item</button>
<button id="pop-button" style="demo-button inline-block">Pop Item</button>
</div>
<ul id="item-list" style="mt-4 bg-[#f3f4f6] p-4 rounded min-h-24">
<!-- List items will appear here -->
</ul>
</body>

184
tests/attribute.html Normal file
View File

@@ -0,0 +1,184 @@
<head>
<title>Button getAttribute/setAttribute Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#3b82f6">
<meta name="description" content="Demonstrating getAttribute and setAttribute with button controls">
<style>
body { bg-[#f8fafc] p-6 }
h1 { text-[#3b82f6] text-3xl font-bold text-center }
h2 { text-[#1e40af] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.control-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors }
.enable-btn { bg-[#10b981] text-white hover:bg-[#059669] }
.disable-btn { bg-[#ef4444] text-white hover:bg-[#dc2626] }
.toggle-btn { bg-[#8b5cf6] text-white hover:bg-[#7c3aed] }
.status-btn { bg-[#6b7280] text-white hover:bg-[#4b5563] }
.demo-buttons { bg-[#f1f5f9] p-4 rounded-lg }
.status-display { bg-[#e0e7ff] p-3 rounded-md text-[#3730a3] font-mono }
.info-box { bg-[#fef3c7] border border-[#f59e0b] p-4 rounded-lg }
.target-button { bg-[#3b82f6] text-white px-6 py-3 rounded-lg font-semibold hover:bg-[#2563eb] }
.target-button[disabled] { bg-[#9ca3af] text-[#6b7280] cursor-not-allowed }
</style>
<script>
local targetButton = gurt.select('#target-button')
local enableBtn = gurt.select('#enable-btn')
local disableBtn = gurt.select('#disable-btn')
local toggleBtn = gurt.select('#toggle-btn')
local statusBtn = gurt.select('#status-btn')
local statusDisplay = gurt.select('#status-display')
local infoBox = gurt.select('#info-box')
local clickCounter = gurt.select('#click-counter')
gurt.log('Button attribute demo script started.')
local clickCount = 0
-- Function to update the status display
local function updateStatus()
local disabled = targetButton:getAttribute('disabled')
local type = targetButton:getAttribute('type')
local style = targetButton:getAttribute('style')
local id = targetButton:getAttribute('id')
local dataValue = targetButton:getAttribute('data-value')
local status = 'Status: ' .. (disabled and 'DISABLED' or 'ENABLED') .. '\\n'
status = status .. 'Type: ' .. (type or 'button') .. '\\n'
status = status .. 'ID: ' .. (id or 'none') .. '\\n'
status = status .. 'Data Value: ' .. (dataValue or 'none') .. '\\n'
status = status .. 'Click Count: ' .. clickCount
statusDisplay.text = status
-- Update info box with current state
if disabled then
infoBox.text = '🔒 Target button is currently DISABLED. It cannot be clicked and appears grayed out.'
else
infoBox.text = '✅ Target button is currently ENABLED. Click it to see the counter increase!'
end
end
-- Target button click handler
targetButton:on('click', function()
clickCount = clickCount + 1
clickCounter.text = 'Button clicked ' .. clickCount .. ' times!'
gurt.log('Target button clicked! Count:', clickCount)
updateStatus()
end)
-- Enable button functionality
enableBtn:on('click', function()
targetButton:setAttribute('disabled', '') -- Remove disabled attribute
targetButton:setAttribute('data-value', 'enabled')
gurt.log('Target button enabled via setAttribute')
updateStatus()
end)
-- Disable button functionality
disableBtn:on('click', function()
targetButton:setAttribute('disabled', 'true')
targetButton:setAttribute('data-value', 'disabled')
gurt.log('Target button disabled via setAttribute')
updateStatus()
end)
-- Toggle button functionality
toggleBtn:on('click', function()
local currentlyDisabled = targetButton:getAttribute('disabled')
if currentlyDisabled then
-- Currently disabled, so enable it
targetButton:setAttribute('disabled', '')
targetButton:setAttribute('data-value', 'toggled-enabled')
gurt.log('Target button toggled to enabled state')
else
-- Currently enabled, so disable it
targetButton:setAttribute('disabled', 'true')
targetButton:setAttribute('data-value', 'toggled-disabled')
gurt.log('Target button toggled to disabled state')
end
updateStatus()
end)
-- Status check button
statusBtn:on('click', function()
local disabled = targetButton:getAttribute('disabled')
local type = targetButton:getAttribute('type')
local dataValue = targetButton:getAttribute('data-value')
gurt.log('=== BUTTON STATUS CHECK ===')
gurt.log('Disabled attribute:', disabled or 'not set')
gurt.log('Type attribute:', type or 'not set')
gurt.log('Data-value attribute:', dataValue or 'not set')
gurt.log('Click count:', clickCount)
gurt.log('===========================')
-- Demonstrate style setAttribute
local randomColors = {'bg-red-500', 'bg-green-500', 'bg-purple-500', 'bg-orange-500', 'bg-pink-500'}
local randomColor = randomColors[math.random(1, #randomColors)]
if not disabled then
targetButton:setAttribute('style', 'target-button ' .. randomColor .. ' text-white px-6 py-3 rounded-lg font-semibold hover:opacity-75')
gurt.setTimeout(function()
targetButton:setAttribute('style', 'target-button bg-[#3b82f6] text-white px-6 py-3 rounded-lg font-semibold hover:bg-[#2563eb]')
end, 1000)
end
end)
-- Initialize status display
updateStatus()
-- Set initial attributes to demonstrate the methods
targetButton:setAttribute('type', 'button')
targetButton:setAttribute('data-value', 'initial')
-- Update status after setting initial attributes
gurt.setTimeout(function()
updateStatus()
end, 100)
</script>
</head>
<body>
<h1>🔘 Button getAttribute & setAttribute Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<p id="info-box">✅ Target button is currently ENABLED. Click it to see the counter increase!</p>
</div>
<h2>Target Button</h2>
<div style="demo-buttons mb-6 text-center">
<button id="target-button" style="target-button">🎯 Click Me!</button>
<p id="click-counter" style="mt-3 text-lg font-semibold text-[#374151]">Button clicked 0 times!</p>
</div>
<h2>Control Buttons</h2>
<div style="button-group mb-6">
<button id="enable-btn" style="control-button enable-btn">🟢 Enable Button</button>
<button id="disable-btn" style="control-button disable-btn">🔴 Disable Button</button>
<button id="toggle-btn" style="control-button toggle-btn">🔄 Toggle State</button>
<button id="status-btn" style="control-button status-btn">📊 Check Status</button>
</div>
<h2>Current Attributes</h2>
<div style="status-display mb-6">
<pre id="status-display">Loading status...</pre>
</div>
<div style="bg-[#e0f2fe] p-4 rounded-lg">
<h3 style="text-[#0277bd] font-semibold mb-2">How It Works:</h3>
<ul style="text-[#01579b] space-y-1">
<li><strong>Enable:</strong> Uses <code>setAttribute('disabled', '')</code> to remove the disabled attribute</li>
<li><strong>Disable:</strong> Uses <code>setAttribute('disabled', 'true')</code> to add the disabled attribute</li>
<li><strong>Toggle:</strong> Uses <code>getAttribute('disabled')</code> to check current state, then toggles it</li>
<li><strong>Status:</strong> Uses <code>getAttribute()</code> to read multiple attributes and displays them</li>
<li><strong>Bonus:</strong> Also demonstrates setting custom data attributes and style changes</li>
</ul>
</div>
</div>
</body>

133
tests/audio.html Normal file
View File

@@ -0,0 +1,133 @@
<head>
<title>Audio Tag Demo - HTML5 Audio Testing</title>
<icon src="https://picsum.photos/32/32?random=audio">
<meta name="theme-color" content="#10b981">
<meta name="description" content="Testing HTML5 audio functionality">
<style>
body { bg-[#f0f9ff] p-8 font-family-system }
h1 { text-[#10b981] text-4xl font-bold text-center mb-8 }
h2 { text-[#059669] text-2xl font-semibold mb-4 }
h3 { text-[#047857] text-xl font-semibold mb-3 }
.section { bg-white p-6 rounded-xl shadow-lg mb-6 }
.audio-demo { mb-4 p-4 bg-[#f0fdf4] border border-[#bbf7d0] rounded-lg }
.code-block { bg-[#1e293b] text-[#e2e8f0] p-3 rounded font-mono text-sm mb-3 }
.description { text-[#475569] mb-3 }
.btn { bg-[#10b981] text-white px-4 py-2 rounded hover:bg-[#059669] active:bg-[#047857] cursor-pointer }
.control-group { flex gap-4 items-center mb-3 }
</style>
<script>
print('hi')
local programmaticAudio = nil
local controlledAudio = gurt.select("#controlled-audio")
local status = gurt.select("#programmatic-status")
gurt.select("#play-btn"):on("click", function()
controlledAudio:play()
end)
gurt.select("#pause-btn"):on("click", function()
controlledAudio:pause()
end)
gurt.select("#vol-low-btn"):on("click", function()
controlledAudio.volume = 0.3
end)
local test = gurt.setTimeout(function()
print('removed')
programmaticAudio:play()
end, 3000)
gurt.select("#vol-high-btn"):on("click", function()
controlledAudio.volume = 0.7
end)
gurt.select("#toggle-loop-btn"):on("click", function()
controlledAudio.loop = false
end)
gurt.select("#create-audio-btn"):on("click", function()
programmaticAudio = Audio.new("http://commondatastorage.googleapis.com/codeskulptor-assets/Evillaugh.ogg")
programmaticAudio.volume = 0.3
end)
gurt.select("#play-prog-btn"):on("click", function()
programmaticAudio:play()
end)
gurt.select("#pause-prog-btn"):on("click", function()
programmaticAudio:pause()
end)
</script>
</head>
<body>
<h1>🎵 HTML5 Audio Tag Demo</h1>
<!-- Basic Audio Elements -->
<div style="section">
<h2>📀 Basic Audio Elements</h2>
<div style="audio-demo">
<h3>Audio with Controls</h3>
<div style="description">Standard audio element with visible controls</div>
<div style="code-block">&lt;audio src="http://commondatastorage.googleapis.com/codeskulptor-assets/Evillaugh.ogg" controls&gt;&lt;/audio&gt;</div>
<audio src="http://commondatastorage.googleapis.com/codeskulptor-assets/Evillaugh.ogg" controls="true"></audio>
</div>
<div style="audio-demo">
<h3>Audio with Loop</h3>
<div style="description">Audio element that loops automatically</div>
<div style="code-block">&lt;audio src="http://commondatastorage.googleapis.com/codeskulptor-demos/DDR_assets/Kangaroo_MusiQue_-_The_Neverwritten_Role_Playing_Game.mp3" controls loop&gt;&lt;/audio&gt;</div>
<audio src="http://commondatastorage.googleapis.com/codeskulptor-demos/DDR_assets/Kangaroo_MusiQue_-_The_Neverwritten_Role_Playing_Game.mp3" controls="true" loop="true"></audio>
</div>
<div style="audio-demo">
<h3>Audio with Mute</h3>
<div style="description">Audio element that starts muted</div>
<div style="code-block">&lt;audio src="https://www.kozco.com/tech/LRMonoPhase4.wav" controls muted&gt;&lt;/audio&gt;</div>
<audio src="https://www.kozco.com/tech/LRMonoPhase4.wav" controls="true" muted="true"></audio>
</div>
</div>
<!-- Lua Audio Control -->
<div style="section">
<h2>🎮 Lua Audio Control</h2>
<div style="audio-demo">
<h3>DOM Audio Control</h3>
<div style="description">Control audio elements via Lua scripting</div>
<audio id="controlled-audio" src="http://commondatastorage.googleapis.com/codeskulptor-assets/Evillaugh.ogg" controls="true"></audio>
<div style="control-group">
<button id="play-btn" style="btn">▶️ Play</button>
<button id="pause-btn" style="btn">⏸️ Pause</button>
<button id="vol-low-btn" style="btn">🔉 Vol 30%</button>
<button id="vol-high-btn" style="btn">🔊 Vol 70%</button>
<button id="toggle-loop-btn" style="btn">🔁 Toggle Loop</button>
</div>
<div style="code-block">
local audio = gurt.select("#controlled-audio")
audio.play()
audio.volume = 0.5
audio.loop = true
</div>
</div>
<div style="audio-demo">
<h3>Programmatic Audio</h3>
<div style="description">Create audio instances with Audio.new()</div>
<div style="control-group">
<button id="create-audio-btn" style="btn">🎵 Create Audio</button>
<button id="play-prog-btn" style="btn">▶️ Play</button>
<button id="pause-prog-btn" style="btn">⏸️ Pause</button>
</div>
<div id="programmatic-status" style="text-[#059669] font-semibold"></div>
<div style="code-block">
local audio = Audio.new("http://commondatastorage.googleapis.com/codeskulptor-assets/Evillaugh.ogg")
audio.volume = 0.3
audio.play()
</div>
</div>
</div>
</body>

View File

@@ -0,0 +1,120 @@
<head>
<title>Task Manager</title>
<icon src="https://cdn-icons-png.flaticon.com/512/126/126472.png">
<meta name="theme-color" content="#1e1e2f">
<meta name="description" content="Manage your tasks easily.">
<style>
h1 { text-[#4ade80] text-3xl font-bold }
p { text-[#94a3b8] text-lg }
input { border border-[#cbd5e1] px-2 py-1 rounded }
</style>
<script src="logic.lua" />
</head>
<body>
<h1 style="text-center">📝 My Task Manager</h1>
<p style="text-center mb-4">Keep track of your to-do list</p>
<!-- Task List -->
<div style="flex flex-col gap-2 w-80 mx-auto bg-[#f8fafc] p-4 rounded">
<span style="flex justify-between items-center bg-[#e2e8f0] px-2 py-1 rounded">
<span>✅ Finish homework</span>
<button style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Delete</button>
</span>
<span style="flex justify-between items-center bg-[#e2e8f0] px-2 py-1 rounded">
<span>✍️ Write blog post</span>
<button style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Delete</button>
</span>
<span style="flex justify-between items-center bg-[#e2e8f0] px-2 py-1 rounded">
<span>💪 Gym workout</span>
<button style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Delete</button>
</span>
</div>
<separator direction="horizontal" />
<!-- Add New Task -->
<h2 style="text-center mt-4">Add a New Task</h2>
<form action="/add-task" method="POST" style="flex flex-col gap-2 w-80 mx-auto">
<input type="text" placeholder="Enter task..." minlength="3" required="true" />
<input type="date" />
<button type="submit" style="bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e]">Add Task</button>
</form>
<separator direction="horizontal" />
<h2 style="text-center">Task Categories</h2>
<div style="flex flex-row gap-2 justify-center items-center w-full">
<span style="bg-[#fef3c7] px-4 py-2 rounded">📚 Study</span>
<span style="bg-[#d1fae5] px-4 py-2 rounded">💼 Work</span>
<span style="bg-[#e0e7ff] px-4 py-2 rounded">🏋️ Health</span>
</div>
<form>
<input type=\"password\" placeholder=\"your password...\" />
<button type=\"submit\" style=\"bg-[#4CAF50] rounded-lg text-[#FFFFFF]\">Submit</button>
<button style=\"bg-[#2196F3] rounded-xl text-[#FFFFFF]\">Blue Button</button>
<button style=\"bg-[#FF5722] rounded-full text-[#FFFFFF]\">Orange Pill</button>
<button style=\"bg-[#9C27B0] rounded-[20px] text-[#FFFFFF]\">Purple Custom</button>
<button style=\"bg-[#FFD700] rounded text-[#000000] hover:bg-[#FFA500] hover:text-[#FFFFFF]\">Hover Test</button>
</form>
<h2>Button Style Tests</h2>
<button>Normal, no-styling button.</button>
<h3>Corner Radius Variants</h3>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-none\">No Radius</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-sm\">Small (2px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded\">Default (4px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-md\">Medium (6px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-lg\">Large (8px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-xl\">Extra Large (12px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-2xl\">2XL (16px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-3xl\">3XL (24px)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-full\">Full (Pill)</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-[30px]\">Custom 30px</button>
<h3>Color Combinations</h3>
<button style=\"bg-[#FF6B6B] text-[#FFFFFF] rounded-lg\">Red Background</button>
<button style=\"bg-[#4ECDC4] text-[#2C3E50] rounded-lg\">Teal & Dark Text</button>
<button style=\"bg-[#45B7D1] text-[#FFFFFF] rounded-lg\">Sky Blue</button>
<button style=\"bg-[#96CEB4] text-[#2C3E50] rounded-lg\">Mint Green</button>
<button style=\"bg-[#FFEAA7] text-[#2D3436] rounded-lg\">Yellow Cream</button>
<button style=\"bg-[#DDA0DD] text-[#FFFFFF] rounded-lg\">Plum Purple</button>
<button style=\"bg-[#98D8C8] text-[#2C3E50] rounded-lg\">Seafoam</button>
<h3>Hover Effects</h3>
<button style=\"bg-[#3498DB] text-[#FFFFFF] rounded-lg hover:bg-[#2980B9] hover:text-[#F8F9FA]\">Blue Hover</button>
<button style=\"bg-[#E67E22] text-[#FFFFFF] rounded-xl hover:bg-[#D35400] hover:text-[#ECF0F1]\">Orange Hover</button>
<button style=\"bg-[#9B59B6] text-[#FFFFFF] rounded-full hover:bg-[#8E44AD] hover:text-[#F4F4F4]\">Purple Pill Hover</button>
<button style=\"bg-[#1ABC9C] text-[#FFFFFF] rounded-2xl hover:bg-[#16A085]\">Turquoise Hover</button>
<h3>Advanced Hover Combinations</h3>
<button style=\"bg-[#34495E] text-[#ECF0F1] rounded hover:bg-[#E74C3C] hover:text-[#FFFFFF]\">Dark to Red</button>
<button style=\"bg-[#F39C12] text-[#2C3E50] rounded-lg hover:bg-[#27AE60] hover:text-[#FFFFFF]\">Gold to Green</button>
<button style=\"bg-[#FFFFFF] text-[#2C3E50] rounded-xl hover:bg-[#2C3E50] hover:text-[#FFFFFF]\">Light to Dark</button>
<h3>Text Color Focus</h3>
<button style=\"text-[#E74C3C] rounded-lg\">Red Text Only</button>
<button style=\"text-[#27AE60] rounded-lg\">Green Text Only</button>
<button style=\"text-[#3498DB] rounded-lg\">Blue Text Only</button>
<button style=\"text-[#9B59B6] rounded-full\">Purple Text Pill</button>
<h3>Mixed Styles</h3>
<button style=\"bg-[#FF7675] text-[#FFFFFF] rounded-[15px] hover:bg-[#FD79A8] hover:text-[#2D3436]\">Custom Mix 1</button>
<button style=\"bg-[#6C5CE7] text-[#DDD] rounded-3xl hover:bg-[#A29BFE] hover:text-[#2D3436]\">Custom Mix 2</button>
<button style=\"bg-[#00B894] text-[#FFFFFF] rounded-[25px] hover:bg-[#00CEC9] hover:text-[#2D3436]\">Custom Mix 3</button>
<button style=\"bg-[#0000ff] text-[#FFFFFF] rounded-[25px] hover:bg-[#ff0000] hover:text-[#2D3436]\">Blue normal, red hover</button>
<h3>Active State Tests</h3>
<button style=\"bg-[#3498DB] text-[#FFFFFF] rounded-lg hover:bg-[#2980B9] active:bg-[#1F618D] active:text-[#F8F9FA]\">Blue with Active</button>
<button style=\"bg-[#E74C3C] text-[#FFFFFF] rounded-xl hover:bg-[#C0392B] active:bg-[#A93226] active:text-[#ECF0F1]\">Red with Active</button>
<button style=\"bg-[#27AE60] text-[#FFFFFF] rounded-full hover:bg-[#229954] active:bg-[#1E8449] active:text-[#D5DBDB]\">Green Pill Active</button>
<button style=\"bg-[#F39C12] text-[#2C3E50] rounded hover:bg-[#E67E22] hover:text-[#FFFFFF] active:bg-[#D35400] active:text-[#F7F9FC]\">Gold Multi-State</button>
<button style=\"bg-[#9B59B6] text-[#FFFFFF] rounded-2xl active:bg-[#7D3C98] active:text-[#E8DAEF]\">Purple Active Only</button>
</body>

38
tests/clipboard.html Normal file
View File

@@ -0,0 +1,38 @@
<head>
<title>Clipboard API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#059669">
<meta name="description" content="Demonstrating Network fetching and Clipboard operations">
<style>
body { bg-[#f0fdf4] p-6 }
h1 { text-[#059669] text-3xl font-bold text-center }
h2 { text-[#047857] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.clipboard-btn { bg-[#10b981] text-white hover:bg-[#059669] p-4 }
.copy-url-btn { bg-[#8b5cf6] text-white hover:bg-[#7c3aed] }
</style>
<script>
gurt.log('Script started!')
local copyBtn = gurt.select('#copy-text-btn')
copyBtn:on('click', function()
gurt.log('Copy button clicked!')
Clipboard.write('Hello from GURT!')
end)
</script>
</head>
<body>
<h1>Clipboard API</h1>
<div style="container mt-6">
<h2>Clipboard Operations</h2>
<div style="button-group mb-6">
<button id="copy-text-btn" style="action-button clipboard-btn">📋 Copy Text</button>
</div>
</div>
</body>

76
tests/css-selector.html Normal file
View File

@@ -0,0 +1,76 @@
<head>
<title>CSS Selector Tests</title>
<style>
/* Descendant selectors */
div p { text-[#663399] }
.container span { bg-[#ffeeaa] }
/* Direct child selectors */
.outer-div > p { font-bold }
.parent > button { bg-[#44cc88] }
/* Adjacent sibling selectors */
h1 + p { text-[#ff0000] font-bold }
h2 + div { bg-[#eeffee] }
/* General sibling selectors */
h1 ~ p { text-[#0000ff] }
h1 ~ .second-p { text-[#0000ff] }
h3 ~ span { bg-[#ffdddd] }
/* Attribute selectors */
input[type="text"] { border border-[#cccccc] bg-[#f9f9f9] }
a[href^="https"] { text-[#008000] font-bold }
button[disabled] { bg-[#888888] text-[#cccccc] }
input[placeholder*="email"] { border-2 border-[#0066cc] bg-[#ffffff] }
div[style$="special"] { bg-[#ffffaa] }
</style>
</head>
<body>
<h1>CSS Selector Test Page</h1>
<p>This paragraph should be red and bold (h1 + p)</p>
<p style="second-p">This paragraph should be blue (h1 ~ p)</p>
<h2>Descendant vs Child Selectors</h2>
<div style="outer-div">
<p>This paragraph should be purple and bold (div p and .outer-div > p)</p>
<div>
<p>This paragraph should be purple but not bold (div p only)</p>
</div>
</div>
<h3>Attribute Selectors</h3>
<input type="text" placeholder="Enter your name" />
<input type="text" placeholder="Enter your email address" />
<input type="password" placeholder="Enter password" />
<br />
<a href="http://example.com">HTTP Link (normal)</a>
<br />
<a href="https://secure.com">HTTPS Link (green and bold)</a>
<br />
<button>Normal Button</button>
<button disabled="true">Disabled Button (gray)</button>
<h3>Sibling Selectors</h3>
<div style="bg-[#eeffee]">This div should have light green bg (h2 + div)</div>
<span>This span should have light red bg (h3 ~ span)</span>
<span>This span should also have light red bg (h3 ~ span)</span>
<div style="container">
<span>This span should have yellow bg (.container span)</span>
<p>Regular paragraph in container</p>
</div>
<div style="parent">
<button>This button should be green (.parent > button)</button>
<div>
<button>This button should be normal (not direct child)</button>
</div>
</div>
<div style="item-special">This div should have yellow bg (class ends with 'special')</div>
<div style="special-item">This div should be normal</div>
</body>

74
tests/dashboard.html Normal file
View File

@@ -0,0 +1,74 @@
<head>
<title>My Custom Dashboard</title>
<icon src="https://cdn-icons-png.flaticon.com/512/1828/1828774.png">
<meta name="theme-color" content="#1a202c">
<meta name="description" content="A stylish no-script dashboard">
<font name="roboto" src="https://fonts.gstatic.com/s/roboto/v48/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2" />
<style>
h1 { text-[#ffffff] text-3xl font-bold }
h2 { text-[#cbd5e1] text-xl }
p { text-[#94a3b8] text-base }
button { bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e] active:bg-[#15803d] }
.card { bg-[#1e293b] text-[#f8fafc] rounded-xl p-4 shadow-lg }
</style>
</head>
<body style="bg-[#0f172a] p-8 text-white font-roboto">
<h1 style="text-center mb-4">📊 My Dashboard</h1>
<!-- Top Summary Cards -->
<div style="flex flex-row gap-4 justify-center flex-wrap">
<div style="card w-48 h-24 flex flex-col justify-center items-center">
<h2 style="text-red-500">Users</h2>
<p>1,240</p>
</div>
<div style="card w-48 h-24 flex flex-col justify-center items-center">
<h2>Sales</h2>
<p>$9,842</p>
</div>
<div style="card w-48 h-24 flex flex-col justify-center items-center">
<h2>Visitors</h2>
<p>3,590</p>
</div>
</div>
<separator direction="horizontal" />
<!-- User Info Panel -->
<h2 style="text-center mt-6">👤 User Panel</h2>
<div style="flex flex-row gap-4 justify-center mt-2">
<div style="card w-64">
<p>Name: Jane Doe</p>
<p>Email: jane@example.com</p>
<p>Status: <span style="text-[#22c55e]">Active</span></p>
</div>
<div style="card w-64">
<p>Plan: Pro</p>
<p>Projects: 8</p>
<p>Tasks: 42</p>
</div>
</div>
<separator direction="horizontal" />
<!-- Recent Activity Log -->
<h2 style="text-center mt-6">📝 Recent Activity</h2>
<ul style="w-[80%] mt-2 flex justify-center flex-column gap-2">
<li style="bg-[#334155] px-4 py-2 rounded-xl mb-1">✅ Task "Update UI" marked as complete</li>
<li style="bg-[#334155] px-4 py-2 rounded-xl mb-1">🔔 New comment on "Bug Fix #224"</li>
<li style="bg-[#334155] px-4 py-2 rounded-xl mb-1">📤 Exported report "Q2 Metrics"</li>
</ul>
<separator direction="horizontal" />
<!-- Action Buttons -->
<h2 style="text-center mt-6">🔧 Actions</h2>
<div style="flex flex-row gap-2 justify-center mt-2">
<button style="rounded-lg px-4 py-2">Create Report</button>
<button style="rounded-lg px-4 py-2 bg-[#3b82f6] hover:bg-[#2563eb] active:bg-[#1e40af]">Invite User</button>
<button style="rounded-lg px-4 py-2 bg-[#facc15] text-[#000] hover:bg-[#eab308] active:bg-[#ca8a04]">Upgrade Plan</button>
</div>
</body>

70
tests/dom-utils.html Normal file
View File

@@ -0,0 +1,70 @@
<head>
<title>DOM Utilities Test</title>
<style>
.test-item { bg-[#e0e7ef] text-[#22223b] rounded p-2 mb-2 }
.highlight { bg-[#ffd700] }
</style>
<script>
local log = gurt.select("#log")
local function log_msg(msg)
log.text = log.text .. msg .. "\\n"
end
local parent = gurt.select("#parent")
local child1 = gurt.select("#child1")
local child2 = gurt.select("#child2")
local child3 = gurt.select("#child3")
print(log)
-- Show DOM property usage
log.text = ""
log_msg("parent of child2: " .. table.tostring(child2.parent))
log_msg("nextSibling of child2: " .. table.tostring(child2.nextSibling))
log_msg("previousSibling of child2: " .. table.tostring(child2.previousSibling))
log_msg("firstChild of parent: " .. table.tostring(parent.firstChild))
log_msg("lastChild of parent: " .. table.tostring(parent.lastChild))
-- Insert Before
gurt.select("#btn-insert-before"):on("click", function()
local newDiv = gurt.create("div", { class = "test-item highlight", text = "Inserted Before Child 2" })
parent:insertBefore(newDiv, child2)
log_msg("Inserted before child2: " .. newDiv._element_id)
end)
-- Insert After
gurt.select("#btn-insert-after"):on("click", function()
local newDiv = gurt.create("div", { class = "test-item highlight", text = "Inserted After Child 2" })
parent:insertAfter(newDiv, child2)
log_msg("Inserted after child2: " .. newDiv._element_id)
end)
-- Replace
gurt.select("#btn-replace"):on("click", function()
local newDiv = gurt.create("div", { class = "test-item highlight", text = "Replacement for Child 2" })
parent:replace(newDiv, child2)
log_msg("Replaced child2 with: " .. newDiv._element_id)
end)
-- Clone
gurt.select("#btn-clone"):on("click", function()
local clone = child3:clone(true)
parent:append(clone)
log_msg("Cloned child3: " .. clone._element_id)
end)
</script>
</head>
<body>
<h1>DOM Utilities Demo</h1>
<div id="parent" style="bg-[#f8fafc] p-4 rounded flex flex-col gap-2">
<div class="test-item">Non-interactible</div>
<div id="child1" class="test-item">Child 1</div>
<div id="child2" class="test-item">Child 2</div>
<div id="child3" class="test-item">Child 3</div>
</div>
<div style="flex gap-2 mt-4">
<button id="btn-insert-before">Insert Before Child 2</button>
<button id="btn-insert-after">Insert After Child 2</button>
<button id="btn-replace">Replace Child 2</button>
<button id="btn-clone">Clone Child 3</button>
</div>
<p id="log" style="mt-4 text-[#444] text-sm">Test</p>
</body>

289
tests/index.html Normal file
View File

@@ -0,0 +1,289 @@
<head>
<title>My cool web</title>
<icon src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Google_%22G%22_logo.svg/768px-Google_%22G%22_logo.svg.png\">
<meta name=\"theme-color\" content=\"#000000\">
<meta name=\"description\" content=\"My cool web\">
<font name="roboto" src="https://fonts.gstatic.com/s/roboto/v48/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2" />
<style>
h1 { text-[#ff0000] font-italic hover:text-[#00ff00] }
button { hover:bg-[#FF6B35] hover:text-[#FFFFFF] active:bg-[#CC5429] active:text-[#F0F0F0] }
</style>
<style src=\"styles.css\">
<script src=\"script.lua\" />
</head>
<body>
<h1>Header 1</h1>
<h2>Header 2</h2>
<h3>Header 3</h3>
<h4>Header 4</h4>
<h5>Header 5</h5>
<h6>Header 6</h6>
<separator />
<p>Normal font</p>
<p style="font-mono">Mono font</p>
<p style="font-sans">Sans font</p>
<p style="font-roboto">Custom font - Roboto</p>
<p>Hey there! this is a test</p>
<b>This is bold</b>
<i>This is italic <mark>actually, and it's pretty <u>cool</u></mark></i>
<u>This is underline</u>
<small>this is small</small>
<mark>this is marked</mark>
<code>this is code<span> THIS IS A SPAN AND SHOULDNT BE ANY DIFFERENT</span></code>
<p>
<a href="https://youtube.com">Hello gang</a>
</p>
<pre>
Text in a pre element
is displayed in a fixed-width
font, and it preserves
both spaces and
line breaks
</pre>
<p style="text-center w-32 h-32">
So
</p>
<div>
<button style="rounded-lg px-4 py-2 cursor-pointer">Create Report</button>
<button style="rounded-lg px-4 py-2 bg-[#3b82f6] hover:bg-[#2563eb] active:bg-[#1e40af] cursor-pointer">Invite User</button>
<button style="rounded-lg px-4 py-2 bg-[#facc15] text-[#000] hover:bg-[#eab308] active:bg-[#ca8a04] cursor-pointer">Upgrade Plan</button>
</div>
<button disabled="true">Disabled Button</button>
<button>Normal Button</button>
<separator direction="horizontal" />
<!-- Test CSS Properties -->
<h2 style="text-center mt-6">🧪 CSS Properties Test</h2>
<div style="flex flex-col gap-2 justify-center items-center mt-2">
<div style="bg-[#ef4444] text-white p-4 rounded-lg opacity-75 z-10 cursor-pointer">
<p>Opacity 75% with cursor pointer and z-index 10 - Text should show pointer cursor, not I-beam</p>
</div>
<div style="bg-[#10b981] text-white p-4 rounded-lg opacity-50 z-20 cursor-text">
<p>Opacity 50% with cursor text and z-index 20 - Text should show I-beam cursor</p>
</div>
<div style="bg-[#8b5cf6] text-white p-4 rounded-lg opacity-[0.25] z-[999] cursor-default">
<p>Custom opacity 0.25 with cursor default and z-index 999 - Text should show arrow cursor</p>
</div>
<div style="bg-[#f59e0b] text-white p-2 rounded cursor-move">
<p>Cursor move - Text should show move cursor</p>
</div>
<div style="bg-[#06b6d4] text-white p-2 rounded cursor-crosshair">
<p>Cursor crosshair - Text should show crosshair cursor</p>
</div>
<div style="bg-[#84cc16] text-white p-2 rounded cursor-help">
<p>Cursor help - Text should show help cursor</p>
</div>
<div style="bg-[#ec4899] text-white p-2 rounded cursor-not-allowed">
<p>Cursor not-allowed - Text should show forbidden cursor</p>
</div>
</div>
<separator direction="horizontal" />
<!-- Test cursor inheritance -->
<h2 style="text-center mt-6">🖱️ Cursor Inheritance Test</h2>
<div style="cursor-pointer bg-[#1e293b] p-4 rounded-lg">
<p>This paragraph is inside a div with cursor-pointer.</p>
<p>Both paragraphs should show pointer cursor instead of default I-beam.</p>
<div style="bg-[#334155] p-2 rounded mt-2">
<p>This nested paragraph should also inherit the pointer cursor.</p>
</div>
</div>
<!-- Border examples -->
<div style="border p-2 mb-2">border</div>
<div style="border-2 p-2 mb-2">border-2</div>
<div style="border-4 p-2 mb-2">border-4</div>
<div style="border-2 border-red-500 p-2 mb-2">border-2 border-red-500</div>
<div style="border p-2 mb-2">border-solid</div>
<div style="border border-dashed p-2 mb-2">border-dashed</div>
<div style="border border-dotted p-2 mb-2">border-dotted</div>
<div style="border-none p-2 mb-2">border-none</div>
<div style="border-t p-2 mb-2">border-t</div>
<div style="border-r p-2 mb-2">border-r</div>
<div style="border-b p-2 mb-2">border-b</div>
<div style="border-l p-2 mb-2">border-l</div>
<div style="border-t-4 p-2 mb-2">border-t-4</div>
<div style="border-b-2 p-2 mb-2">border-b-2</div>
<div style="border-l-6 p-2 mb-2">border-l-6</div>
<div style="border-t-3 border-green-500 p-2 mb-2">border-t-3 border-green-500</div>
<div style="border border-white p-2 mb-2">border-white</div>
<div style="border border-black p-2 mb-2">border-black</div>
<div style="border border-transparent p-2 mb-2">border-transparent</div>
<div style="border border-gray-400 p-2 mb-2">border-gray-400</div>
<div style="border border-slate-700 p-2 mb-2">border-slate-700</div>
<div style="border border-red-500 p-2 mb-2">border-red-500</div>
<div style="border border-green-600 p-2 mb-2">border-green-600</div>
<div style="border border-blue-400 p-2 mb-2">border-blue-400</div>
<div style="border border-yellow-300 p-2 mb-2">border-yellow-300</div>
<select style=\"text-center max-w-5 max-h-32\">
<option value=\"test1\">Test 1</option>
<option value=\"test2\" selected=\"true\">Test 2</option>
<option value=\"test3\">Test 3</option>
<option value=\"test4\" disabled=\"true\">Test 4</option>
<option value=\"test5\">Test 5</option>
</select>
<textarea />
<textarea cols=\"30\" />
<textarea rows=\"2\" />
<textarea maxlength=\"20\" />
<textarea readonly=\"true\">le skibidi le toilet</textarea>
<textarea disabled=\"true\" value=\"DISABLED\" />
<textarea placeholder=\"this is a placeholder...\" />
<!-- action, method, and type=submit are for when we implement Lua -->
<form action=\"/submit\" method=\"POST\">
<span>Name:</span>
<input type=\"text\" placeholder=\"First name\" value=\"John\" maxlength=\"20\" minlength=\"3\" />
<span>Email regex:</span>
<input type=\"text\" placeholder=\"Last name\" value=\"Doe\" pattern=\"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$\" />
<span>Smart:</span>
<input type=\"checkbox\" />
<input type=\"checkbox\" value=\"true\" />
<p>favorite food</p>
<input type=\"radio\" group=\"food\" />
<span>Pizza</span>
<input type=\"radio\" group=\"food\" />
<span>Berry</span>
<input type=\"radio\" group=\"food\" />
<span>Gary</span>
<h2>Color</h2>
<input type=\"color\" value=\"#ff0000\" />
<h2>Date</h2>
<input type=\"date\" value=\"2018-07-22\" />
<h2>Range Slider</h2>
<input style=\"max-w-2 max-h-2\" type=\"range\" min=\"0\" max=\"100\" step=\"5\" value=\"50\" />
<h2>Number Input</h2>
<input type=\"number\" min=\"1\" max=\"10\" step=\"0.5\" value=\"5\" placeholder=\"Enter number\" />
<h2>File Upload</h2>
<input type=\"file\" accept=\".txt,.pdf,image/*\" />
</form>
<separator direction=\"horizontal\" />
# Ordered list
<ol>
<li>hello gang</li>
<li>this</li>
<li>is</li>
</ol>
<ol type=\"zero-lead\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ol type=\"lower-alpha\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ol type=\"upper-alpha\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ol type=\"lower-roman\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ol type=\"upper-roman\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ol>
<ul>
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ul>
<ul type=\"circle\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ul>
<ul type=\"none\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ul>
<ul type=\"square\">
<li>hello gang</li>
<li>this</li>
<li>is</li>
<li>a test</li>
</ul>
<img style=\"text-center max-w-24 max-h-24\" src=\"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQMNUPIKabszX0Js_c0kfa4cz_JQYKfGTuBUA&s\" />
<separator direction=\"vertical\" />
<!-- FLEXBOX EXAMPLES -->
<h2>Flex Row (gap, justify-between, items-center)</h2>
<div style=\"flex flex-row gap-4 justify-between items-center w-64 h-16 bg-[#f0f0f0]\">
<span style=\"bg-[#ffaaaa] w-16 h-8 flex items-center justify-center\">A</span>
<span style=\"bg-[#aaffaa] w-16 h-8 flex items-center justify-center\">B</span>
<span style=\"bg-[#aaaaff] w-16 h-8 flex items-center justify-center\">C</span>
</div>
<h2>Flex Column (gap, items-center, content-center)</h2>
<div style=\"flex flex-col gap-2 items-center content-center h-32 w-32 bg-[#e0e0e0]\">
<span style=\"bg-[#ffaaaa] w-16 h-6 flex items-center justify-center\">1</span>
<span style=\"bg-[#aaffaa] w-16 h-6 flex items-center justify-center\">2</span>
<span style=\"bg-[#aaaaff] w-16 h-6 flex items-center justify-center\">3</span>
</div>
<h2>Flex Wrap (row, wrap, gap)</h2>
<div style=\"flex flex-row flex-wrap gap-2 w-40 bg-[#f8f8f8]\">
<span style=\"bg-[#ffaaaa] w-16 h-6 flex items-center justify-center\">X</span>
<span style=\"bg-[#aaffaa] w-16 h-6 flex items-center justify-center\">Y</span>
<span style=\"bg-[#aaaaff] w-16 h-6 flex items-center justify-center\">Z</span>
<span style=\"bg-[#ffffaa] w-16 h-6 flex items-center justify-center\">W</span>
</div>
<h2>Flex Grow/Shrink/Basis</h2>
<div style=\"flex flex-row gap-2 w-64 bg-[#f0f0f0]\">
<span style=\"bg-[#ffaaaa] flex-grow-1 h-8 flex items-center justify-center\">Grow 1</span>
<span style=\"bg-[#aaffaa] flex-grow-2 h-8 flex items-center justify-center\">Grow 2</span>
<span style=\"bg-[#aaaaff] flex-shrink-0 w-8 h-8 flex items-center justify-center\">No Shrink</span>
</div>
<h2>Align Self</h2>
<div style=\"flex flex-row h-24 bg-[#f0f0f0] items-stretch gap-2 w-64\">
<span style=\"bg-[#ffaaaa] w-12 h-8 self-start flex items-center justify-center\">Start</span>
<span style=\"bg-[#aaffaa] w-12 h-8 self-center flex items-center justify-center\">Center</span>
<span style=\"bg-[#aaaaff] w-12 h-8 self-end flex items-center justify-center\">End</span>
<span style=\"bg-[#ffffaa] w-12 h-8 self-stretch flex items-center justify-center\">Stretch</span>
</div>
</body>

273
tests/input-events.html Normal file
View File

@@ -0,0 +1,273 @@
<head>
<title>Input Events API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#059669">
<meta name="description" content="Demonstrating input element events with GURT Lua API">
<style>
body { bg-[#f0fdf4] p-6 }
h1 { text-[#059669] text-3xl font-bold text-center }
h2 { text-[#047857] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.form-group { flex flex-col gap-2 mb-4 }
.input-demo { bg-[#f8fafc] p-4 rounded-lg border }
.event-log { bg-[#1f2937] text-white p-4 rounded-lg font-mono text-sm max-h-64 overflow-auto }
.form-button { bg-[#10b981] text-white px-4 py-2 rounded hover:bg-[#059669] cursor-pointer }
.clear-btn { bg-[#ef4444] text-white px-4 py-2 rounded hover:bg-[#dc2626] cursor-pointer }
</style>
<script>
-- Get the event log element
local eventLog = gurt.select('#event-log')
local function logEvent(elementType, eventType, data)
local timestamp = Time.format(Time.now(), '%H:%M:%S')
local message = '[' .. timestamp .. '] ' .. elementType .. ' -> ' .. eventType
if data then
message = message .. ': ' .. data
end
print(message)
end
-- Text Input Events
local textInput = gurt.select('#text-input')
print('Text input found:', textInput)
if textInput then
textInput:on('input', function(e)
logEvent('Text Input', 'input', e.value)
end)
textInput:on('change', function(e)
logEvent('Text Input', 'change', e.value)
end)
textInput:on('focusin', function()
logEvent('Text Input', 'focusin', nil)
end)
textInput:on('focusout', function()
logEvent('Text Input', 'focusout', nil)
end)
else
print('Text input not found!')
end
-- Email Input Events
local emailInput = gurt.select('#email-input')
emailInput:on('input', function(e)
logEvent('Email Input', 'input', e.value)
end)
emailInput:on('change', function(e)
logEvent('Email Input', 'change', e.value)
end)
-- Password Input Events
local passwordInput = gurt.select('#password-input')
passwordInput:on('input', function(e)
logEvent('Password Input', 'input', table.tostring(e))
end)
passwordInput:on('change', function(e)
logEvent('Password Input', 'change', table.tostring(e))
end)
-- Number Input Events
local numberInput = gurt.select('#number-input')
numberInput:on('change', function(e)
logEvent('Number Input', 'change', e.value)
end)
-- Range Input Events
local rangeInput = gurt.select('#range-input')
rangeInput:on('change', function(e)
logEvent('Range Input', 'change', e.value)
end)
-- Color Input Events
local colorInput = gurt.select('#color-input')
colorInput:on('change', function(e)
logEvent('Color Input', 'change', e.value)
end)
-- Date Input Events
local dateInput = gurt.select('#date-input')
dateInput:on('change', function(e)
logEvent('Date Input', 'change', e.value)
end)
-- File Input Events
local fileInput = gurt.select('#file-input')
fileInput:on('change', function(e)
if e.dataURL then
e.dataURL = e.dataURL:sub(1, 100)
end
if e.text then
e.text = e.text:sub(1, 100)
end
logEvent('File Input', 'change', table.tostring(e))
end)
-- Checkbox Events
local checkbox = gurt.select('#checkbox')
checkbox:on('change', function(e)
logEvent('Checkbox', 'change', table.tostring(e))
end)
-- Radio Button Events
local radio1 = gurt.select('#radio1')
local radio2 = gurt.select('#radio2')
local radio3 = gurt.select('#radio3')
radio1:on('change', function(e)
logEvent('Radio Button 1', 'change', table.tostring(e))
end)
radio2:on('change', function(e)
logEvent('Radio Button 2', 'change', table.tostring(e))
end)
radio3:on('change', function(e)
logEvent('Radio Button 3', 'change', table.tostring(e))
end)
-- Textarea Events
local textarea = gurt.select('#textarea')
textarea:on('input', function(e)
logEvent('Textarea', 'input', e.value:sub(1, 20) .. '...')
end)
textarea:on('change', function(e)
logEvent('Textarea', 'change', 'Length: ' .. #e.value)
end)
-- Select Events
local selectElement = gurt.select('#select-element')
selectElement:on('change', function(e)
logEvent('Select', 'change', 'Index: ' .. table.tostring(e))
end)
-- Button Events
local submitBtn = gurt.select('#submit-btn')
submitBtn:on('click', function()
logEvent('Submit Button', 'click', nil)
end)
submitBtn:on('submit', function(e)
logEvent('Form', 'submit', table.tostring(e))
end)
-- Clear log button
local clearBtn = gurt.select('#clear-btn')
clearBtn:on('click', function()
eventLog.text = '--- Event Log Cleared ---\\n'
eventCount = 0
end)
-- Initial log message
logEvent('System', 'initialized', 'Input events demo ready')
</script>
</head>
<body>
<h1>🎛️ Input Events API Demo</h1>
<div style="container mt-6">
<div style="flex flex-row gap-6">
<!-- Input Forms Column -->
<div style="flex-1">
<h2>Input Elements</h2>
<form id="demo-form">
<div style="form-group">
<label>Text Input:</label>
<input id="text-input" key="username" type="text" placeholder="Type something..." />
</div>
<div style="form-group">
<label>Email Input:</label>
<input id="email-input" key="email" type="email" placeholder="Enter email..." />
</div>
<div style="form-group">
<label>Password Input:</label>
<input id="password-input" key="password" type="password" placeholder="Enter password..." />
</div>
<div style="form-group">
<label>Number Input:</label>
<input id="number-input" key="score" type="number" min="0" max="100" value="50" />
</div>
<div style="form-group">
<label>Range Input:</label>
<input id="range-input" key="volume" type="range" min="0" max="100" value="25" />
</div>
<div style="form-group">
<label>Color Input:</label>
<input id="color-input" key="favoriteColor" type="color" value="#ff0000" />
</div>
<div style="form-group">
<label>Date Input:</label>
<input id="date-input" key="birthDate" type="date" value="2024-01-01" />
</div>
<div style="form-group">
<label>File Input:</label>
<input id="file-input" key="attachment" type="file" accept=".txt,.pdf,.png" />
</div>
<div style="form-group">
<input id="checkbox" key="newsletter" type="checkbox" />
<p>Checkbox Option</p>
</div>
<div style="form-group">
<input id="radio1" key="option" type="radio" group="options" value="option1" /><span>Option 1</span>
<input id="radio2" key="option" type="radio" group="options" value="option2" /><span>Option 2</span>
<input id="radio3" key="option" type="radio" group="options" value="option3" /><span>Option 3</span>
</div>
<div style="form-group">
<label>Textarea:</label>
<textarea id="textarea" key="message" placeholder="Write something longer..." rows="3"></textarea>
</div>
<div style="form-group">
<label>Select Dropdown:</label>
<select id="select-element" key="fruit">
<option value="apple">Apple</option>
<option value="banana" selected="true">Banana</option>
<option value="orange">Orange</option>
<option value="grape">Grape</option>
</select>
</div>
<div style="flex gap-2">
<button id="submit-btn" type="submit" style="form-button">Submit Form</button>
<button id="clear-btn" type="button" style="clear-btn">Clear Log</button>
</div>
</form>
</div>
<!-- Event Log Column -->
<div style="flex-1">
<h2>Event Log</h2>
<div style="event-log">
<pre id="event-log">Waiting for events...
</pre>
</div>
<div style="bg-[#e0f2fe] p-4 rounded-lg mt-4">
<h3 style="text-[#0277bd] font-semibold mb-2">Available Events:</h3>
<ul style="text-[#01579b] space-y-1 text-sm">
<li><strong>input:</strong> Fires as you type (real-time)</li>
<li><strong>change:</strong> Fires when value changes and element loses focus</li>
<li><strong>focusin:</strong> Fires when element gains focus</li>
<li><strong>focusout:</strong> Fires when element loses focus</li>
<li><strong>click:</strong> Fires when button is clicked</li>
<li><strong>submit:</strong> Fires when form is submitted (includes form data)</li>
</ul>
</div>
</div>
</div>
</div>
</body>

View File

@@ -0,0 +1,167 @@
<head>
<title>setInterval & Network Image Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#7c3aed">
<meta name="description" content="Testing setInterval/clearInterval and network image loading with binary data">
<style>
body { bg-[#f8fafc] p-6 }
h1 { text-[#7c3aed] text-3xl font-bold text-center }
h2 { text-[#6d28d9] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.control-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#7c3aed] text-white hover:bg-[#6d28d9] }
.danger-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#ef4444] text-white hover:bg-[#dc2626] }
.success-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#059669] text-white hover:bg-[#047857] }
.log-area { bg-[#f1f5f9] p-4 rounded-lg min-h-32 font-mono text-sm max-h-96 overflow-auto }
.image-container { text-center p-4 border-2 border-dashed border-[#cbd5e1] rounded-lg }
.counter { text-[#7c3aed] text-6xl font-bold text-center p-4 }
.info-box { bg-[#ede9fe] border border-[#7c3aed] p-4 rounded-lg }
</style>
<script>
-- Get UI elements
local logArea = gurt.select('#log-area')
local counterDisplay = gurt.select('#counter')
local startIntervalBtn = gurt.select('#start-interval-btn')
local stopIntervalBtn = gurt.select('#stop-interval-btn')
local loadImageBtn = gurt.select('#load-image-btn')
local imageContainer = gurt.select('#image-container')
gurt.log('setInterval & Network Image demo script started.')
local logMessages = {}
local counter = 0
local intervalId = nil
-- Function to add message to log
local function addLog(message)
table.insert(logMessages, Time.format(Time.now(), '%H:%M:%S.%f'):sub(1, 12) .. ' - ' .. message)
if #logMessages > 30 then
table.remove(logMessages, 1)
end
logArea.text = table.concat(logMessages, '\\n')
end
-- Update counter display
local function updateCounter()
counterDisplay.text = tostring(counter)
end
-- Start interval button
startIntervalBtn:on('click', function()
if intervalId then
addLog('❌ Interval already running (ID: ' .. intervalId .. ')')
return
end
counter = 0
updateCounter()
intervalId = gurt.setInterval(function()
counter = counter + 1
updateCounter()
addLog('⏱️ Counter updated to: ' .. counter)
end, 500) -- Every 500ms
addLog('✅ Interval started (ID: ' .. intervalId .. ')')
end)
-- Stop interval button
stopIntervalBtn:on('click', function()
if not intervalId then
addLog('❌ No interval to stop')
return
end
gurt.clearInterval(intervalId)
addLog('🛑 Interval stopped (ID: ' .. intervalId .. ')')
intervalId = nil
end)
-- Network image loading
loadImageBtn:on('click', function()
addLog('🔄 Starting random image fetch...')
imageContainer.text = 'Loading image...'
-- Use a random image service that returns binary data
local randomImageUrl = 'https://picsum.photos/300/200?random=' .. math.floor(Time.now() * 1000)
addLog('📡 Fetching: ' .. randomImageUrl)
local response = fetch(randomImageUrl)
-- Handle both success and redirect cases (302 is common for image services)
if response:ok() or response.status == 302 then
addLog('✅ Image fetch response received (Status: ' .. response.status .. ')')
addLog('📊 Content-Type: ' .. (response.headers['content-type'] or 'unknown'))
addLog('📏 Content-Length: ' .. (response.headers['content-length'] or 'unknown'))
-- For image services, we can often use the original URL directly
-- since the browser/engine handles redirects automatically
local imageElement = gurt.create('img', {
src = randomImageUrl,
style = 'max-w-[300px] max-h-[200px] rounded-lg shadow-md'
})
-- Clear container and append new image
imageContainer.text = ''
imageContainer:append(imageElement)
addLog('🖼️ Image element created and appended')
addLog('💡 Note: Image service may use redirects (302), but img tag handles this')
else
addLog('❌ Image fetch failed: ' .. response.status .. ' ' .. (response.statusText or 'Unknown'))
imageContainer.text = 'Failed to load image'
end
end)
-- Initialize
updateCounter()
addLog('🚀 Demo ready!')
addLog('💡 Click "Start Interval" to begin counter')
addLog('🖼️ Click "Load Random Image" to test binary data handling')
</script>
</head>
<body>
<h1>⏰ setInterval & 🖼️ Network Image Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<h3 style="text-[#6d28d9] font-semibold mb-2">Testing Features:</h3>
<p><strong>Intervals:</strong> <code>gurt.setInterval(callback, delay)</code> and <code>gurt.clearInterval(id)</code></p>
<p><strong>Network Images:</strong> <code>fetch()</code> with binary data and dynamic <code>&lt;img&gt;</code> creation</p>
</div>
<div style="counter mb-6" id="counter">0</div>
<h2>Interval Controls</h2>
<div style="button-group mb-6">
<button id="start-interval-btn" style="control-button">▶️ Start Interval</button>
<button id="stop-interval-btn" style="danger-button">⏹️ Stop Interval</button>
</div>
<h2>Network Image Test</h2>
<div style="button-group mb-6">
<button id="load-image-btn" style="success-button">🖼️ Load Random Image</button>
</div>
<div id="image-container" style="image-container mb-6">
<p style="text-[#64748b]">Click "Load Random Image" to test binary data fetching</p>
</div>
<h2>Activity Log</h2>
<div style="log-area mb-6">
<pre id="log-area">Initializing...</pre>
</div>
<div style="bg-[#f3f4f6] p-4 rounded-lg">
<h3 style="text-[#374151] font-semibold mb-2">Implementation Notes:</h3>
<ul style="text-[#4b5563] space-y-1 text-sm">
<li><strong>setInterval:</strong> Creates repeating timers (one_shot = false)</li>
<li><strong>clearInterval:</strong> Stops and cleans up interval timers</li>
<li><strong>Binary Data:</strong> fetch() handles binary image data seamlessly</li>
<li><strong>Dynamic DOM:</strong> Images created and appended programmatically</li>
<li><strong>Random Images:</strong> Picsum service provides different images each time</li>
</ul>
</div>
</div>
</body>

148
tests/lua-api.html Normal file
View File

@@ -0,0 +1,148 @@
<head>
<title>Lua API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#000080">
<meta name="description" content="Demonstrating the GURT Lua API">
<style>
body { bg-[#f8f9fa] p-6 }
h1 { text-[#2563eb] text-2xl font-bold }
.container { bg-[#ffffff] p-4 rounded-lg shadow-lg }
.demo-button { bg-[#3b82f6] text-white px-4 py-2 rounded hover:bg-[#2563eb] }
.fancy { bg-green-500 text-red-500 p-2 rounded-full mt-2 mb-2 text-2xl hover:bg-red-300 hover:text-[#2563eb] }
</style>
<script>
local typing = gurt.select('#type')
local mouse = gurt.select('#mouse')
local btnmouse = gurt.select('#btnmouse')
gurt.log('Starting Lua script execution...')
gurt.body:on('keypress', function(el)
typing.text = table.tostring(el)
end)
gurt.body:on('mousemove', function(el)
mouse.text = table.tostring(el)
end)
-- Test element selection and manipulation
local heading = gurt.select('#main-heading')
heading.text = 'Welcome to the New Web!'
local button = gurt.select('#demo-button')
local event_log = gurt.select('#event-log')
button:on('mousedown', function()
print('Mouse down')
end)
button:on('mouseup', function()
print('Mouse up')
end)
button:on('mouseenter', function()
print('Mouse enter')
end)
button:on('mouseexit', function()
print('Mouse exit')
end)
button:on('mousemove', function(el)
btnmouse.text = table.tostring(el)
end)
if button and event_log then
local click_count = 0
local subscription = button:on('click', function()
click_count = click_count + 1
local new_text = 'Button clicked ' .. click_count .. ' time(s)!'
event_log.text = new_text
end)
heading:on('focusin', function()
print('oh u flck')
subscription:unsubscribe()
end)
gurt.log('Event listener attached to button with subscription ID')
else
gurt.log('Could not find button or event log element')
end
-- DOM Manipulation Demo
gurt.log('Testing DOM manipulation...')
-- Create a new div with styling
local new_div = gurt.create('div', { style = 'bg-red-500 p-4 rounded-lg mb-4' })
-- Create a paragraph with text
local new_p = gurt.create('p', {
style = 'text-white font-bold text-lg',
text = 'This element was created dynamically with Lua!'
})
-- Append paragraph to div
new_div:append(new_p)
-- Append div to body
gurt.body:append(new_div)
-- Create another element to test removal
local temp_element = gurt.create('div', {
style = 'bg-yellow-400 p-2 rounded text-black',
text = 'This will be removed in 3 seconds...'
})
gurt.body:append(temp_element)
local test = gurt.setTimeout(function()
print('removed')
temp_element:remove()
end, 3000)
-- gurt.clearTimeout(test)
local addBtn = gurt.select('#add-class')
local removeBtn = gurt.select('#remove-class')
local btnTarget = gurt.select('#btnTarget')
addBtn:on('click', function()
btnTarget.classList:add('fancy')
-- btnTarget.classList:toggle('fancy')
print('Class added')
end)
removeBtn:on('click', function()
btnTarget.classList:remove('fancy')
print('Class removed')
end)
</script>
</head>
<body>
<h1 id="main-heading">Welcome to GURT Lua API Demo</h1>
<div style="container">
<p>This page demonstrates the GURT Lua API in action.</p>
<div id="demo-button" style="w-40 h-40 bg-red-500 p-4 rounded-lg">Click me to see Lua in action!</div>
</div>
<p id="event-log" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Click the button</p>
<p id="mouse" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Move your mouse</p>
<p id="btnmouse" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Move mouse over Button</p>
<p id="type" style="mt-4 p-4 bg-[#f3f4f6] rounded min-h-24">Type something</p>
<div style="mt-6 flex gap-4 items-center">
<div style="text-lg font-semibold">Style Controls:</div>
<button id="add-class" style="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700">Add Class</button>
<button id="remove-class" style="bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700">Remove Class</button>
</div>
<button id="btnTarget" style="bg-gray-600">Button</button>
</body>

231
tests/network-and-json.html Normal file
View File

@@ -0,0 +1,231 @@
<title>Network & JSON API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#0891b2">
<meta name="description" content="Demonstrating Network fetch() and JSON APIs">
<style>
body { bg-[#ecfdf5] p-6 }
h1 { text-[#0891b2] text-3xl font-bold text-center }
h2 { text-[#0f766e] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.fetch-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#059669] text-white hover:bg-[#047857] }
.json-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#7c3aed] text-white hover:bg-[#6d28d9] }
.clear-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#ef4444] text-white hover:bg-[#dc2626] }
.response-area { bg-[#f1f5f9] p-4 rounded-lg min-h-32 font-mono text-sm max-h-96 overflow-auto }
.info-box { bg-[#dbeafe] border border-[#3b82f6] p-4 rounded-lg }
.input-area { bg-[#f9fafb] p-4 rounded-lg border }
</style>
<script>
-- Get UI elements
local responseArea = gurt.select('#response-area')
local fetchGetBtn = gurt.select('#fetch-get-btn')
local fetchPostBtn = gurt.select('#fetch-post-btn')
local jsonEncodeBtn = gurt.select('#json-encode-btn')
local jsonDecodeBtn = gurt.select('#json-decode-btn')
local clearLogBtn = gurt.select('#clear-log-btn')
local urlInput = gurt.select('#url-input')
local jsonInput = gurt.select('#json-input')
gurt.log('Network & JSON API demo script started.')
local logMessages = {}
-- Function to add message to log
local function addLog(message)
table.insert(logMessages, Time.format(Time.now(), '%H:%M:%S') .. ' - ' .. message)
if #logMessages > 50 then
table.remove(logMessages, 1)
end
responseArea.text = table.concat(logMessages, '\\n')
end
-- Initialize with default values
urlInput.text = 'https://jsonplaceholder.typicode.com/posts/1'
jsonInput.text = JSON.stringify({
name = 'Alice Johnson',
age = 28,
hobbies = {'reading', 'coding', 'gaming'},
active = true,
score = 95.5
})
-- GET Request Test
fetchGetBtn:on('click', function()
local url = urlInput.text
addLog('Making GET request to: ' .. url)
local response = fetch(url)
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
addLog('Response Headers: ' .. JSON.stringify(response.headers))
if response:ok() then
local responseText = response:text()
addLog('Response Body: ' .. responseText:sub(1, 200) .. (responseText:len() > 200 and '...' or ''))
-- Try to parse as JSON
local jsonData = response:json()
if jsonData then
addLog('Parsed JSON successfully')
end
else
addLog('Request failed with status: ' .. response.status)
end
end)
-- POST Request Test
fetchPostBtn:on('click', function()
local url = 'https://jsonplaceholder.typicode.com/posts'
local postData = {
title = 'Test Post from GURT',
body = 'This is a test post created using the GURT Network API',
userId = 1
}
addLog('Making POST request to: ' .. url)
addLog('POST Data: ' .. JSON.stringify(postData))
local response = fetch(url, {
method = 'POST',
headers = {
['Content-Type'] = 'application/json'
},
body = JSON.stringify(postData)
})
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
if response:ok() then
local responseText = response:text()
addLog('Created Resource: ' .. responseText)
else
addLog('POST request failed with status: ' .. response.status)
end
end)
-- JSON Encode Test
jsonEncodeBtn:on('click', function()
local inputText = jsonInput.text
addLog('Encoding text to JSON: ' .. inputText:sub(1, 100) .. (inputText:len() > 100 and '...' or ''))
-- Try to parse the input as Lua data first
local success, data = pcall(function()
-- Simple data structure for demo
return {
message = inputText,
timestamp = Time.now(),
random = math.random(1, 100),
nested = {
array = {1, 2, 3},
bool = true
}
}
end)
if success then
local jsonString = JSON.stringify(data)
addLog('JSON Encoded: ' .. jsonString)
else
addLog('Error creating test data for encoding')
end
end)
-- JSON Decode Test
jsonDecodeBtn:on('click', function()
local jsonText = jsonInput.text
addLog('Decoding JSON: ' .. jsonText:sub(1, 100) .. (jsonText:len() > 100 and '...' or ''))
local data, error = JSON.parse(jsonText)
if data then
addLog('JSON Decoded successfully!')
addLog('Data type: ' .. type(data))
if type(data) == 'table' then
local keys = {}
for k, v in pairs(data) do
table.insert(keys, k .. ':' .. type(v))
end
addLog('Keys: ' .. table.concat(keys, ', '))
end
addLog('Stringified back: ' .. JSON.stringify(data))
else
addLog('JSON Decode Error: ' .. (error or 'Unknown error'))
end
end)
-- Clear log button
clearLogBtn:on('click', function()
logMessages = {}
responseArea.text = 'Log cleared.'
addLog('Network & JSON API demo ready')
end)
-- Initialize
addLog('Network & JSON API demo ready')
addLog('Try the buttons above to test network requests and JSON operations!')
</script>
</head>
<body>
<h1>🌐 Network & JSON API Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<h3 style="text-[#1e40af] font-semibold mb-2">API Examples:</h3>
<p><strong>Network:</strong> <code>fetch(url, {method: "POST", headers: {...}, body: "..."})</code></p>
<p><strong>JSON:</strong> <code>JSON.stringify(data)</code> and <code>JSON.parse(jsonString)</code></p>
</div>
<h2>Input Controls</h2>
<div style="input-area mb-6">
<div style="flex flex-col gap-3">
<div>
<label style="block text-sm font-medium mb-1">Test URL:</label>
<input id="url-input" type="text" style="w-full p-2 border border-gray-300 rounded-md" placeholder="Enter API URL..." />
</div>
<div>
<label style="block text-sm font-medium mb-1">JSON Data:</label>
<textarea id="json-input" style="w-full p-2 border border-gray-300 rounded-md" rows="3" placeholder="Enter JSON data..."></textarea>
</div>
</div>
</div>
<h2>Network Tests</h2>
<div style="button-group mb-6">
<button id="fetch-get-btn" style="fetch-button">🔍 GET Request</button>
<button id="fetch-post-btn" style="fetch-button">📤 POST Request</button>
</div>
<h2>JSON Tests</h2>
<div style="button-group mb-6">
<button id="json-encode-btn" style="json-button">📝 JSON Encode</button>
<button id="json-decode-btn" style="json-button">📖 JSON Decode</button>
</div>
<div style="button-group mb-6">
<button id="clear-log-btn" style="clear-button">🧹 Clear Log</button>
</div>
<h2>Response Log</h2>
<div style="response-area mb-6">
<pre id="response-area">Initializing...</pre>
</div>
<div style="bg-[#f0f9ff] p-4 rounded-lg">
<h3 style="text-[#0369a1] font-semibold mb-2">Network API Features:</h3>
<ul style="text-[#075985] space-y-1 text-sm">
<li><strong>fetch(url, options):</strong> Makes HTTP requests with support for all methods</li>
<li><strong>Response methods:</strong> text(), json(), ok() for processing responses</li>
<li><strong>Headers & Body:</strong> Full control over request headers and body content</li>
<li><strong>Status & StatusText:</strong> Access to HTTP response status information</li>
</ul>
<h3 style="text-[#0369a1] font-semibold mt-4 mb-2">JSON API Features:</h3>
<ul style="text-[#075985] space-y-1 text-sm">
<li><strong>JSON.stringify():</strong> Alias for encode (browser compatibility)</li>
<li><strong>JSON.parse():</strong> Alias for decode (browser compatibility)</li>
</ul>
</div>
</div>
</body>

72
tests/object-fit.html Normal file
View File

@@ -0,0 +1,72 @@
<head>
<title>Object-Fit CSS Demo</title>
<icon src="https://picsum.photos/32/32?random=1">
<meta name="theme-color" content="#0ea5e9">
<meta name="description" content="Demonstrating object-fit CSS properties for images">
<style>
body { bg-[#f1f5f9] p-8 }
h1 { text-[#0ea5e9] text-4xl font-bold text-center mb-8 }
h2 { text-[#0369a1] text-2xl font-semibold mb-4 }
.demo-grid { flex flex-wrap gap-6 justify-center }
.demo-item { bg-white p-6 rounded-xl shadow-lg }
.image-container { w-[300px] h-[200px] border-2 border-[#cbd5e1] rounded-lg overflow-hidden mb-4 }
.code-block { bg-[#1e293b] text-[#e2e8f0] p-3 rounded font-mono text-sm }
.description { text-[#475569] text-sm mb-2 }
</style>
</head>
<body>
<h1>🖼️ Object-Fit CSS Demonstration</h1>
<div style="demo-grid">
<!-- Object-fit: none (STRETCH_KEEP) -->
<div style="demo-item">
<h2>object-none</h2>
<div style="description">Image keeps original size, may overflow container</div>
<div style="image-container">
<img src="https://picsum.photos/400/700?random=1" style="w-full h-full object-none" />
</div>
<div style="code-block">object-none</div>
</div>
<!-- Object-fit: fill (STRETCH_SCALE) -->
<div style="demo-item">
<h2>object-fill</h2>
<div style="description">Image fills container, may distort aspect ratio</div>
<div style="image-container">
<img src="https://picsum.photos/500/600?random=2" style="w-full h-full object-fill" />
</div>
<div style="code-block">object-fill</div>
</div>
<!-- Object-fit: contain (STRETCH_KEEP_ASPECT) -->
<div style="demo-item">
<h2>object-contain</h2>
<div style="description">Image fits inside container while preserving aspect ratio</div>
<div style="image-container">
<img src="https://picsum.photos/700/600?random=3" style="w-full h-full object-contain" />
</div>
<div style="code-block">object-contain</div>
</div>
<!-- Object-fit: cover (STRETCH_KEEP_ASPECT_COVERED) -->
<div style="demo-item">
<h2>object-cover</h2>
<div style="description">Image covers entire container while preserving aspect ratio</div>
<div style="image-container">
<img src="https://picsum.photos/200/300?random=4" style="w-full h-full object-cover" />
</div>
<div style="code-block">object-cover</div>
</div>
</div>
<div style="bg-white p-6 rounded-xl shadow-lg mt-8 max-w-4xl mx-auto">
<h2>📝 Object-fit Property Mapping</h2>
<div style="text-[#475569]">
<p><strong>object-none:</strong> Godot's STRETCH_KEEP - Image keeps original dimensions</p>
<p><strong>object-fill:</strong> Godot's STRETCH_SCALE - Image stretches to fill container</p>
<p><strong>object-contain:</strong> Godot's STRETCH_KEEP_ASPECT - Image fits inside with preserved aspect ratio</p>
<p><strong>object-cover:</strong> Godot's STRETCH_KEEP_ASPECT_COVERED - Image covers container with preserved aspect ratio</p>
</div>
</div>
</body>

195
tests/signal.html Normal file
View File

@@ -0,0 +1,195 @@
<head>
<title>Signal API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#8b5cf6">
<meta name="description" content="Demonstrating the new Signal API with custom events">
<style>
body { bg-[#f8fafc] p-6 }
h1 { text-[#8b5cf6] text-3xl font-bold text-center }
h2 { text-[#6d28d9] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.signal-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors }
.fire-btn { bg-[#10b981] text-white hover:bg-[#059669] }
.connect-btn { bg-[#3b82f6] text-white hover:bg-[#2563eb] }
.disconnect-btn { bg-[#ef4444] text-white hover:bg-[#dc2626] }
.log-area { bg-[#f1f5f9] p-4 rounded-lg min-h-32 font-mono text-sm }
.status-display { bg-[#ddd6fe] p-3 rounded-md text-[#5b21b6] font-mono }
.info-box { bg-[#fef3c7] border border-[#f59e0b] p-4 rounded-lg }
</style>
<script>
-- Create custom signals
local mySignal = Signal.new()
local dataSignal = Signal.new()
local userActionSignal = Signal.new()
print(".container > div: ", gurt.selectAll('.container > div'))
print(".container div: ", gurt.selectAll('.container div'))
print("button[disabled]: ", gurt.selectAll('button[disabled]'))
print(".container: ", gurt.selectAll('.container'))
print("#log-area: ", gurt.selectAll('#log-area'))
-- Get UI elements
local logArea = gurt.select('#log-area')
local statusDisplay = gurt.select('#status-display')
local connectBtn = gurt.select('#connect-btn')
local disconnectBtn = gurt.select('#disconnect-btn')
local fireBtn = gurt.select('#fire-btn')
local fireDataBtn = gurt.select('#fire-data-btn')
local clearLogBtn = gurt.select('#clear-log-btn')
gurt.log('Signal API demo script started.')
local logMessages = {}
local connectionCount = 0
local activeConnections = {}
-- Function to add message to log
local function addLog(message)
table.insert(logMessages, Time.format(Time.now(), '%H:%M:%S') .. ' - ' .. message)
if #logMessages > 20 then
table.remove(logMessages, 1)
end
logArea.text = table.concat(logMessages, '\\n')
end
-- Function to update status
local function updateStatus()
statusDisplay.text = 'Active Connections: ' .. #activeConnections .. '\\nTotal Events Fired: ' .. connectionCount
end
-- Signal handlers
local function onMySignal(arg1, arg2)
addLog('mySignal fired with args: ' .. (arg1 or 'nil') .. ', ' .. (arg2 or 'nil'))
end
local function onDataSignal(data)
addLog('dataSignal received: ' .. table.tostring(data))
end
local function onUserAction(action, timestamp)
addLog('userActionSignal: ' .. action .. ' at ' .. timestamp)
end
-- Connect button
connectBtn:on('click', function()
-- Connect multiple handlers to demonstrate multiple connections
local conn1 = mySignal:connect(onMySignal)
local conn2 = dataSignal:connect(onDataSignal)
local conn3 = userActionSignal:connect(onUserAction)
table.insert(activeConnections, conn1)
table.insert(activeConnections, conn2)
table.insert(activeConnections, conn3)
addLog('Connected 3 signal handlers')
updateStatus()
end)
-- Disconnect button
disconnectBtn:on('click', function()
for i = 1, #activeConnections do
activeConnections[i]:disconnect()
end
activeConnections = {}
addLog('Disconnected all signal handlers')
updateStatus()
end)
-- Fire simple signal
fireBtn:on('click', function()
mySignal:fire('Hello', 123)
connectionCount = connectionCount + 1
addLog('Fired mySignal with two arguments')
updateStatus()
end)
-- Fire data signal
fireDataBtn:on('click', function()
local sampleData = {
user = 'Alice',
score = math.random(100, 999),
items = {'sword', 'shield', 'potion'}
}
dataSignal:fire(sampleData)
connectionCount = connectionCount + 1
addLog('Fired dataSignal with complex data')
updateStatus()
end)
-- Fire user action signal
gurt.body:on('keypress', function(keyInfo)
if #activeConnections > 0 then
userActionSignal:fire('keypress: ' .. keyInfo.key, Time.format(Time.now(), '%H:%M:%S'))
connectionCount = connectionCount + 1
updateStatus()
end
end)
-- Clear log button
clearLogBtn:on('click', function()
logMessages = {}
logArea.text = 'Log cleared.'
addLog('Log area cleared')
end)
-- Initialize with some sample connections
local initialConn = mySignal:connect(function(a, b)
addLog('Initial handler triggered with: ' .. (a or 'nil') .. ', ' .. (b or 'nil'))
end)
table.insert(activeConnections, initialConn)
addLog('Signal API demo initialized')
addLog('Try connecting handlers and firing signals!')
addLog('Press any key to trigger userActionSignal (when connected)')
updateStatus()
</script>
</head>
<body>
<h1>🔔 Signal API Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<p><strong>Signal API Usage Example:</strong></p>
<p><code>local mySignal = Signal.new()</code></p>
<p><code>mySignal:connect(function(arg1, arg2) print("Event fired with: ", arg1, arg2) end)</code></p>
<p><code>mySignal:fire("Hello", 123)</code></p>
<p><code>connection:disconnect()</code></p>
</div>
<h2>Controls</h2>
<div style="button-group mb-6">
<button id="connect-btn" style="signal-button connect-btn">🔗 Connect Handlers</button>
<button id="disconnect-btn" style="signal-button disconnect-btn">❌ Disconnect All</button>
<button id="fire-btn" style="signal-button fire-btn">🔔 Fire Simple Signal</button>
<button id="fire-data-btn" style="signal-button fire-btn">📊 Fire Data Signal</button>
<button id="clear-log-btn" style="signal-button">🧹 Clear Log</button>
</div>
<h2>Status</h2>
<div style="status-display mb-6">
<pre id="status-display">Loading status...</pre>
</div>
<h2>Event Log</h2>
<div style="log-area mb-6">
<pre id="log-area">Initializing...</pre>
</div>
<div style="bg-[#e0f2fe] p-4 rounded-lg">
<h3 style="text-[#0277bd] font-semibold mb-2">Signal API Features:</h3>
<ul style="text-[#01579b] space-y-1">
<li><strong>Signal.new():</strong> Creates a new signal object</li>
<li><strong>signal:connect(callback):</strong> Connects a callback function and returns a connection object</li>
<li><strong>signal:fire(...):</strong> Fires the signal with optional arguments</li>
<li><strong>connection:disconnect():</strong> Disconnects a specific connection</li>
<li><strong>signal:disconnect():</strong> Disconnects all connections from the signal</li>
<li><strong>Multiple Connections:</strong> One signal can have multiple connected callbacks</li>
<li><strong>Argument Passing:</strong> Signals can pass multiple arguments to connected callbacks</li>
</ul>
</div>
<button disabled="true">Test</button>
<button disabled="true">Test2</button>
</div>
</body>

132
tests/transform.html Normal file
View File

@@ -0,0 +1,132 @@
<head>
<title>Transform CSS Demo - Scale & Rotation</title>
<icon src="https://picsum.photos/32/32?random=1">
<meta name="theme-color" content="#8b5cf6">
<meta name="description" content="Testing scale and rotation CSS utilities">
<style>
body { bg-[#f8fafc] p-8 }
h1 { text-[#8b5cf6] text-4xl font-bold text-center mb-8 }
h2 { text-[#7c3aed] text-2xl font-semibold mb-4 }
.demo-grid { flex flex-wrap gap-6 justify-center }
.demo-item { bg-white p-6 rounded-xl shadow-lg text-center }
.demo-box { w-[100px] h-[100px] bg-[#3b82f6] text-white text-xl font-bold rounded-lg flex items-center justify-center mb-4 mx-auto }
.code-block { bg-[#1e293b] text-[#e2e8f0] p-3 rounded font-mono text-sm }
.description { text-[#64748b] text-sm mb-3 }
</style>
</head>
<body>
<h1>🔄 Scale & Rotation CSS Demonstration</h1>
<div style="demo-grid">
<!-- Normal (no transform) -->
<div style="demo-item">
<h2>Normal</h2>
<div style="description">No transform applied</div>
<div style="demo-box">Box</div>
<div style="code-block">No transform</div>
</div>
<!-- Scale 50% -->
<div style="demo-item">
<h2>Scale 50%</h2>
<div style="description">Scaled to 50% size</div>
<div style="demo-box scale-50">Box</div>
<div style="code-block">scale-50</div>
</div>
<!-- Scale 150% -->
<div style="demo-item">
<h2>Scale 150%</h2>
<div style="description">Scaled to 150% size</div>
<div style="demo-box scale-150">Box</div>
<div style="code-block">scale-150</div>
</div>
<!-- Scale X-axis only -->
<div style="demo-item">
<h2>Scale X 75%</h2>
<div style="description">X-axis scaled to 75%</div>
<div style="demo-box scale-x-75">Box</div>
<div style="code-block">scale-x-75</div>
</div>
<!-- Scale Y-axis only -->
<div style="demo-item">
<h2>Scale Y 125%</h2>
<div style="description">Y-axis scaled to 125%</div>
<div style="demo-box scale-y-125">Box</div>
<div style="code-block">scale-y-125</div>
</div>
<!-- Custom scale with bracket notation -->
<div style="demo-item">
<h2>Custom Scale</h2>
<div style="description">Custom scale value 1.7</div>
<div style="demo-box scale-[170]">Box</div>
<div style="code-block">scale-[170]</div>
</div>
<!-- Rotate 45 degrees -->
<div style="demo-item">
<h2>Rotate 45°</h2>
<div style="description">Rotated 45 degrees</div>
<div style="demo-box rotate-45">Box</div>
<div style="code-block">rotate-45</div>
</div>
<!-- Rotate 90 degrees -->
<div style="demo-item">
<h2>Rotate 90°</h2>
<div style="description">Rotated 90 degrees</div>
<div style="demo-box rotate-90">Box</div>
<div style="code-block">rotate-90</div>
</div>
<!-- Custom rotation with bracket notation -->
<div style="demo-item">
<h2>Custom Rotate</h2>
<div style="description">Custom rotation 30deg</div>
<div style="demo-box rotate-[30deg]">Box</div>
<div style="code-block">rotate-[30deg]</div>
</div>
<!-- Combined scale and rotation -->
<div style="demo-item">
<h2>Scale + Rotate</h2>
<div style="description">Scale 125% and rotate 45°</div>
<div style="demo-box scale-125 rotate-45">Box</div>
<div style="code-block">scale-125 rotate-45</div>
</div>
<!-- Rotation in radians -->
<div style="demo-item">
<h2>Radians</h2>
<div style="description">Rotation using radians</div>
<div style="demo-box rotate-[1.57rad]">Box</div>
<div style="code-block">rotate-[1.57rad]</div>
</div>
<!-- Hover effects with transforms -->
<div style="demo-item">
<h2>Hover Effect</h2>
<div style="description">Hover to see scale effect</div>
<div style="demo-box hover:scale-110 transition hover:rotate-45">Box</div>
<div style="code-block">hover:scale-110</div>
</div>
</div>
<button style="hover:scale-110 transition">Button</button>
<div style="bg-white p-6 rounded-xl shadow-lg mt-8 max-w-4xl mx-auto">
<h2>📝 Transform Utility Reference</h2>
<div style="text-[#475569]">
<p><strong>Scale utilities:</strong> scale-{value}, scale-x-{value}, scale-y-{value}</p>
<p><strong>Named values:</strong> 0, 50, 75, 90, 95, 100, 105, 110, 125, 150, 200</p>
<p><strong>Custom values:</strong> scale-[{number}] where number is percentage (100 = 1.0)</p>
<p><strong>Rotation utilities:</strong> rotate-{degrees}, rotate-x-{degrees}, rotate-y-{degrees}</p>
<p><strong>Named degrees:</strong> 0, 1, 2, 3, 6, 12, 45, 90, 180, 270</p>
<p><strong>Custom rotations:</strong> rotate-[{value}deg], rotate-[{value}rad], rotate-[{value}turn]</p>
</div>
</div>
</body>

264
tests/tween.html Normal file
View File

@@ -0,0 +1,264 @@
<head>
<title>Tween Animation Demo</title>
<icon src="https://cdn-icons-png.flaticon.com/512/1828/1828774.png">
<meta name="theme-color" content="#1a202c">
<meta name="description" content="Demonstrating Lua Tween animations">
<style>
body { bg-[#0f1629] text-[#ffffff] p-6 font-sans }
h1 { text-[#60a5fa] text-4xl font-bold text-center mb-6 }
h2 { text-[#a78bfa] text-2xl font-bold mt-8 mb-4 }
.container { bg-[#1e293b] p-6 rounded-lg shadow-lg mb-6 }
.demo-box {
bg-[#3b82f6]
w-[100px]
h-[100px]
rounded-lg
flex
items-center
justify-center
text-[#ffffff]
font-bold
cursor-pointer
mb-4
}
.control-panel {
flex
flex-row
gap-2
flex-wrap
justify-center
mt-4
}
button {
bg-[#059669]
text-[#ffffff]
px-4
py-2
rounded
hover:bg-[#047857]
active:bg-[#065f46]
cursor-pointer
}
.reset-btn { bg-[#dc2626] hover:bg-[#b91c1c] active:bg-[#991b1b] }
.warning { text-[#fbbf24] bg-[#451a03] p-4 rounded border-l-4 border-[#f59e0b] }
</style>
<script>
-- Get references to all demo elements
local fadeBox = gurt.select('#fade-box')
local colorBox = gurt.select('#color-box')
local scaleBox = gurt.select('#scale-box')
local rotateBox = gurt.select('#rotate-box')
local moveBox = gurt.select('#move-box')
local comboBox = gurt.select('#combo-box')
gurt.log('Tween animation demo started!')
-- Fade Animation
gurt.select('#fade-btn'):on('click', function()
fadeBox:createTween():to('opacity', 0):duration(1.0):easing('out'):transition('linear'):play()
end)
gurt.select('#fade-restore-btn'):on('click', function()
fadeBox:createTween():to('opacity', 1):duration(0.5):easing('in'):transition('linear'):play()
end)
-- Color Animation
gurt.select('#color-btn'):on('click', function()
colorBox:createTween():to('backgroundColor', '#ff0000'):duration(1.0):easing('inout'):transition('quad'):play()
end)
gurt.select('#color-restore-btn'):on('click', function()
colorBox:createTween():to('backgroundColor', '#3b82f6'):duration(1.0):easing('inout'):transition('quad'):play()
end)
-- Scale Animation
gurt.select('#scale-btn'):on('click', function()
scaleBox:createTween():to('scale', 1.5):duration(1.0):easing('out'):transition('cubic'):play()
end)
gurt.select('#scale-restore-btn'):on('click', function()
scaleBox:createTween():to('scale', 1.0):duration(0.8):easing('in'):transition('cubic'):play()
end)
-- Rotation Animation
gurt.select('#rotate-btn'):on('click', function()
rotateBox:createTween():to('rotation', 360):duration(2.0):easing('inout'):transition('sine'):play()
end)
gurt.select('#rotate-restore-btn'):on('click', function()
rotateBox:createTween():to('rotation', 0):duration(1.0):easing('out'):transition('sine'):play()
end)
-- Movement Animation
gurt.select('#move-btn'):on('click', function()
moveBox:createTween():to('x', 200):duration(1.5):easing('out'):transition('elastic'):play()
end)
gurt.select('#move-restore-btn'):on('click', function()
moveBox:createTween():to('x', 0):duration(1.0):easing('in'):transition('elastic'):play()
end)
-- Complex Parallel Animation
gurt.select('#combo-btn'):on('click', function()
local tween = comboBox:createTween()
tween:parallel()
tween:to('scale', 1.3):duration(1.0):easing('out'):transition('back')
tween:to('rotation', 180):duration(1.0):easing('out'):transition('sine')
tween:to('backgroundColor', '#10b981'):duration(1.0):easing('out'):transition('linear')
tween:play()
end)
-- Complex Chain Animation
gurt.select('#chain-btn'):on('click', function()
local tween = comboBox:createTween()
tween:chain()
tween:to('x', 150):duration(0.8):easing('out'):transition('bounce')
tween:to('y', -50):duration(0.8):easing('out'):transition('bounce')
tween:to('x', 0):duration(0.8):easing('out'):transition('bounce')
tween:to('y', 0):duration(0.8):easing('out'):transition('bounce')
tween:play()
end)
-- Reset all animations
gurt.select('#reset-all-btn'):on('click', function()
-- Reset all properties to default
fadeBox:createTween():to('opacity', 1):duration(0.3):play()
colorBox:createTween():to('backgroundColor', '#3b82f6'):duration(0.3):play()
scaleBox:createTween():to('scale', 1.0):duration(0.3):play()
rotateBox:createTween():to('rotation', 0):duration(0.3):play()
moveBox:createTween():to('x', 0):duration(0.3):play()
local combo_tween = comboBox:createTween()
combo_tween:parallel()
combo_tween:to('scale', 1.0):duration(0.3)
combo_tween:to('rotation', 0):duration(0.3)
combo_tween:to('backgroundColor', '#3b82f6'):duration(0.3)
combo_tween:to('x', 0):duration(0.3)
combo_tween:to('y', 0):duration(0.3)
combo_tween:play()
end)
-- Callback example
gurt.select('#callback-btn'):on('click', function()
fadeBox:createTween():to('opacity', 0.3):duration(1.0):easing('inout'):callback(function()
gurt.log('Fade animation completed!')
end):play()
end)
-- Loops example
gurt.select('#steps-btn'):on('click', function()
scaleBox:createTween():loops(3)
:to('scale', 2.0):duration(0.5)
:to('scale', 1.0):duration(0.5)
:callback(function()
print('Animation completed!')
end):play()
end)
</script>
</head>
<body>
<h1>🎬 Lua Tween Animation Demo</h1>
<div style="warning">
<p><strong>Note:</strong> This demo showcases the Lua Tween API for smooth animations. Each box demonstrates different animation properties and easing functions.</p>
</div>
<h2>Fade Animation</h2>
<div style="container">
<div id="fade-box" style="demo-box">Fade Me</div>
<div style="control-panel">
<button id="fade-btn">Fade Out</button>
<button id="fade-restore-btn">Fade In</button>
<button id="callback-btn">Fade with Callback</button>
</div>
</div>
<h2>Color Animation</h2>
<div style="container">
<div id="color-box" style="demo-box">Change Color</div>
<div style="control-panel">
<button id="color-btn">To Red</button>
<button id="color-restore-btn">To Blue</button>
</div>
</div>
<h2>Scale Animation</h2>
<div style="container">
<div id="scale-box" style="demo-box">Scale Me</div>
<div style="control-panel">
<button id="scale-btn">Scale Up</button>
<button id="scale-restore-btn">Scale Down</button>
<button id="steps-btn">Pulse (Loop)</button>
</div>
</div>
<h2>Rotation Animation</h2>
<div style="container">
<div id="rotate-box" style="demo-box">Spin Me</div>
<div style="control-panel">
<button id="rotate-btn">Rotate 360°</button>
<button id="rotate-restore-btn">Reset Rotation</button>
</div>
</div>
<h2>Movement Animation</h2>
<div style="container">
<div id="move-box" style="demo-box">Move Me</div>
<div style="control-panel">
<button id="move-btn">Move Right</button>
<button id="move-restore-btn">Move Back</button>
</div>
</div>
<h2>Complex Animations</h2>
<div style="container">
<div id="combo-box" style="demo-box">Complex</div>
<div style="control-panel">
<button id="combo-btn">Parallel Animation</button>
<button id="chain-btn">Chain Animation</button>
</div>
</div>
<div style="control-panel mt-8">
<button id="reset-all-btn" style="reset-btn">🔄 Reset All Animations</button>
</div>
<div style="container mt-8">
<h2>Available Tween Methods:</h2>
<ul style="list-disc pl-6 text-[#d1d5db]">
<li><strong>element:createTween()</strong> - Create a new tween for the element</li>
<li><strong>tween:to(property, target_value, duration, easing)</strong> - Animate to a target value</li>
<li><strong>tween:from(property, start_value, duration, easing)</strong> - Animate from a start value</li>
<li><strong>tween:parallel()</strong> - Set tween to run animations in parallel</li>
<li><strong>tween:chain()</strong> - Set tween to run animations in sequence</li>
<li><strong>tween:steps(count)</strong> - Set number of loops</li>
<li><strong>tween:callback(function)</strong> - Execute function when tween completes</li>
<li><strong>tween:play()</strong> - Start the tween animation</li>
<li><strong>tween:stop()</strong> - Stop the tween animation</li>
<li><strong>tween:pause()</strong> - Pause the tween animation</li>
<li><strong>tween:resume()</strong> - Resume the tween animation</li>
</ul>
<h2 style="mt-4">Supported Properties:</h2>
<ul style="list-disc pl-6 text-[#d1d5db]">
<li><strong>opacity</strong> - Element transparency (0-1)</li>
<li><strong>backgroundColor</strong> - Background color (hex/color names)</li>
<li><strong>color/textColor</strong> - Text color (hex/color names)</li>
<li><strong>width/height</strong> - Element dimensions (pixels)</li>
<li><strong>x/y</strong> - Position coordinates (pixels)</li>
<li><strong>scale</strong> - Element scale factor</li>
<li><strong>rotation</strong> - Rotation angle (degrees)</li>
</ul>
<h2 style="mt-4">Easing Functions:</h2>
<ul style="list-disc pl-6 text-[#d1d5db]">
<li><strong>easeIn</strong> - Slow start, fast end</li>
<li><strong>easeOut</strong> - Fast start, slow end</li>
<li><strong>easeInOut</strong> - Slow start and end, fast middle</li>
<li><strong>easeOutIn</strong> - Fast start and end, slow middle</li>
</ul>
</div>
</body>

211
tests/websocket.html Normal file
View File

@@ -0,0 +1,211 @@
<head>
<title>WebSocket API Demo</title>
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
<meta name="theme-color" content="#059669">
<meta name="description" content="Demonstrating WebSocket real-time communication API">
<style>
body { bg-[#f0fdf4] p-6 }
h1 { text-[#059669] text-3xl font-bold text-center }
h2 { text-[#047857] text-xl font-semibold }
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
.button-group { flex gap-3 justify-center items-center flex-wrap }
.ws-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#10b981] text-white hover:bg-[#059669] }
.send-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#3b82f6] text-white hover:bg-[#2563eb] }
.disconnect-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#ef4444] text-white hover:bg-[#dc2626] }
.clear-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#6b7280] text-white hover:bg-[#4b5563] }
.log-area { bg-[#f1f5f9] p-4 rounded-lg min-h-32 font-mono text-sm max-h-96 overflow-auto }
.info-box { bg-[#dbeafe] border border-[#3b82f6] p-4 rounded-lg }
.input-area { bg-[#f9fafb] p-4 rounded-lg border }
.status-connected { text-[#059669] font-bold }
.status-disconnected { text-[#ef4444] font-bold }
.status-connecting { text-[#f59e0b] font-bold }
</style>
<script>
-- Get UI elements
local logArea = gurt.select('#log-area')
local statusDisplay = gurt.select('#status-display')
local connectBtn = gurt.select('#connect-btn')
local disconnectBtn = gurt.select('#disconnect-btn')
local sendBtn = gurt.select('#send-btn')
local clearLogBtn = gurt.select('#clear-log-btn')
local urlInput = gurt.select('#url-input')
local messageInput = gurt.select('#message-input')
gurt.log('WebSocket API demo script started.')
local logMessages = {}
local socket = nil
local connected = false
-- Function to add message to log
local function addLog(message)
table.insert(logMessages, Time.format(Time.now(), '%H:%M:%S') .. ' - ' .. message)
if #logMessages > 50 then
table.remove(logMessages, 1)
end
logArea.text = table.concat(logMessages, '\\n')
end
-- Function to update status display
local function updateStatus(status, color)
statusDisplay.text = 'Status: ' .. status
statusDisplay.style = 'status-' .. color
end
-- Initialize with default values
urlInput.text = 'wss://echo.websocket.org'
messageInput.text = 'Hello from Gurted!'
-- Connect to WebSocket
connectBtn:on('click', function()
local url = urlInput.text
addLog('Attempting to connect to: ' .. url)
updateStatus('Connecting...', 'connecting')
socket = WebSocket:new(url)
socket:on('open', function()
addLog('✅ Connected to WebSocket server!')
updateStatus('Connected', 'connected')
connected = true
socket:send('Hello from the Gurted web!')
end)
socket:on('message', function(event)
addLog('📨 Received: ' .. event.data)
end)
socket:on('close', function()
addLog('❌ Connection closed')
updateStatus('Disconnected', 'disconnected')
connected = false
end)
socket:on('error', function(event)
addLog('🚨 Error: ' .. (event.message or 'Unknown error'))
updateStatus('Error', 'disconnected')
connected = false
end)
end)
-- Disconnect from WebSocket
disconnectBtn:on('click', function()
if socket and connected then
addLog('Disconnecting from WebSocket...')
socket:close()
else
addLog('No active connection to disconnect')
end
end)
-- Send message
sendBtn:on('click', function()
if socket and connected then
local message = messageInput.text
if message and message ~= '' then
socket:send(message)
addLog('📤 Sent: ' .. message)
else
addLog('❌ Cannot send empty message')
end
else
addLog('❌ Not connected to WebSocket server')
end
end)
-- Clear log button
clearLogBtn:on('click', function()
logMessages = {}
logArea.text = 'Log cleared.'
addLog('WebSocket API demo ready')
end)
-- Allow Enter key to send messages
messageInput:on('keypress', function(e)
if e.key == 'Enter' and socket and connected then
local message = messageInput.text
if message and message ~= '' then
socket:send(message)
addLog('📤 Sent: ' .. message)
messageInput.text = ''
end
end
end)
-- Initialize
updateStatus('Disconnected', 'disconnected')
addLog('WebSocket API demo ready')
addLog('Enter a WebSocket URL and click Connect to start!')
</script>
</head>
<body>
<h1>🔌 WebSocket API Demo</h1>
<div style="container mt-6">
<div style="info-box mb-6">
<h3 style="text-[#1e40af] font-semibold mb-2">WebSocket API Usage:</h3>
<p><code>local socket = WebSocket:new(url)</code></p>
<p><code>socket:on('open', function() ... end)</code></p>
<p><code>socket:on('message', function(event) print(event.data) end)</code></p>
<p><code>socket:send('Hello Server!')</code></p>
<p><code>socket:close()</code></p>
</div>
<h2>Connection</h2>
<div style="input-area mb-6">
<div style="flex flex-col gap-3">
<div>
<label style="block text-sm font-medium mb-1">WebSocket URL:</label>
<input id="url-input" type="text" style="w-full p-2 border border-gray-300 rounded-md" placeholder="ws://echo.websocket.org" />
</div>
<div id="status-display" style="status-disconnected">Status: Disconnected</div>
<div style="flex gap-2">
<button id="connect-btn" style="ws-button">🔗 Connect</button>
<button id="disconnect-btn" style="disconnect-button">❌ Disconnect</button>
</div>
</div>
</div>
<h2>Send Messages</h2>
<div style="input-area mb-6">
<div style="flex flex-col gap-3">
<div>
<label style="block text-sm font-medium mb-1">Message:</label>
<input id="message-input" type="text" style="w-full p-2 border border-gray-300 rounded-md" placeholder="Type your message..." />
</div>
<div style="flex gap-2">
<button id="send-btn" style="send-button">📤 Send Message</button>
<span style="text-sm text-gray-600">Or press Enter to send</span>
</div>
</div>
</div>
<h2>Event Log</h2>
<div style="button-group mb-3">
<button id="clear-log-btn" style="clear-button">🧹 Clear Log</button>
</div>
<div style="log-area mb-6">
<pre id="log-area">Initializing...</pre>
</div>
<div style="bg-[#f0f9ff] p-4 rounded-lg">
<h3 style="text-[#0369a1] font-semibold mb-2">WebSocket Events:</h3>
<ul style="text-[#075985] space-y-1 text-sm">
<li><strong>open:</strong> Fired when connection is established</li>
<li><strong>message:</strong> Fired when a message is received (event.data contains the message)</li>
<li><strong>close:</strong> Fired when connection is closed</li>
<li><strong>error:</strong> Fired when an error occurs (event.message contains error info)</li>
</ul>
<h3 style="text-[#0369a1] font-semibold mt-4 mb-2">WebSocket Methods:</h3>
<ul style="text-[#075985] space-y-1 text-sm">
<li><strong>WebSocket:new(url):</strong> Creates and connects to WebSocket server</li>
<li><strong>socket:send(message):</strong> Sends a text message to the server</li>
<li><strong>socket:close():</strong> Closes the connection</li>
<li><strong>socket:on(event, callback):</strong> Registers event handlers</li>
</ul>
</div>
</div>
</body>