This commit is contained in:
2026-01-25 02:47:47 +01:00
parent 8c1a721c4c
commit 957e3a4762
74 changed files with 7749 additions and 292 deletions
+396
View File
@@ -0,0 +1,396 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>argparse - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="index.html">Overview</a></li>
<li><a href="http.html">http</a></li>
<li><a href="websocket.html">websocket</a></li>
<li><a href="tls.html">tls</a></li>
<li><a href="net.html">net</a></li>
<li><a href="dns.html">dns</a></li>
<li><a href="json.html">json</a></li>
<li><a href="base64.html">base64</a></li>
<li><a href="regex.html">regex</a></li>
<li><a href="jinja.html">jinja</a></li>
<li><a href="crypto.html">crypto</a></li>
<li><a href="os.html">os</a></li>
<li><a href="env.html">env</a></li>
<li><a href="signal.html">signal</a></li>
<li><a href="subprocess.html">subprocess</a></li>
<li><a href="sqlite.html">sqlite</a></li>
<li><a href="datetime.html">datetime</a></li>
<li><a href="timer.html">timer</a></li>
<li><a href="io.html">io</a></li>
<li><a href="scheduler.html">scheduler</a></li>
<li><a href="math.html">math</a></li>
<li><a href="uuid.html">uuid</a></li>
<li><a href="html.html">html</a></li>
<li><a href="argparse.html" class="active">argparse</a></li>
<li><a href="wdantic.html">wdantic</a></li>
<li><a href="dataset.html">dataset</a></li>
<li><a href="markdown.html">markdown</a></li>
<li><a href="web.html">web</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="../howto/index.html">How-To List</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">API Reference</a>
<span class="separator">/</span>
<span>argparse</span>
</nav>
<article>
<h1>argparse</h1>
<p>The <code>argparse</code> module provides command-line argument parsing with support for positional arguments, optional flags, type conversion, and help generation.</p>
<pre><code>import "argparse" for ArgumentParser</code></pre>
<h2>ArgumentParser Class</h2>
<div class="class-header">
<h3>ArgumentParser</h3>
<p>Command-line argument parser</p>
</div>
<h3>Constructors</h3>
<div class="method-signature">
<span class="method-name">ArgumentParser.new</span>() → <span class="type">ArgumentParser</span>
</div>
<p>Creates a new argument parser with no description.</p>
<div class="method-signature">
<span class="method-name">ArgumentParser.new</span>(<span class="param">description</span>) → <span class="type">ArgumentParser</span>
</div>
<p>Creates a new argument parser with a description shown in help.</p>
<ul class="param-list">
<li><span class="param-name">description</span> <span class="param-type">(String)</span> - Description of the program</li>
</ul>
<h3>Properties</h3>
<div class="method-signature">
<span class="method-name">prog</span><span class="type">String</span>
</div>
<p>Gets or sets the program name shown in help output.</p>
<div class="method-signature">
<span class="method-name">description</span><span class="type">String</span>
</div>
<p>Gets or sets the program description.</p>
<h3>Instance Methods</h3>
<div class="method-signature">
<span class="method-name">addArgument</span>(<span class="param">name</span>) → <span class="type">ArgumentParser</span>
</div>
<p>Adds an argument with default options. Returns the parser for chaining.</p>
<ul class="param-list">
<li><span class="param-name">name</span> <span class="param-type">(String)</span> - Argument name (positional) or flag (starts with <code>-</code>)</li>
</ul>
<div class="method-signature">
<span class="method-name">addArgument</span>(<span class="param">name</span>, <span class="param">options</span>) → <span class="type">ArgumentParser</span>
</div>
<p>Adds an argument with specified options.</p>
<ul class="param-list">
<li><span class="param-name">name</span> <span class="param-type">(String)</span> - Argument name or flag</li>
<li><span class="param-name">options</span> <span class="param-type">(Map)</span> - Configuration options</li>
</ul>
<div class="method-signature">
<span class="method-name">parseArgs</span>() → <span class="type">Map</span>
</div>
<p>Parses arguments from <code>Process.arguments</code>.</p>
<div class="method-signature">
<span class="method-name">parseArgs</span>(<span class="param">args</span>) → <span class="type">Map</span>
</div>
<p>Parses the provided argument list.</p>
<ul class="param-list">
<li><span class="param-name">args</span> <span class="param-type">(List)</span> - List of argument strings</li>
<li><span class="returns">Returns:</span> Map of argument names to values</li>
</ul>
<div class="method-signature">
<span class="method-name">printHelp</span>()
</div>
<p>Prints formatted help information to stdout.</p>
<h2>Argument Options</h2>
<table>
<tr>
<th>Option</th>
<th>Type</th>
<th>Description</th>
</tr>
<tr>
<td><code>long</code></td>
<td>String</td>
<td>Long form of the flag (e.g., <code>--verbose</code>)</td>
</tr>
<tr>
<td><code>type</code></td>
<td>String</td>
<td><code>"string"</code>, <code>"int"</code>, <code>"float"</code>, or <code>"bool"</code></td>
</tr>
<tr>
<td><code>default</code></td>
<td>any</td>
<td>Default value if not provided</td>
</tr>
<tr>
<td><code>required</code></td>
<td>Bool</td>
<td>Whether the argument is required</td>
</tr>
<tr>
<td><code>help</code></td>
<td>String</td>
<td>Help text description</td>
</tr>
<tr>
<td><code>choices</code></td>
<td>List</td>
<td>List of valid values</td>
</tr>
<tr>
<td><code>action</code></td>
<td>String</td>
<td>How to handle the argument</td>
</tr>
<tr>
<td><code>nargs</code></td>
<td>String/Num</td>
<td>Number of values to consume</td>
</tr>
<tr>
<td><code>dest</code></td>
<td>String</td>
<td>Name for the result map key</td>
</tr>
</table>
<h2>Actions</h2>
<table>
<tr>
<th>Action</th>
<th>Description</th>
</tr>
<tr>
<td><code>store</code></td>
<td>Store the value (default)</td>
</tr>
<tr>
<td><code>storeTrue</code></td>
<td>Store <code>true</code> when flag is present</td>
</tr>
<tr>
<td><code>storeFalse</code></td>
<td>Store <code>false</code> when flag is present</td>
</tr>
<tr>
<td><code>count</code></td>
<td>Count occurrences of the flag</td>
</tr>
<tr>
<td><code>append</code></td>
<td>Append values to a list</td>
</tr>
</table>
<h2>Nargs Values</h2>
<table>
<tr>
<th>Value</th>
<th>Description</th>
</tr>
<tr>
<td><code>*</code></td>
<td>Zero or more values (returns list)</td>
</tr>
<tr>
<td><code>+</code></td>
<td>One or more values (returns list)</td>
</tr>
<tr>
<td><code>N</code> (number)</td>
<td>Exactly N values (returns list)</td>
</tr>
</table>
<h2>Examples</h2>
<h3>Basic Usage</h3>
<pre><code>import "argparse" for ArgumentParser
var parser = ArgumentParser.new("File processing utility")
parser.prog = "myapp"
parser.addArgument("filename", {"help": "Input file to process"})
parser.addArgument("-o", {
"long": "--output",
"help": "Output file path",
"default": "output.txt"
})
var args = parser.parseArgs()
System.print("Input: %(args["filename"])")
System.print("Output: %(args["output"])")</code></pre>
<h3>Boolean Flags</h3>
<pre><code>import "argparse" for ArgumentParser
var parser = ArgumentParser.new()
parser.addArgument("-v", {
"long": "--verbose",
"action": "storeTrue",
"help": "Enable verbose output"
})
parser.addArgument("-q", {
"long": "--quiet",
"action": "storeFalse",
"dest": "verbose",
"help": "Disable verbose output"
})
var args = parser.parseArgs(["-v"])
System.print(args["verbose"]) // true</code></pre>
<h3>Type Conversion</h3>
<pre><code>import "argparse" for ArgumentParser
var parser = ArgumentParser.new()
parser.addArgument("-n", {
"long": "--count",
"type": "int",
"default": 1,
"help": "Number of iterations"
})
parser.addArgument("-t", {
"long": "--threshold",
"type": "float",
"default": 0.5,
"help": "Detection threshold"
})
var args = parser.parseArgs(["-n", "10", "-t", "0.75"])
System.print(args["count"]) // 10 (Num)
System.print(args["threshold"]) // 0.75 (Num)</code></pre>
<h3>Multiple Values</h3>
<pre><code>import "argparse" for ArgumentParser
var parser = ArgumentParser.new()
parser.addArgument("files", {
"nargs": "+",
"help": "Files to process"
})
parser.addArgument("-e", {
"long": "--exclude",
"action": "append",
"help": "Patterns to exclude"
})
var args = parser.parseArgs(["file1.txt", "file2.txt", "-e", "*.tmp", "-e", "*.bak"])
System.print(args["files"]) // ["file1.txt", "file2.txt"]
System.print(args["exclude"]) // ["*.tmp", "*.bak"]</code></pre>
<h3>Choices</h3>
<pre><code>import "argparse" for ArgumentParser
var parser = ArgumentParser.new()
parser.addArgument("-f", {
"long": "--format",
"choices": ["json", "xml", "csv"],
"default": "json",
"help": "Output format"
})
var args = parser.parseArgs(["-f", "csv"])
System.print(args["format"]) // csv</code></pre>
<h3>Verbosity Counter</h3>
<pre><code>import "argparse" for ArgumentParser
var parser = ArgumentParser.new()
parser.addArgument("-v", {
"action": "count",
"help": "Increase verbosity"
})
var args = parser.parseArgs(["-v", "-v", "-v"])
System.print(args["v"]) // 3</code></pre>
<div class="admonition note">
<div class="admonition-title">Note</div>
<p>Argument names starting with <code>-</code> are treated as optional flags. Names without a leading dash are positional arguments. Hyphens in argument names are converted to underscores in the result map.</p>
</div>
</article>
<footer class="page-footer">
<a href="html.html" class="prev">html</a>
<a href="wdantic.html" class="next">wdantic</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+389
View File
@@ -0,0 +1,389 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>dataset - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="index.html">Overview</a></li>
<li><a href="http.html">http</a></li>
<li><a href="websocket.html">websocket</a></li>
<li><a href="tls.html">tls</a></li>
<li><a href="net.html">net</a></li>
<li><a href="dns.html">dns</a></li>
<li><a href="json.html">json</a></li>
<li><a href="base64.html">base64</a></li>
<li><a href="regex.html">regex</a></li>
<li><a href="jinja.html">jinja</a></li>
<li><a href="crypto.html">crypto</a></li>
<li><a href="os.html">os</a></li>
<li><a href="env.html">env</a></li>
<li><a href="signal.html">signal</a></li>
<li><a href="subprocess.html">subprocess</a></li>
<li><a href="sqlite.html">sqlite</a></li>
<li><a href="datetime.html">datetime</a></li>
<li><a href="timer.html">timer</a></li>
<li><a href="io.html">io</a></li>
<li><a href="scheduler.html">scheduler</a></li>
<li><a href="math.html">math</a></li>
<li><a href="uuid.html">uuid</a></li>
<li><a href="html.html">html</a></li>
<li><a href="argparse.html">argparse</a></li>
<li><a href="wdantic.html">wdantic</a></li>
<li><a href="dataset.html" class="active">dataset</a></li>
<li><a href="markdown.html">markdown</a></li>
<li><a href="web.html">web</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="../howto/index.html">How-To List</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">API Reference</a>
<span class="separator">/</span>
<span>dataset</span>
</nav>
<article>
<h1>dataset</h1>
<p>The <code>dataset</code> module provides a simple ORM-like interface for SQLite databases with automatic schema management. Tables and columns are created automatically as you insert data.</p>
<pre><code>import "dataset" for Dataset, Table</code></pre>
<h2>Dataset Class</h2>
<div class="class-header">
<h3>Dataset</h3>
<p>Database connection and table access</p>
</div>
<h3>Constructors</h3>
<div class="method-signature">
<span class="method-name">Dataset.open</span>(<span class="param">path</span>) → <span class="type">Dataset</span>
</div>
<p>Opens or creates a SQLite database file.</p>
<ul class="param-list">
<li><span class="param-name">path</span> <span class="param-type">(String)</span> - Path to the database file</li>
</ul>
<pre><code>var db = Dataset.open("data.db")</code></pre>
<div class="method-signature">
<span class="method-name">Dataset.memory</span>() → <span class="type">Dataset</span>
</div>
<p>Creates an in-memory database (data is lost when closed).</p>
<pre><code>var db = Dataset.memory()</code></pre>
<h3>Properties</h3>
<div class="method-signature">
<span class="method-name">db</span><span class="type">Database</span>
</div>
<p>Access to the underlying SQLite database for raw queries.</p>
<div class="method-signature">
<span class="method-name">tables</span><span class="type">List</span>
</div>
<p>List of table names in the database.</p>
<h3>Subscript Access</h3>
<div class="method-signature">
<span class="method-name">[tableName]</span><span class="type">Table</span>
</div>
<p>Gets a table by name. Creates the table if it does not exist on first insert.</p>
<pre><code>var users = db["users"]</code></pre>
<h3>Instance Methods</h3>
<div class="method-signature">
<span class="method-name">close</span>()
</div>
<p>Closes the database connection.</p>
<h2>Table Class</h2>
<div class="class-header">
<h3>Table</h3>
<p>CRUD operations on a database table</p>
</div>
<h3>Properties</h3>
<div class="method-signature">
<span class="method-name">name</span><span class="type">String</span>
</div>
<p>The table name.</p>
<div class="method-signature">
<span class="method-name">columns</span><span class="type">Map</span>
</div>
<p>Map of column names to SQL types.</p>
<h3>Instance Methods</h3>
<div class="method-signature">
<span class="method-name">insert</span>(<span class="param">record</span>) → <span class="type">Map</span>
</div>
<p>Inserts a record and returns it with generated <code>uid</code> and <code>created_at</code>.</p>
<ul class="param-list">
<li><span class="param-name">record</span> <span class="param-type">(Map)</span> - Data to insert</li>
<li><span class="returns">Returns:</span> Inserted record with uid and created_at</li>
</ul>
<pre><code>var user = db["users"].insert({
"name": "Alice",
"email": "alice@example.com"
})
System.print(user["uid"]) // auto-generated UUID</code></pre>
<div class="method-signature">
<span class="method-name">update</span>(<span class="param">record</span>) → <span class="type">Num</span>
</div>
<p>Updates a record by uid. Returns number of rows affected.</p>
<ul class="param-list">
<li><span class="param-name">record</span> <span class="param-type">(Map)</span> - Must contain <code>uid</code> and fields to update</li>
</ul>
<pre><code>db["users"].update({
"uid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Alice Smith"
})</code></pre>
<div class="method-signature">
<span class="method-name">delete</span>(<span class="param">uid</span>) → <span class="type">Bool</span>
</div>
<p>Soft deletes a record (sets <code>deleted_at</code> timestamp). Returns true if record was deleted.</p>
<pre><code>db["users"].delete("550e8400-e29b-41d4-a716-446655440000")</code></pre>
<div class="method-signature">
<span class="method-name">hardDelete</span>(<span class="param">uid</span>) → <span class="type">Bool</span>
</div>
<p>Permanently deletes a record from the database.</p>
<div class="method-signature">
<span class="method-name">find</span>(<span class="param">conditions</span>) → <span class="type">List</span>
</div>
<p>Finds records matching conditions. Returns list of records (excludes soft-deleted).</p>
<pre><code>var admins = db["users"].find({"role": "admin"})</code></pre>
<div class="method-signature">
<span class="method-name">findOne</span>(<span class="param">conditions</span>) → <span class="type">Map|null</span>
</div>
<p>Finds first record matching conditions or null.</p>
<pre><code>var user = db["users"].findOne({"email": "alice@example.com"})</code></pre>
<div class="method-signature">
<span class="method-name">all</span>() → <span class="type">List</span>
</div>
<p>Returns all non-deleted records.</p>
<div class="method-signature">
<span class="method-name">count</span>() → <span class="type">Num</span>
</div>
<p>Returns count of non-deleted records.</p>
<h2>Query Operators</h2>
<p>Use suffixes in condition keys for comparison operators:</p>
<table>
<tr>
<th>Suffix</th>
<th>SQL Operator</th>
<th>Example</th>
</tr>
<tr>
<td><code>__gt</code></td>
<td>&gt;</td>
<td><code>{"age__gt": 18}</code></td>
</tr>
<tr>
<td><code>__lt</code></td>
<td>&lt;</td>
<td><code>{"price__lt": 100}</code></td>
</tr>
<tr>
<td><code>__gte</code></td>
<td>&gt;=</td>
<td><code>{"score__gte": 90}</code></td>
</tr>
<tr>
<td><code>__lte</code></td>
<td>&lt;=</td>
<td><code>{"score__lte": 100}</code></td>
</tr>
<tr>
<td><code>__ne</code></td>
<td>!=</td>
<td><code>{"status__ne": "deleted"}</code></td>
</tr>
<tr>
<td><code>__like</code></td>
<td>LIKE</td>
<td><code>{"name__like": "A\%"}</code></td>
</tr>
<tr>
<td><code>__in</code></td>
<td>IN</td>
<td><code>{"status__in": ["active", "pending"]}</code></td>
</tr>
<tr>
<td><code>__null</code></td>
<td>IS NULL / IS NOT NULL</td>
<td><code>{"deleted_at__null": true}</code></td>
</tr>
</table>
<h2>Automatic Features</h2>
<h3>Auto-Generated Fields</h3>
<ul>
<li><code>uid</code> - UUID v4 primary key (auto-generated if not provided)</li>
<li><code>created_at</code> - ISO timestamp (auto-generated on insert)</li>
<li><code>deleted_at</code> - ISO timestamp (set by soft delete)</li>
</ul>
<h3>Auto Schema</h3>
<ul>
<li>Tables are created automatically on first insert</li>
<li>Columns are added automatically when new fields appear</li>
<li>Type inference: Num → INTEGER/REAL, Bool → INTEGER, Map/List → TEXT (JSON)</li>
</ul>
<h3>JSON Serialization</h3>
<p>Maps and Lists are automatically serialized to JSON when stored and deserialized when retrieved.</p>
<h2>Examples</h2>
<h3>Basic CRUD</h3>
<pre><code>import "dataset" for Dataset
var db = Dataset.open("app.db")
var users = db["users"]
var user = users.insert({
"name": "Alice",
"email": "alice@example.com",
"settings": {"theme": "dark", "notifications": true}
})
System.print("Created user: %(user["uid"])")
users.update({
"uid": user["uid"],
"name": "Alice Smith"
})
var found = users.findOne({"email": "alice@example.com"})
System.print("Found: %(found["name"])")
users.delete(user["uid"])
db.close()</code></pre>
<h3>Querying with Operators</h3>
<pre><code>import "dataset" for Dataset
var db = Dataset.open("products.db")
var products = db["products"]
var expensive = products.find({"price__gt": 100})
var cheap = products.find({"price__lte": 10})
var search = products.find({"name__like": "\%phone\%"})
var featured = products.find({
"category__in": ["electronics", "gadgets"],
"stock__gt": 0
})
db.close()</code></pre>
<h3>Working with JSON Data</h3>
<pre><code>import "dataset" for Dataset
var db = Dataset.memory()
db["posts"].insert({
"title": "First Post",
"tags": ["wren", "programming", "tutorial"],
"metadata": {
"author": "Alice",
"views": 100,
"featured": true
}
})
var post = db["posts"].findOne({"title": "First Post"})
System.print(post["tags"]) // ["wren", "programming", "tutorial"]
System.print(post["metadata"]) // {"author": "Alice", ...}</code></pre>
<div class="admonition note">
<div class="admonition-title">Note</div>
<p>Soft delete is the default behavior. Records are not permanently removed but marked with a <code>deleted_at</code> timestamp. Use <code>hardDelete()</code> for permanent removal. All query methods automatically exclude soft-deleted records.</p>
</div>
<div class="admonition warning">
<div class="admonition-title">Warning</div>
<p>The <code>uid</code> field is the primary key. Do not use <code>id</code> as a field name. If you provide a <code>uid</code> during insert, it will be used instead of auto-generating one.</p>
</div>
</article>
<footer class="page-footer">
<a href="wdantic.html" class="prev">wdantic</a>
<a href="markdown.html" class="next">markdown</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+281
View File
@@ -0,0 +1,281 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>html - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="index.html">Overview</a></li>
<li><a href="http.html">http</a></li>
<li><a href="websocket.html">websocket</a></li>
<li><a href="tls.html">tls</a></li>
<li><a href="net.html">net</a></li>
<li><a href="dns.html">dns</a></li>
<li><a href="json.html">json</a></li>
<li><a href="base64.html">base64</a></li>
<li><a href="regex.html">regex</a></li>
<li><a href="jinja.html">jinja</a></li>
<li><a href="crypto.html">crypto</a></li>
<li><a href="os.html">os</a></li>
<li><a href="env.html">env</a></li>
<li><a href="signal.html">signal</a></li>
<li><a href="subprocess.html">subprocess</a></li>
<li><a href="sqlite.html">sqlite</a></li>
<li><a href="datetime.html">datetime</a></li>
<li><a href="timer.html">timer</a></li>
<li><a href="io.html">io</a></li>
<li><a href="scheduler.html">scheduler</a></li>
<li><a href="math.html">math</a></li>
<li><a href="uuid.html">uuid</a></li>
<li><a href="html.html" class="active">html</a></li>
<li><a href="argparse.html">argparse</a></li>
<li><a href="wdantic.html">wdantic</a></li>
<li><a href="dataset.html">dataset</a></li>
<li><a href="markdown.html">markdown</a></li>
<li><a href="web.html">web</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="../howto/index.html">How-To List</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">API Reference</a>
<span class="separator">/</span>
<span>html</span>
</nav>
<article>
<h1>html</h1>
<p>The <code>html</code> module provides utilities for HTML and URL encoding/decoding, slug generation, and query string handling.</p>
<pre><code>import "html" for Html</code></pre>
<h2>Html Class</h2>
<div class="class-header">
<h3>Html</h3>
<p>HTML and URL encoding utilities</p>
</div>
<h3>Static Methods</h3>
<div class="method-signature">
<span class="method-name">Html.urlencode</span>(<span class="param">string</span>) → <span class="type">String</span>
</div>
<p>URL-encodes a string for use in URLs and query parameters. Spaces become <code>+</code>, special characters become percent-encoded.</p>
<ul class="param-list">
<li><span class="param-name">string</span> <span class="param-type">(String)</span> - The string to encode</li>
<li><span class="returns">Returns:</span> URL-encoded string</li>
</ul>
<pre><code>System.print(Html.urlencode("hello world")) // hello+world
System.print(Html.urlencode("a=b&c=d")) // a\%3Db\%26c\%3Dd
System.print(Html.urlencode("café")) // caf\%C3\%A9</code></pre>
<div class="method-signature">
<span class="method-name">Html.urldecode</span>(<span class="param">string</span>) → <span class="type">String</span>
</div>
<p>Decodes a URL-encoded string. Converts <code>+</code> to space and decodes percent-encoded characters.</p>
<ul class="param-list">
<li><span class="param-name">string</span> <span class="param-type">(String)</span> - The URL-encoded string</li>
<li><span class="returns">Returns:</span> Decoded string</li>
</ul>
<pre><code>System.print(Html.urldecode("hello+world")) // hello world
System.print(Html.urldecode("caf\%C3\%A9")) // café</code></pre>
<div class="method-signature">
<span class="method-name">Html.slugify</span>(<span class="param">string</span>) → <span class="type">String</span>
</div>
<p>Converts a string to a URL-friendly slug. Lowercase, alphanumeric characters with hyphens.</p>
<ul class="param-list">
<li><span class="param-name">string</span> <span class="param-type">(String)</span> - The string to slugify</li>
<li><span class="returns">Returns:</span> URL-friendly slug</li>
</ul>
<pre><code>System.print(Html.slugify("Hello World")) // hello-world
System.print(Html.slugify("My Blog Post!")) // my-blog-post
System.print(Html.slugify(" Multiple Spaces ")) // multiple-spaces</code></pre>
<div class="method-signature">
<span class="method-name">Html.quote</span>(<span class="param">string</span>) → <span class="type">String</span>
</div>
<p>Escapes HTML special characters to prevent XSS attacks.</p>
<ul class="param-list">
<li><span class="param-name">string</span> <span class="param-type">(String)</span> - The string to escape</li>
<li><span class="returns">Returns:</span> HTML-escaped string</li>
</ul>
<pre><code>System.print(Html.quote("&lt;script&gt;alert('xss')&lt;/script&gt;"))
// &amp;lt;script&amp;gt;alert(&amp;#39;xss&amp;#39;)&amp;lt;/script&amp;gt;
System.print(Html.quote("A &amp; B")) // A &amp;amp; B
System.print(Html.quote("\"quoted\"")) // &amp;quot;quoted&amp;quot;</code></pre>
<div class="method-signature">
<span class="method-name">Html.unquote</span>(<span class="param">string</span>) → <span class="type">String</span>
</div>
<p>Unescapes HTML entities back to their original characters.</p>
<ul class="param-list">
<li><span class="param-name">string</span> <span class="param-type">(String)</span> - The HTML-escaped string</li>
<li><span class="returns">Returns:</span> Unescaped string</li>
</ul>
<pre><code>System.print(Html.unquote("&amp;lt;div&amp;gt;")) // &lt;div&gt;
System.print(Html.unquote("A &amp;amp; B")) // A &amp; B</code></pre>
<div class="method-signature">
<span class="method-name">Html.encodeParams</span>(<span class="param">params</span>) → <span class="type">String</span>
</div>
<p>Encodes a map of key-value pairs into a URL query string.</p>
<ul class="param-list">
<li><span class="param-name">params</span> <span class="param-type">(Map)</span> - Map of parameters to encode</li>
<li><span class="returns">Returns:</span> URL-encoded query string</li>
</ul>
<pre><code>var params = {"name": "John Doe", "age": 30}
System.print(Html.encodeParams(params)) // name=John+Doe&amp;age=30
var search = {"q": "wren lang", "page": 1}
System.print(Html.encodeParams(search)) // q=wren+lang&amp;page=1</code></pre>
<div class="method-signature">
<span class="method-name">Html.decodeParams</span>(<span class="param">string</span>) → <span class="type">Map</span>
</div>
<p>Decodes a URL query string into a map of key-value pairs.</p>
<ul class="param-list">
<li><span class="param-name">string</span> <span class="param-type">(String)</span> - URL-encoded query string</li>
<li><span class="returns">Returns:</span> Map of decoded parameters</li>
</ul>
<pre><code>var params = Html.decodeParams("name=John+Doe&amp;age=30")
System.print(params["name"]) // John Doe
System.print(params["age"]) // 30</code></pre>
<h2>Entity Reference</h2>
<table>
<tr>
<th>Character</th>
<th>Entity</th>
</tr>
<tr>
<td>&amp;</td>
<td>&amp;amp;</td>
</tr>
<tr>
<td>&lt;</td>
<td>&amp;lt;</td>
</tr>
<tr>
<td>&gt;</td>
<td>&amp;gt;</td>
</tr>
<tr>
<td>"</td>
<td>&amp;quot;</td>
</tr>
<tr>
<td>'</td>
<td>&amp;#39;</td>
</tr>
</table>
<h2>Examples</h2>
<h3>Building URLs</h3>
<pre><code>import "html" for Html
var baseUrl = "https://api.example.com/search"
var params = {
"query": "wren programming",
"limit": 10,
"offset": 0
}
var url = baseUrl + "?" + Html.encodeParams(params)
System.print(url)
// https://api.example.com/search?query=wren+programming&amp;limit=10&amp;offset=0</code></pre>
<h3>Safe HTML Output</h3>
<pre><code>import "html" for Html
var userInput = "&lt;script&gt;alert('xss')&lt;/script&gt;"
var safeHtml = "&lt;div class=\"comment\"&gt;" + Html.quote(userInput) + "&lt;/div&gt;"
System.print(safeHtml)</code></pre>
<h3>Generating Slugs for URLs</h3>
<pre><code>import "html" for Html
var title = "How to Build Web Apps with Wren!"
var slug = Html.slugify(title)
var url = "/blog/" + slug
System.print(url) // /blog/how-to-build-web-apps-with-wren</code></pre>
<h3>Parsing Query Strings</h3>
<pre><code>import "html" for Html
var queryString = "category=books&amp;sort=price&amp;order=asc"
var params = Html.decodeParams(queryString)
for (key in params.keys) {
System.print("%(key): %(params[key])")
}</code></pre>
<div class="admonition warning">
<div class="admonition-title">Warning</div>
<p>Always use <code>Html.quote()</code> when inserting user-provided content into HTML to prevent cross-site scripting (XSS) attacks.</p>
</div>
</article>
<footer class="page-footer">
<a href="uuid.html" class="prev">uuid</a>
<a href="argparse.html" class="next">argparse</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+77 -1
View File
@@ -60,6 +60,13 @@
<li><a href="io.html">io</a></li>
<li><a href="scheduler.html">scheduler</a></li>
<li><a href="math.html">math</a></li>
<li><a href="uuid.html">uuid</a></li>
<li><a href="html.html">html</a></li>
<li><a href="argparse.html">argparse</a></li>
<li><a href="wdantic.html">wdantic</a></li>
<li><a href="dataset.html">dataset</a></li>
<li><a href="markdown.html">markdown</a></li>
<li><a href="web.html">web</a></li>
</ul>
</div>
<div class="section">
@@ -97,7 +104,7 @@
<article>
<h1>API Reference</h1>
<p>Wren-CLI provides 21 built-in modules covering networking, file I/O, data processing, system operations, and more. All modules are imported using the <code>import</code> statement.</p>
<p>Wren-CLI provides 28 built-in modules covering networking, file I/O, data processing, system operations, and more. All modules are imported using the <code>import</code> statement.</p>
<pre><code>import "http" for Http
import "json" for Json
@@ -153,6 +160,18 @@ import "io" for File</code></pre>
<h3><a href="crypto.html">crypto</a></h3>
<p>Cryptographic hashing (MD5, SHA-1, SHA-256) and random byte generation.</p>
</div>
<div class="card">
<h3><a href="uuid.html">uuid</a></h3>
<p>UUID generation and validation with v4 support.</p>
</div>
<div class="card">
<h3><a href="html.html">html</a></h3>
<p>HTML/URL encoding, decoding, slug generation, and query string handling.</p>
</div>
<div class="card">
<h3><a href="markdown.html">markdown</a></h3>
<p>Convert Markdown text to HTML with safe mode support.</p>
</div>
</div>
<h2>System</h2>
@@ -205,6 +224,28 @@ import "io" for File</code></pre>
<h3><a href="scheduler.html">scheduler</a></h3>
<p>Async fiber scheduling for non-blocking I/O operations.</p>
</div>
<div class="card">
<h3><a href="dataset.html">dataset</a></h3>
<p>Simple ORM for SQLite with automatic schema management.</p>
</div>
</div>
<h2>Application Development</h2>
<p>Modules for building web applications and command-line tools.</p>
<div class="card-grid">
<div class="card">
<h3><a href="web.html">web</a></h3>
<p>Web framework with routing, middleware, sessions, and HTTP client.</p>
</div>
<div class="card">
<h3><a href="argparse.html">argparse</a></h3>
<p>Command-line argument parsing with type conversion and help generation.</p>
</div>
<div class="card">
<h3><a href="wdantic.html">wdantic</a></h3>
<p>Data validation with schema definitions and built-in validators.</p>
</div>
</div>
<h2>Module Summary</h2>
@@ -314,6 +355,41 @@ import "io" for File</code></pre>
<td>Math</td>
<td>Math functions</td>
</tr>
<tr>
<td><a href="uuid.html">uuid</a></td>
<td>Uuid</td>
<td>UUID generation</td>
</tr>
<tr>
<td><a href="html.html">html</a></td>
<td>Html</td>
<td>HTML/URL encoding</td>
</tr>
<tr>
<td><a href="argparse.html">argparse</a></td>
<td>ArgumentParser</td>
<td>CLI arguments</td>
</tr>
<tr>
<td><a href="wdantic.html">wdantic</a></td>
<td>Validator, Field, Schema, ValidationResult</td>
<td>Data validation</td>
</tr>
<tr>
<td><a href="dataset.html">dataset</a></td>
<td>Dataset, Table</td>
<td>Simple ORM</td>
</tr>
<tr>
<td><a href="markdown.html">markdown</a></td>
<td>Markdown</td>
<td>Markdown to HTML</td>
</tr>
<tr>
<td><a href="web.html">web</a></td>
<td>Application, Router, Request, Response, View, Session, Client</td>
<td>Web framework</td>
</tr>
</table>
</article>
+430
View File
@@ -0,0 +1,430 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>markdown - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="index.html">Overview</a></li>
<li><a href="http.html">http</a></li>
<li><a href="websocket.html">websocket</a></li>
<li><a href="tls.html">tls</a></li>
<li><a href="net.html">net</a></li>
<li><a href="dns.html">dns</a></li>
<li><a href="json.html">json</a></li>
<li><a href="base64.html">base64</a></li>
<li><a href="regex.html">regex</a></li>
<li><a href="jinja.html">jinja</a></li>
<li><a href="crypto.html">crypto</a></li>
<li><a href="os.html">os</a></li>
<li><a href="env.html">env</a></li>
<li><a href="signal.html">signal</a></li>
<li><a href="subprocess.html">subprocess</a></li>
<li><a href="sqlite.html">sqlite</a></li>
<li><a href="datetime.html">datetime</a></li>
<li><a href="timer.html">timer</a></li>
<li><a href="io.html">io</a></li>
<li><a href="scheduler.html">scheduler</a></li>
<li><a href="math.html">math</a></li>
<li><a href="uuid.html">uuid</a></li>
<li><a href="html.html">html</a></li>
<li><a href="argparse.html">argparse</a></li>
<li><a href="wdantic.html">wdantic</a></li>
<li><a href="dataset.html">dataset</a></li>
<li><a href="markdown.html" class="active">markdown</a></li>
<li><a href="web.html">web</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="../howto/index.html">How-To List</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">API Reference</a>
<span class="separator">/</span>
<span>markdown</span>
</nav>
<article>
<h1>markdown</h1>
<p>The <code>markdown</code> module provides bidirectional conversion between Markdown and HTML. It supports common Markdown syntax including headings, emphasis, code blocks, lists, links, and images.</p>
<pre><code>import "markdown" for Markdown</code></pre>
<h2>Markdown Class</h2>
<div class="class-header">
<h3>Markdown</h3>
<p>Markdown to HTML converter</p>
</div>
<h3>Static Methods</h3>
<div class="method-signature">
<span class="method-name">Markdown.toHtml</span>(<span class="param">text</span>) → <span class="type">String</span>
</div>
<p>Converts Markdown text to HTML.</p>
<ul class="param-list">
<li><span class="param-name">text</span> <span class="param-type">(String)</span> - Markdown text</li>
<li><span class="returns">Returns:</span> HTML string</li>
</ul>
<pre><code>var html = Markdown.toHtml("# Hello World")
System.print(html) // &lt;h1&gt;Hello World&lt;/h1&gt;</code></pre>
<div class="method-signature">
<span class="method-name">Markdown.toHtml</span>(<span class="param">text</span>, <span class="param">options</span>) → <span class="type">String</span>
</div>
<p>Converts Markdown text to HTML with options.</p>
<ul class="param-list">
<li><span class="param-name">text</span> <span class="param-type">(String)</span> - Markdown text</li>
<li><span class="param-name">options</span> <span class="param-type">(Map)</span> - Conversion options</li>
<li><span class="returns">Returns:</span> HTML string</li>
</ul>
<div class="method-signature">
<span class="method-name">Markdown.fromHtml</span>(<span class="param">html</span>) → <span class="type">String</span>
</div>
<p>Converts HTML to Markdown text.</p>
<ul class="param-list">
<li><span class="param-name">html</span> <span class="param-type">(String)</span> - HTML string</li>
<li><span class="returns">Returns:</span> Markdown text</li>
</ul>
<pre><code>var md = Markdown.fromHtml("&lt;h1&gt;Hello World&lt;/h1&gt;")
System.print(md) // # Hello World</code></pre>
<div class="method-signature">
<span class="method-name">Markdown.fromHtml</span>(<span class="param">html</span>, <span class="param">options</span>) → <span class="type">String</span>
</div>
<p>Converts HTML to Markdown text with options.</p>
<ul class="param-list">
<li><span class="param-name">html</span> <span class="param-type">(String)</span> - HTML string</li>
<li><span class="param-name">options</span> <span class="param-type">(Map)</span> - Conversion options</li>
<li><span class="returns">Returns:</span> Markdown text</li>
</ul>
<h2>Options</h2>
<h3>toHtml Options</h3>
<table>
<tr>
<th>Option</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
<tr>
<td><code>safeMode</code></td>
<td>Bool</td>
<td><code>false</code></td>
<td>Escape HTML in input to prevent XSS</td>
</tr>
</table>
<h3>fromHtml Options</h3>
<table>
<tr>
<th>Option</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
<tr>
<td><code>stripUnknown</code></td>
<td>Bool</td>
<td><code>true</code></td>
<td>Strip unknown HTML tags, keeping their content</td>
</tr>
</table>
<h2>Supported Syntax</h2>
<h3>Headings</h3>
<pre><code># Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6</code></pre>
<p>Converts to <code>&lt;h1&gt;</code> through <code>&lt;h6&gt;</code> tags.</p>
<h3>Emphasis</h3>
<pre><code>*italic* or _italic_
**bold** or __bold__
~~strikethrough~~</code></pre>
<p>Converts to <code>&lt;em&gt;</code>, <code>&lt;strong&gt;</code>, and <code>&lt;del&gt;</code> tags.</p>
<h3>Code</h3>
<pre><code>Inline `code` here
```
Code block
Multiple lines
```</code></pre>
<p>Inline code uses <code>&lt;code&gt;</code>, blocks use <code>&lt;pre&gt;&lt;code&gt;</code>.</p>
<h3>Lists</h3>
<pre><code>Unordered:
- Item 1
- Item 2
* Also works
+ And this
Ordered:
1. First
2. Second
3. Third</code></pre>
<p>Creates <code>&lt;ul&gt;</code> and <code>&lt;ol&gt;</code> with <code>&lt;li&gt;</code> items.</p>
<h3>Links and Images</h3>
<pre><code>[Link text](https://example.com)
![Alt text](image.png)</code></pre>
<p>Creates <code>&lt;a href="..."&gt;</code> and <code>&lt;img src="..." alt="..."&gt;</code>.</p>
<h3>Blockquotes</h3>
<pre><code>&gt; This is a quote
&gt; Multiple lines</code></pre>
<p>Creates <code>&lt;blockquote&gt;</code> with <code>&lt;p&gt;</code> content.</p>
<h3>Horizontal Rule</h3>
<pre><code>---
***
___</code></pre>
<p>Creates <code>&lt;hr&gt;</code> tag.</p>
<h3>Paragraphs</h3>
<p>Text separated by blank lines becomes <code>&lt;p&gt;</code> elements.</p>
<h2>HTML to Markdown Conversions</h2>
<p>The <code>fromHtml</code> method converts the following HTML elements to Markdown:</p>
<table>
<tr>
<th>HTML</th>
<th>Markdown</th>
</tr>
<tr>
<td><code>&lt;h1&gt;</code> to <code>&lt;h6&gt;</code></td>
<td><code>#</code> to <code>######</code></td>
</tr>
<tr>
<td><code>&lt;strong&gt;</code>, <code>&lt;b&gt;</code></td>
<td><code>**text**</code></td>
</tr>
<tr>
<td><code>&lt;em&gt;</code>, <code>&lt;i&gt;</code></td>
<td><code>*text*</code></td>
</tr>
<tr>
<td><code>&lt;code&gt;</code></td>
<td><code>`text`</code></td>
</tr>
<tr>
<td><code>&lt;pre&gt;&lt;code&gt;</code></td>
<td>Fenced code block</td>
</tr>
<tr>
<td><code>&lt;a href="url"&gt;</code></td>
<td><code>[text](url)</code></td>
</tr>
<tr>
<td><code>&lt;img src="url" alt=""&gt;</code></td>
<td><code>![alt](url)</code></td>
</tr>
<tr>
<td><code>&lt;ul&gt;&lt;li&gt;</code></td>
<td><code>- item</code></td>
</tr>
<tr>
<td><code>&lt;ol&gt;&lt;li&gt;</code></td>
<td><code>1. item</code></td>
</tr>
<tr>
<td><code>&lt;blockquote&gt;</code></td>
<td><code>&gt; text</code></td>
</tr>
<tr>
<td><code>&lt;hr&gt;</code></td>
<td><code>---</code></td>
</tr>
<tr>
<td><code>&lt;del&gt;</code>, <code>&lt;s&gt;</code></td>
<td><code>~~text~~</code></td>
</tr>
</table>
<p>Container tags (<code>&lt;div&gt;</code>, <code>&lt;span&gt;</code>, <code>&lt;section&gt;</code>, etc.) are stripped but their content is preserved. Script and style tags are removed entirely.</p>
<h2>Examples</h2>
<h3>Basic Conversion</h3>
<pre><code>import "markdown" for Markdown
var md = "
# Welcome
This is a **Markdown** document with:
- Lists
- *Emphasis*
- `Code`
Visit [Wren](https://wren.io) for more.
"
var html = Markdown.toHtml(md)
System.print(html)</code></pre>
<h3>Safe Mode for User Content</h3>
<pre><code>import "markdown" for Markdown
var userInput = "# Title\n&lt;script&gt;alert('xss')&lt;/script&gt;\nContent here."
var safeHtml = Markdown.toHtml(userInput, {"safeMode": true})
System.print(safeHtml)</code></pre>
<h3>Rendering a Blog Post</h3>
<pre><code>import "markdown" for Markdown
import "io" for File
var postContent = File.read("post.md")
var html = Markdown.toHtml(postContent)
var page = "&lt;html&gt;
&lt;head&gt;&lt;title&gt;Blog&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
&lt;article&gt;
%(html)
&lt;/article&gt;
&lt;/body&gt;
&lt;/html&gt;"
File.write("post.html", page)</code></pre>
<h3>Code Blocks with Language Hints</h3>
<pre><code>import "markdown" for Markdown
var md = "
```wren
System.print(\"Hello, World!\")
```
"
var html = Markdown.toHtml(md)
System.print(html)
// &lt;pre&gt;&lt;code&gt;System.print("Hello, World!")&lt;/code&gt;&lt;/pre&gt;</code></pre>
<h3>Combining with Templates</h3>
<pre><code>import "markdown" for Markdown
import "jinja" for Environment, DictLoader
var env = Environment.new(DictLoader.new({
"base": "&lt;html&gt;&lt;body&gt;{{ content }}&lt;/body&gt;&lt;/html&gt;"
}))
var md = "# Hello\n\nThis is **Markdown**."
var content = Markdown.toHtml(md)
var html = env.getTemplate("base").render({"content": content})
System.print(html)</code></pre>
<h3>Converting HTML to Markdown</h3>
<pre><code>import "markdown" for Markdown
var html = "
&lt;html&gt;
&lt;body&gt;
&lt;h1&gt;Article Title&lt;/h1&gt;
&lt;p&gt;This is &lt;strong&gt;important&lt;/strong&gt; content.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First item&lt;/li&gt;
&lt;li&gt;Second item&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;
"
var md = Markdown.fromHtml(html)
System.print(md)
// # Article Title
//
// This is **important** content.
//
// - First item
// - Second item</code></pre>
<h3>Cleaning HTML for Plain Text</h3>
<pre><code>import "markdown" for Markdown
var webContent = "&lt;div&gt;&lt;script&gt;alert('xss')&lt;/script&gt;&lt;p&gt;Safe &lt;b&gt;content&lt;/b&gt;&lt;/p&gt;&lt;/div&gt;"
var clean = Markdown.fromHtml(webContent)
System.print(clean) // Safe **content**</code></pre>
<div class="admonition warning">
<div class="admonition-title">Warning</div>
<p>When rendering user-provided Markdown, always use <code>safeMode: true</code> to prevent cross-site scripting (XSS) attacks. Safe mode escapes HTML entities in the input text.</p>
</div>
<div class="admonition note">
<div class="admonition-title">Note</div>
<p>Language identifiers after code fences (e.g., <code>```wren</code>) are currently ignored. The code is rendered without syntax highlighting. Consider using a client-side syntax highlighter like Prism.js or highlight.js for the resulting HTML.</p>
</div>
</article>
<footer class="page-footer">
<a href="dataset.html" class="prev">dataset</a>
<a href="web.html" class="next">web</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+223
View File
@@ -0,0 +1,223 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>uuid - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="index.html">Overview</a></li>
<li><a href="http.html">http</a></li>
<li><a href="websocket.html">websocket</a></li>
<li><a href="tls.html">tls</a></li>
<li><a href="net.html">net</a></li>
<li><a href="dns.html">dns</a></li>
<li><a href="json.html">json</a></li>
<li><a href="base64.html">base64</a></li>
<li><a href="regex.html">regex</a></li>
<li><a href="jinja.html">jinja</a></li>
<li><a href="crypto.html">crypto</a></li>
<li><a href="os.html">os</a></li>
<li><a href="env.html">env</a></li>
<li><a href="signal.html">signal</a></li>
<li><a href="subprocess.html">subprocess</a></li>
<li><a href="sqlite.html">sqlite</a></li>
<li><a href="datetime.html">datetime</a></li>
<li><a href="timer.html">timer</a></li>
<li><a href="io.html">io</a></li>
<li><a href="scheduler.html">scheduler</a></li>
<li><a href="math.html">math</a></li>
<li><a href="uuid.html" class="active">uuid</a></li>
<li><a href="html.html">html</a></li>
<li><a href="argparse.html">argparse</a></li>
<li><a href="wdantic.html">wdantic</a></li>
<li><a href="dataset.html">dataset</a></li>
<li><a href="markdown.html">markdown</a></li>
<li><a href="web.html">web</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="../howto/index.html">How-To List</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">API Reference</a>
<span class="separator">/</span>
<span>uuid</span>
</nav>
<article>
<h1>uuid</h1>
<p>The <code>uuid</code> module provides UUID (Universally Unique Identifier) generation and validation. It supports version 4 UUIDs which are randomly generated.</p>
<pre><code>import "uuid" for Uuid</code></pre>
<h2>Uuid Class</h2>
<div class="class-header">
<h3>Uuid</h3>
<p>UUID generation and validation</p>
</div>
<h3>Static Methods</h3>
<div class="method-signature">
<span class="method-name">Uuid.v4</span>() → <span class="type">String</span>
</div>
<p>Generates a new random version 4 UUID.</p>
<ul class="param-list">
<li><span class="returns">Returns:</span> A 36-character UUID string in the format <code>xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx</code></li>
</ul>
<pre><code>var id = Uuid.v4()
System.print(id) // e.g., "550e8400-e29b-41d4-a716-446655440000"</code></pre>
<div class="method-signature">
<span class="method-name">Uuid.isValid</span>(<span class="param">string</span>) → <span class="type">Bool</span>
</div>
<p>Checks if a string is a valid UUID format (any version).</p>
<ul class="param-list">
<li><span class="param-name">string</span> <span class="param-type">(String)</span> - The string to validate</li>
<li><span class="returns">Returns:</span> <code>true</code> if the string is a valid UUID format, <code>false</code> otherwise</li>
</ul>
<pre><code>System.print(Uuid.isValid("550e8400-e29b-41d4-a716-446655440000")) // true
System.print(Uuid.isValid("not-a-uuid")) // false
System.print(Uuid.isValid("550e8400e29b41d4a716446655440000")) // false (missing hyphens)</code></pre>
<div class="method-signature">
<span class="method-name">Uuid.isV4</span>(<span class="param">string</span>) → <span class="type">Bool</span>
</div>
<p>Checks if a string is a valid version 4 UUID.</p>
<ul class="param-list">
<li><span class="param-name">string</span> <span class="param-type">(String)</span> - The string to validate</li>
<li><span class="returns">Returns:</span> <code>true</code> if the string is a valid v4 UUID, <code>false</code> otherwise</li>
</ul>
<pre><code>var id = Uuid.v4()
System.print(Uuid.isV4(id)) // true
System.print(Uuid.isV4("550e8400-e29b-11d4-a716-446655440000")) // false (version 1)</code></pre>
<h2>UUID Format</h2>
<p>UUIDs are 128-bit identifiers represented as 32 hexadecimal characters separated by hyphens into five groups:</p>
<pre><code>xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
8 4 4 4 12 = 32 hex chars + 4 hyphens = 36 chars</code></pre>
<table>
<tr>
<th>Position</th>
<th>Description</th>
</tr>
<tr>
<td>M</td>
<td>Version number (4 for v4 UUIDs)</td>
</tr>
<tr>
<td>N</td>
<td>Variant (8, 9, a, or b for RFC 4122 UUIDs)</td>
</tr>
</table>
<h2>Examples</h2>
<h3>Generating Unique Identifiers</h3>
<pre><code>import "uuid" for Uuid
var userId = Uuid.v4()
var sessionId = Uuid.v4()
System.print("User ID: %(userId)")
System.print("Session ID: %(sessionId)")</code></pre>
<h3>Validating User Input</h3>
<pre><code>import "uuid" for Uuid
var input = "550e8400-e29b-41d4-a716-446655440000"
if (Uuid.isValid(input)) {
System.print("Valid UUID")
if (Uuid.isV4(input)) {
System.print("This is a v4 UUID")
}
} else {
System.print("Invalid UUID format")
}</code></pre>
<h3>Using with Database Records</h3>
<pre><code>import "uuid" for Uuid
class User {
construct new(name) {
_id = Uuid.v4()
_name = name
}
id { _id }
name { _name }
}
var user = User.new("Alice")
System.print("Created user %(user.name) with ID %(user.id)")</code></pre>
<div class="admonition note">
<div class="admonition-title">Note</div>
<p>Version 4 UUIDs are generated using cryptographically secure random bytes from the <code>crypto</code> module. The probability of generating duplicate UUIDs is astronomically low.</p>
</div>
</article>
<footer class="page-footer">
<a href="math.html" class="prev">math</a>
<a href="html.html" class="next">html</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+410
View File
@@ -0,0 +1,410 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>wdantic - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="index.html">Overview</a></li>
<li><a href="http.html">http</a></li>
<li><a href="websocket.html">websocket</a></li>
<li><a href="tls.html">tls</a></li>
<li><a href="net.html">net</a></li>
<li><a href="dns.html">dns</a></li>
<li><a href="json.html">json</a></li>
<li><a href="base64.html">base64</a></li>
<li><a href="regex.html">regex</a></li>
<li><a href="jinja.html">jinja</a></li>
<li><a href="crypto.html">crypto</a></li>
<li><a href="os.html">os</a></li>
<li><a href="env.html">env</a></li>
<li><a href="signal.html">signal</a></li>
<li><a href="subprocess.html">subprocess</a></li>
<li><a href="sqlite.html">sqlite</a></li>
<li><a href="datetime.html">datetime</a></li>
<li><a href="timer.html">timer</a></li>
<li><a href="io.html">io</a></li>
<li><a href="scheduler.html">scheduler</a></li>
<li><a href="math.html">math</a></li>
<li><a href="uuid.html">uuid</a></li>
<li><a href="html.html">html</a></li>
<li><a href="argparse.html">argparse</a></li>
<li><a href="wdantic.html" class="active">wdantic</a></li>
<li><a href="dataset.html">dataset</a></li>
<li><a href="markdown.html">markdown</a></li>
<li><a href="web.html">web</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="../howto/index.html">How-To List</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">API Reference</a>
<span class="separator">/</span>
<span>wdantic</span>
</nav>
<article>
<h1>wdantic</h1>
<p>The <code>wdantic</code> module provides data validation similar to Python's Pydantic. It includes standalone validators and a schema-based validation system for structured data.</p>
<pre><code>import "wdantic" for Validator, Field, Schema, ValidationResult</code></pre>
<h2>Validator Class</h2>
<div class="class-header">
<h3>Validator</h3>
<p>Standalone validation functions</p>
</div>
<h3>Static Methods</h3>
<div class="method-signature">
<span class="method-name">Validator.email</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Validates email address format.</p>
<pre><code>Validator.email("user@example.com") // true
Validator.email("invalid") // false</code></pre>
<div class="method-signature">
<span class="method-name">Validator.domain</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Validates domain name format.</p>
<pre><code>Validator.domain("example.com") // true
Validator.domain("localhost") // false</code></pre>
<div class="method-signature">
<span class="method-name">Validator.url</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Validates HTTP/HTTPS URL format.</p>
<pre><code>Validator.url("https://example.com/path") // true
Validator.url("ftp://example.com") // false</code></pre>
<div class="method-signature">
<span class="method-name">Validator.uuid</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Validates UUID format.</p>
<pre><code>Validator.uuid("550e8400-e29b-41d4-a716-446655440000") // true</code></pre>
<div class="method-signature">
<span class="method-name">Validator.safeStr</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Checks if string contains only printable ASCII characters (32-126).</p>
<pre><code>Validator.safeStr("Hello World") // true
Validator.safeStr("Hello\x00") // false</code></pre>
<div class="method-signature">
<span class="method-name">Validator.base64</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Validates Base64 encoding format.</p>
<pre><code>Validator.base64("SGVsbG8=") // true
Validator.base64("invalid!") // false</code></pre>
<div class="method-signature">
<span class="method-name">Validator.json</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Checks if string is valid JSON.</p>
<pre><code>Validator.json("{\"key\": \"value\"}") // true
Validator.json("{invalid}") // false</code></pre>
<div class="method-signature">
<span class="method-name">Validator.ipv4</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Validates IPv4 address format.</p>
<pre><code>Validator.ipv4("192.168.1.1") // true
Validator.ipv4("256.0.0.1") // false</code></pre>
<div class="method-signature">
<span class="method-name">Validator.minLength</span>(<span class="param">value</span>, <span class="param">min</span>) → <span class="type">Bool</span>
</div>
<p>Checks minimum length of string or list.</p>
<div class="method-signature">
<span class="method-name">Validator.maxLength</span>(<span class="param">value</span>, <span class="param">max</span>) → <span class="type">Bool</span>
</div>
<p>Checks maximum length of string or list.</p>
<div class="method-signature">
<span class="method-name">Validator.range</span>(<span class="param">value</span>, <span class="param">min</span>, <span class="param">max</span>) → <span class="type">Bool</span>
</div>
<p>Checks if number is within range (inclusive).</p>
<pre><code>Validator.range(5, 1, 10) // true
Validator.range(15, 1, 10) // false</code></pre>
<div class="method-signature">
<span class="method-name">Validator.positive</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Checks if number is positive (greater than 0).</p>
<div class="method-signature">
<span class="method-name">Validator.negative</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Checks if number is negative (less than 0).</p>
<div class="method-signature">
<span class="method-name">Validator.integer</span>(<span class="param">value</span>) → <span class="type">Bool</span>
</div>
<p>Checks if number is an integer (no decimal part).</p>
<div class="method-signature">
<span class="method-name">Validator.regex</span>(<span class="param">value</span>, <span class="param">pattern</span>) → <span class="type">Bool</span>
</div>
<p>Tests if value matches a regular expression pattern.</p>
<pre><code>Validator.regex("abc123", "^[a-z]+[0-9]+$") // true</code></pre>
<h2>Field Class</h2>
<div class="class-header">
<h3>Field</h3>
<p>Factory for creating field definitions</p>
</div>
<h3>Static Methods</h3>
<div class="method-signature">
<span class="method-name">Field.string</span>() → <span class="type">StringField</span>
</div>
<div class="method-signature">
<span class="method-name">Field.string</span>(<span class="param">options</span>) → <span class="type">StringField</span>
</div>
<p>Creates a string field. Options: <code>minLength</code>, <code>maxLength</code>, <code>pattern</code>, <code>required</code>, <code>default</code>.</p>
<div class="method-signature">
<span class="method-name">Field.integer</span>() → <span class="type">IntegerField</span>
</div>
<div class="method-signature">
<span class="method-name">Field.integer</span>(<span class="param">options</span>) → <span class="type">IntegerField</span>
</div>
<p>Creates an integer field. Options: <code>min</code>, <code>max</code>, <code>required</code>, <code>default</code>.</p>
<div class="method-signature">
<span class="method-name">Field.number</span>() → <span class="type">NumberField</span>
</div>
<div class="method-signature">
<span class="method-name">Field.number</span>(<span class="param">options</span>) → <span class="type">NumberField</span>
</div>
<p>Creates a number field (integer or float). Options: <code>min</code>, <code>max</code>, <code>required</code>, <code>default</code>.</p>
<div class="method-signature">
<span class="method-name">Field.email</span>() → <span class="type">EmailField</span>
</div>
<p>Creates a field that validates email format.</p>
<div class="method-signature">
<span class="method-name">Field.boolean</span>() → <span class="type">BooleanField</span>
</div>
<p>Creates a boolean field.</p>
<div class="method-signature">
<span class="method-name">Field.list</span>(<span class="param">itemType</span>) → <span class="type">ListField</span>
</div>
<p>Creates a list field with typed items.</p>
<div class="method-signature">
<span class="method-name">Field.map</span>() → <span class="type">MapField</span>
</div>
<p>Creates a map/object field.</p>
<div class="method-signature">
<span class="method-name">Field.optional</span>(<span class="param">fieldDef</span>) → <span class="type">OptionalField</span>
</div>
<p>Makes any field optional (not required).</p>
<h2>Schema Class</h2>
<div class="class-header">
<h3>Schema</h3>
<p>Validates data against a field definition map</p>
</div>
<h3>Constructor</h3>
<div class="method-signature">
<span class="method-name">Schema.new</span>(<span class="param">definition</span>) → <span class="type">Schema</span>
</div>
<p>Creates a schema from a map of field names to field definitions.</p>
<h3>Instance Methods</h3>
<div class="method-signature">
<span class="method-name">validate</span>(<span class="param">data</span>) → <span class="type">ValidationResult</span>
</div>
<p>Validates data against the schema.</p>
<div class="method-signature">
<span class="method-name">validateOrAbort</span>(<span class="param">data</span>) → <span class="type">Map</span>
</div>
<p>Validates data and aborts on failure. Returns validated data on success.</p>
<h2>ValidationResult Class</h2>
<div class="class-header">
<h3>ValidationResult</h3>
<p>Result of schema validation</p>
</div>
<h3>Properties</h3>
<div class="method-signature">
<span class="method-name">isValid</span><span class="type">Bool</span>
</div>
<p>Whether validation passed.</p>
<div class="method-signature">
<span class="method-name">errors</span><span class="type">List</span>
</div>
<p>List of ValidationError objects.</p>
<div class="method-signature">
<span class="method-name">data</span><span class="type">Map</span>
</div>
<p>Validated and coerced data (null if invalid).</p>
<h2>Examples</h2>
<h3>Basic Schema Validation</h3>
<pre><code>import "wdantic" for Field, Schema
var userSchema = Schema.new({
"name": Field.string({"minLength": 1, "maxLength": 100}),
"email": Field.email(),
"age": Field.integer({"min": 0, "max": 150})
})
var result = userSchema.validate({
"name": "Alice",
"email": "alice@example.com",
"age": 30
})
if (result.isValid) {
System.print("Valid: %(result.data)")
} else {
for (error in result.errors) {
System.print("Error: %(error)")
}
}</code></pre>
<h3>Optional Fields</h3>
<pre><code>import "wdantic" for Field, Schema
var schema = Schema.new({
"title": Field.string(),
"description": Field.optional(Field.string()),
"tags": Field.optional(Field.list(Field.string()))
})
var result = schema.validate({
"title": "My Post"
})
System.print(result.isValid) // true</code></pre>
<h3>Nested Lists</h3>
<pre><code>import "wdantic" for Field, Schema
var schema = Schema.new({
"numbers": Field.list(Field.integer({"min": 0}))
})
var result = schema.validate({
"numbers": [1, 2, 3, -1] // -1 will fail
})
System.print(result.isValid) // false</code></pre>
<h3>Using validateOrAbort</h3>
<pre><code>import "wdantic" for Field, Schema
var schema = Schema.new({
"username": Field.string({"minLength": 3}),
"password": Field.string({"minLength": 8})
})
var data = schema.validateOrAbort({
"username": "admin",
"password": "secret123"
})</code></pre>
<h3>Standalone Validators</h3>
<pre><code>import "wdantic" for Validator
var email = "user@example.com"
if (Validator.email(email)) {
System.print("Valid email")
}
var ip = "192.168.1.1"
if (Validator.ipv4(ip)) {
System.print("Valid IP address")
}
var jsonStr = "{\"key\": 123}"
if (Validator.json(jsonStr)) {
System.print("Valid JSON")
}</code></pre>
<div class="admonition note">
<div class="admonition-title">Note</div>
<p>Field types automatically coerce values when possible. For example, <code>IntegerField</code> will convert the string <code>"42"</code> to the number <code>42</code>.</p>
</div>
</article>
<footer class="page-footer">
<a href="argparse.html" class="prev">argparse</a>
<a href="dataset.html" class="next">dataset</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+550
View File
@@ -0,0 +1,550 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>web - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="index.html">Overview</a></li>
<li><a href="http.html">http</a></li>
<li><a href="websocket.html">websocket</a></li>
<li><a href="tls.html">tls</a></li>
<li><a href="net.html">net</a></li>
<li><a href="dns.html">dns</a></li>
<li><a href="json.html">json</a></li>
<li><a href="base64.html">base64</a></li>
<li><a href="regex.html">regex</a></li>
<li><a href="jinja.html">jinja</a></li>
<li><a href="crypto.html">crypto</a></li>
<li><a href="os.html">os</a></li>
<li><a href="env.html">env</a></li>
<li><a href="signal.html">signal</a></li>
<li><a href="subprocess.html">subprocess</a></li>
<li><a href="sqlite.html">sqlite</a></li>
<li><a href="datetime.html">datetime</a></li>
<li><a href="timer.html">timer</a></li>
<li><a href="io.html">io</a></li>
<li><a href="scheduler.html">scheduler</a></li>
<li><a href="math.html">math</a></li>
<li><a href="uuid.html">uuid</a></li>
<li><a href="html.html">html</a></li>
<li><a href="argparse.html">argparse</a></li>
<li><a href="wdantic.html">wdantic</a></li>
<li><a href="dataset.html">dataset</a></li>
<li><a href="markdown.html">markdown</a></li>
<li><a href="web.html" class="active">web</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="../howto/index.html">How-To List</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">API Reference</a>
<span class="separator">/</span>
<span>web</span>
</nav>
<article>
<h1>web</h1>
<p>The <code>web</code> module provides a web framework for building HTTP servers and a client for making HTTP requests. It includes routing, middleware, sessions, static file serving, and class-based views.</p>
<pre><code>import "web" for Application, Router, Request, Response, View, Session, Client</code></pre>
<h2>Application Class</h2>
<div class="class-header">
<h3>Application</h3>
<p>HTTP server with routing and middleware</p>
</div>
<h3>Constructor</h3>
<div class="method-signature">
<span class="method-name">Application.new</span>() → <span class="type">Application</span>
</div>
<p>Creates a new web application.</p>
<h3>Properties</h3>
<div class="method-signature">
<span class="method-name">router</span><span class="type">Router</span>
</div>
<p>Access to the underlying router.</p>
<div class="method-signature">
<span class="method-name">sessionStore</span><span class="type">SessionStore</span>
</div>
<p>Access to the session storage.</p>
<h3>Routing Methods</h3>
<div class="method-signature">
<span class="method-name">get</span>(<span class="param">path</span>, <span class="param">handler</span>) → <span class="type">Application</span>
</div>
<div class="method-signature">
<span class="method-name">post</span>(<span class="param">path</span>, <span class="param">handler</span>) → <span class="type">Application</span>
</div>
<div class="method-signature">
<span class="method-name">put</span>(<span class="param">path</span>, <span class="param">handler</span>) → <span class="type">Application</span>
</div>
<div class="method-signature">
<span class="method-name">delete</span>(<span class="param">path</span>, <span class="param">handler</span>) → <span class="type">Application</span>
</div>
<div class="method-signature">
<span class="method-name">patch</span>(<span class="param">path</span>, <span class="param">handler</span>) → <span class="type">Application</span>
</div>
<p>Register route handlers. Handler receives <code>Request</code> and returns <code>Response</code>.</p>
<ul class="param-list">
<li><span class="param-name">path</span> <span class="param-type">(String)</span> - URL path with optional parameters (<code>:param</code>) or wildcards (<code>*</code>)</li>
<li><span class="param-name">handler</span> <span class="param-type">(Fn)</span> - Function receiving Request, returning Response</li>
</ul>
<div class="method-signature">
<span class="method-name">addView</span>(<span class="param">path</span>, <span class="param">viewClass</span>) → <span class="type">Application</span>
</div>
<p>Registers a class-based view for all HTTP methods.</p>
<div class="method-signature">
<span class="method-name">static_</span>(<span class="param">prefix</span>, <span class="param">directory</span>) → <span class="type">Application</span>
</div>
<p>Serves static files from a directory.</p>
<pre><code>app.static_("/assets", "./public")</code></pre>
<div class="method-signature">
<span class="method-name">use</span>(<span class="param">middleware</span>) → <span class="type">Application</span>
</div>
<p>Adds middleware function. Middleware receives Request, returns Response or null to continue.</p>
<div class="method-signature">
<span class="method-name">run</span>(<span class="param">host</span>, <span class="param">port</span>)
</div>
<p>Starts the server (blocking).</p>
<h2>Request Class</h2>
<div class="class-header">
<h3>Request</h3>
<p>Incoming HTTP request</p>
</div>
<h3>Properties</h3>
<table>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
<tr>
<td><code>method</code></td>
<td>String</td>
<td>HTTP method (GET, POST, etc.)</td>
</tr>
<tr>
<td><code>path</code></td>
<td>String</td>
<td>Request path without query string</td>
</tr>
<tr>
<td><code>query</code></td>
<td>Map</td>
<td>Parsed query parameters</td>
</tr>
<tr>
<td><code>headers</code></td>
<td>Map</td>
<td>Request headers</td>
</tr>
<tr>
<td><code>body</code></td>
<td>String</td>
<td>Raw request body</td>
</tr>
<tr>
<td><code>params</code></td>
<td>Map</td>
<td>Route parameters from URL</td>
</tr>
<tr>
<td><code>cookies</code></td>
<td>Map</td>
<td>Parsed cookies</td>
</tr>
<tr>
<td><code>session</code></td>
<td>Session</td>
<td>Session data</td>
</tr>
</table>
<h3>Methods</h3>
<div class="method-signature">
<span class="method-name">header</span>(<span class="param">name</span>) → <span class="type">String|null</span>
</div>
<p>Gets header value (case-insensitive).</p>
<div class="method-signature">
<span class="method-name">json</span><span class="type">Map|List</span>
</div>
<p>Parses body as JSON (cached).</p>
<div class="method-signature">
<span class="method-name">form</span><span class="type">Map</span>
</div>
<p>Parses body as form data (cached).</p>
<h2>Response Class</h2>
<div class="class-header">
<h3>Response</h3>
<p>HTTP response builder</p>
</div>
<h3>Static Factory Methods</h3>
<div class="method-signature">
<span class="method-name">Response.text</span>(<span class="param">content</span>) → <span class="type">Response</span>
</div>
<p>Creates plain text response.</p>
<div class="method-signature">
<span class="method-name">Response.html</span>(<span class="param">content</span>) → <span class="type">Response</span>
</div>
<p>Creates HTML response.</p>
<div class="method-signature">
<span class="method-name">Response.json</span>(<span class="param">data</span>) → <span class="type">Response</span>
</div>
<p>Creates JSON response (automatically stringifies).</p>
<div class="method-signature">
<span class="method-name">Response.redirect</span>(<span class="param">url</span>) → <span class="type">Response</span>
</div>
<div class="method-signature">
<span class="method-name">Response.redirect</span>(<span class="param">url</span>, <span class="param">status</span>) → <span class="type">Response</span>
</div>
<p>Creates redirect response (default 302).</p>
<div class="method-signature">
<span class="method-name">Response.file</span>(<span class="param">path</span>) → <span class="type">Response</span>
</div>
<div class="method-signature">
<span class="method-name">Response.file</span>(<span class="param">path</span>, <span class="param">contentType</span>) → <span class="type">Response</span>
</div>
<p>Serves a file. Auto-detects content type if not specified.</p>
<h3>Instance Methods</h3>
<div class="method-signature">
<span class="method-name">header</span>(<span class="param">name</span>, <span class="param">value</span>) → <span class="type">Response</span>
</div>
<p>Sets a response header.</p>
<div class="method-signature">
<span class="method-name">cookie</span>(<span class="param">name</span>, <span class="param">value</span>) → <span class="type">Response</span>
</div>
<div class="method-signature">
<span class="method-name">cookie</span>(<span class="param">name</span>, <span class="param">value</span>, <span class="param">options</span>) → <span class="type">Response</span>
</div>
<p>Sets a cookie. Options: <code>path</code>, <code>maxAge</code>, <code>httpOnly</code>, <code>secure</code>.</p>
<h3>Properties</h3>
<div class="method-signature">
<span class="method-name">status</span><span class="type">Num</span>
</div>
<p>Gets or sets HTTP status code.</p>
<div class="method-signature">
<span class="method-name">body</span><span class="type">String</span>
</div>
<p>Gets or sets response body.</p>
<h2>View Class</h2>
<div class="class-header">
<h3>View</h3>
<p>Base class for class-based views</p>
</div>
<p>Subclass and override methods for each HTTP method:</p>
<pre><code>class UserView is View {
get(request) {
return Response.json({"users": []})
}
post(request) {
var data = request.json
return Response.json({"created": data})
}
}</code></pre>
<h2>Session Class</h2>
<div class="class-header">
<h3>Session</h3>
<p>Session data storage</p>
</div>
<h3>Properties and Methods</h3>
<div class="method-signature">
<span class="method-name">id</span><span class="type">String</span>
</div>
<p>The session ID.</p>
<div class="method-signature">
<span class="method-name">[key]</span><span class="type">any</span>
</div>
<p>Gets session value.</p>
<div class="method-signature">
<span class="method-name">[key]=</span>(<span class="param">value</span>)
</div>
<p>Sets session value.</p>
<div class="method-signature">
<span class="method-name">remove</span>(<span class="param">key</span>)
</div>
<p>Removes a session key.</p>
<h2>Client Class</h2>
<div class="class-header">
<h3>Client</h3>
<p>HTTP client for making requests</p>
</div>
<h3>Static Methods</h3>
<div class="method-signature">
<span class="method-name">Client.get</span>(<span class="param">url</span>) → <span class="type">Map</span>
</div>
<div class="method-signature">
<span class="method-name">Client.get</span>(<span class="param">url</span>, <span class="param">options</span>) → <span class="type">Map</span>
</div>
<p>Makes GET request.</p>
<div class="method-signature">
<span class="method-name">Client.post</span>(<span class="param">url</span>) → <span class="type">Map</span>
</div>
<div class="method-signature">
<span class="method-name">Client.post</span>(<span class="param">url</span>, <span class="param">options</span>) → <span class="type">Map</span>
</div>
<p>Makes POST request.</p>
<div class="method-signature">
<span class="method-name">Client.put</span>(<span class="param">url</span>, <span class="param">options</span>) → <span class="type">Map</span>
</div>
<p>Makes PUT request.</p>
<div class="method-signature">
<span class="method-name">Client.delete</span>(<span class="param">url</span>, <span class="param">options</span>) → <span class="type">Map</span>
</div>
<p>Makes DELETE request.</p>
<h3>Client Options</h3>
<table>
<tr>
<th>Option</th>
<th>Type</th>
<th>Description</th>
</tr>
<tr>
<td><code>headers</code></td>
<td>Map</td>
<td>Request headers</td>
</tr>
<tr>
<td><code>body</code></td>
<td>String</td>
<td>Request body</td>
</tr>
<tr>
<td><code>json</code></td>
<td>Map/List</td>
<td>JSON body (auto-stringifies and sets Content-Type)</td>
</tr>
</table>
<h3>Response Format</h3>
<pre><code>{
"status": 200,
"headers": {"Content-Type": "application/json"},
"body": "{...}"
}</code></pre>
<h2>Examples</h2>
<h3>Basic Server</h3>
<pre><code>import "web" for Application, Response
var app = Application.new()
app.get("/", Fn.new { |req|
return Response.html("&lt;h1&gt;Hello World&lt;/h1&gt;")
})
app.get("/api/users", Fn.new { |req|
return Response.json({"users": ["Alice", "Bob"]})
})
app.run("0.0.0.0", 8080)</code></pre>
<h3>Route Parameters</h3>
<pre><code>import "web" for Application, Response
var app = Application.new()
app.get("/users/:id", Fn.new { |req|
var userId = req.params["id"]
return Response.json({"id": userId})
})
app.get("/files/*", Fn.new { |req|
return Response.text("Wildcard route")
})
app.run("0.0.0.0", 8080)</code></pre>
<h3>Class-Based Views</h3>
<pre><code>import "web" for Application, Response, View
class ArticleView is View {
get(request) {
return Response.json({"articles": []})
}
post(request) {
var data = request.json
return Response.json({"created": data})
}
}
var app = Application.new()
app.addView("/articles", ArticleView)
app.run("0.0.0.0", 8080)</code></pre>
<h3>Sessions</h3>
<pre><code>import "web" for Application, Response
var app = Application.new()
app.get("/login", Fn.new { |req|
req.session["user"] = "Alice"
return Response.text("Logged in")
})
app.get("/profile", Fn.new { |req|
var user = req.session["user"]
if (user == null) {
return Response.redirect("/login")
}
return Response.text("Hello, %(user)")
})
app.run("0.0.0.0", 8080)</code></pre>
<h3>Middleware</h3>
<pre><code>import "web" for Application, Response
var app = Application.new()
app.use(Fn.new { |req|
System.print("%(req.method) %(req.path)")
return null
})
app.use(Fn.new { |req|
if (req.path.startsWith("/admin") &amp;&amp; !req.session["isAdmin"]) {
return Response.redirect("/login")
}
return null
})
app.get("/", Fn.new { |req|
return Response.text("Home")
})
app.run("0.0.0.0", 8080)</code></pre>
<h3>HTTP Client</h3>
<pre><code>import "web" for Client
import "json" for Json
var response = Client.get("https://api.example.com/data")
System.print("Status: %(response["status"])")
System.print("Body: %(response["body"])")
var postResponse = Client.post("https://api.example.com/users", {
"json": {"name": "Alice", "email": "alice@example.com"}
})
var data = Json.parse(postResponse["body"])</code></pre>
<div class="admonition note">
<div class="admonition-title">Note</div>
<p>Sessions are stored in memory by default. Data is lost when the server restarts. For production, consider persisting session data to a database.</p>
</div>
</article>
<footer class="page-footer">
<a href="markdown.html" class="prev">markdown</a>
<a href="index.html" class="next">Overview</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>