feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
// Please do not edit this file. It has been generated automatically
|
|
|
|
|
// from `src/module/markdown.wren` using `util/wren_to_c_string.py`
|
|
|
|
|
|
|
|
|
|
static const char* markdownModuleSource =
|
|
|
|
|
"// retoor <retoor@molodetz.nl>\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"import \"html\" for Html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"class Markdown {\n"
|
|
|
|
|
" static toHtml(text) { toHtml(text, {}) }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static toHtml(text, options) {\n"
|
|
|
|
|
" var safeMode = options.containsKey(\"safeMode\") ? options[\"safeMode\"] : false\n"
|
|
|
|
|
" var lines = text.split(\"\\n\")\n"
|
|
|
|
|
" var result = []\n"
|
|
|
|
|
" var inCodeBlock = false\n"
|
|
|
|
|
" var codeBlockContent = []\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var codeBlockLang = null\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" var inList = false\n"
|
|
|
|
|
" var listType = null\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var listClass = null\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" var inBlockquote = false\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var inTable = false\n"
|
|
|
|
|
" var tableRows = []\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
"\n"
|
|
|
|
|
" for (i in 0...lines.count) {\n"
|
|
|
|
|
" var line = lines[i]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (line.startsWith(\"```\")) {\n"
|
|
|
|
|
" if (inCodeBlock) {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var langAttr = codeBlockLang != null ? \" class=\\\"language-%(codeBlockLang)\\\"\" : \"\"\n"
|
|
|
|
|
" result.add(\"<pre><code%(langAttr)>\" + (safeMode ? Html.quote(codeBlockContent.join(\"\\n\")) : codeBlockContent.join(\"\\n\")) + \"</code></pre>\")\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" codeBlockContent = []\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" codeBlockLang = null\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" inCodeBlock = false\n"
|
|
|
|
|
" } else {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" closeTable_(result, inTable, tableRows, safeMode)\n"
|
|
|
|
|
" inTable = false\n"
|
|
|
|
|
" tableRows = []\n"
|
|
|
|
|
" closeList_(result, inList, listType, listClass)\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" inList = false\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" listClass = null\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" inCodeBlock = true\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var lang = line[3..-1].trim()\n"
|
|
|
|
|
" if (lang.count > 0) codeBlockLang = lang\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" }\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (inCodeBlock) {\n"
|
|
|
|
|
" codeBlockContent.add(line)\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" if (isTableRow_(line)) {\n"
|
|
|
|
|
" if (!inTable) {\n"
|
|
|
|
|
" closeList_(result, inList, listType, listClass)\n"
|
|
|
|
|
" inList = false\n"
|
|
|
|
|
" listClass = null\n"
|
|
|
|
|
" if (inBlockquote) {\n"
|
|
|
|
|
" result.add(\"</blockquote>\")\n"
|
|
|
|
|
" inBlockquote = false\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" inTable = true\n"
|
|
|
|
|
" tableRows = []\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" tableRows.add(line)\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (inTable) {\n"
|
|
|
|
|
" result.add(buildTable_(tableRows, safeMode))\n"
|
|
|
|
|
" inTable = false\n"
|
|
|
|
|
" tableRows = []\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" if (line.count == 0) {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" closeList_(result, inList, listType, listClass)\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" inList = false\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" listClass = null\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" if (inBlockquote) {\n"
|
|
|
|
|
" result.add(\"</blockquote>\")\n"
|
|
|
|
|
" inBlockquote = false\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (line.startsWith(\"> \")) {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" closeList_(result, inList, listType, listClass)\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" inList = false\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" listClass = null\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" if (!inBlockquote) {\n"
|
|
|
|
|
" result.add(\"<blockquote>\")\n"
|
|
|
|
|
" inBlockquote = true\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" result.add(\"<p>\" + processInline_(line[2..-1], safeMode) + \"</p>\")\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (line.startsWith(\"---\") || line.startsWith(\"***\") || line.startsWith(\"___\")) {\n"
|
|
|
|
|
" var isHr = true\n"
|
|
|
|
|
" for (c in line) {\n"
|
|
|
|
|
" if (c != \"-\" && c != \"*\" && c != \"_\" && c != \" \") {\n"
|
|
|
|
|
" isHr = false\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (isHr && line.count >= 3) {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" closeList_(result, inList, listType, listClass)\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" inList = false\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" listClass = null\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" result.add(\"<hr>\")\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var heading = parseHeading_(line)\n"
|
|
|
|
|
" if (heading) {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" closeList_(result, inList, listType, listClass)\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" inList = false\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" listClass = null\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" result.add(\"<h%(heading[\"level\"])>\" + processInline_(heading[\"text\"], safeMode) + \"</h%(heading[\"level\"])>\")\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var listItem = parseListItem_(line, safeMode)\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" if (listItem) {\n"
|
|
|
|
|
" var newType = listItem[\"type\"]\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var newClass = listItem[\"class\"]\n"
|
|
|
|
|
" if (!inList || listType != newType || listClass != newClass) {\n"
|
|
|
|
|
" closeList_(result, inList, listType, listClass)\n"
|
|
|
|
|
" var classAttr = newClass != null ? \" class=\\\"%(newClass)\\\"\" : \"\"\n"
|
|
|
|
|
" result.add(newType == \"ul\" ? \"<ul%(classAttr)>\" : \"<ol%(classAttr)>\")\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" inList = true\n"
|
|
|
|
|
" listType = newType\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" listClass = newClass\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" }\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" result.add(listItem[\"html\"])\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" closeList_(result, inList, listType, listClass)\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" inList = false\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" listClass = null\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" result.add(\"<p>\" + processInline_(line, safeMode) + \"</p>\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" closeTable_(result, inTable, tableRows, safeMode)\n"
|
|
|
|
|
" closeList_(result, inList, listType, listClass)\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" if (inBlockquote) {\n"
|
|
|
|
|
" result.add(\"</blockquote>\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (inCodeBlock) {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var langAttr = codeBlockLang != null ? \" class=\\\"language-%(codeBlockLang)\\\"\" : \"\"\n"
|
|
|
|
|
" result.add(\"<pre><code%(langAttr)>\" + (safeMode ? Html.quote(codeBlockContent.join(\"\\n\")) : codeBlockContent.join(\"\\n\")) + \"</code></pre>\")\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result.join(\"\\n\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" static closeList_(result, inList, listType, listClass) {\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" if (inList) {\n"
|
|
|
|
|
" result.add(listType == \"ul\" ? \"</ul>\" : \"</ol>\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" static closeTable_(result, inTable, tableRows, safeMode) {\n"
|
|
|
|
|
" if (inTable && tableRows.count > 0) {\n"
|
|
|
|
|
" result.add(buildTable_(tableRows, safeMode))\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static isTableRow_(line) {\n"
|
|
|
|
|
" var trimmed = line.trim()\n"
|
|
|
|
|
" return trimmed.contains(\"|\") && (trimmed.startsWith(\"|\") || trimmed.endsWith(\"|\"))\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static isTableSeparator_(line) {\n"
|
|
|
|
|
" var trimmed = line.trim()\n"
|
|
|
|
|
" if (!trimmed.contains(\"|\")) return false\n"
|
|
|
|
|
" if (!trimmed.contains(\"-\")) return false\n"
|
|
|
|
|
" for (c in trimmed) {\n"
|
|
|
|
|
" if (c != \"|\" && c != \"-\" && c != \":\" && c != \" \") return false\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return true\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static splitTableCells_(line) {\n"
|
|
|
|
|
" var trimmed = line.trim()\n"
|
|
|
|
|
" if (trimmed.startsWith(\"|\")) trimmed = trimmed[1..-1]\n"
|
|
|
|
|
" if (trimmed.endsWith(\"|\")) trimmed = trimmed[0..-2]\n"
|
|
|
|
|
" return trimmed.split(\"|\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static parseTableAlignments_(line) {\n"
|
|
|
|
|
" var cells = splitTableCells_(line)\n"
|
|
|
|
|
" var alignments = []\n"
|
|
|
|
|
" for (cell in cells) {\n"
|
|
|
|
|
" var t = cell.trim()\n"
|
|
|
|
|
" var left = t.count > 0 && t[0] == \":\"\n"
|
|
|
|
|
" var right = t.count > 0 && t[-1] == \":\"\n"
|
|
|
|
|
" if (left && right) {\n"
|
|
|
|
|
" alignments.add(\"center\")\n"
|
|
|
|
|
" } else if (right) {\n"
|
|
|
|
|
" alignments.add(\"right\")\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" alignments.add(\"left\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return alignments\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static buildTable_(rows, safeMode) {\n"
|
|
|
|
|
" if (rows.count < 2) return \"\"\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var separatorIdx = -1\n"
|
|
|
|
|
" for (i in 1...rows.count) {\n"
|
|
|
|
|
" if (isTableSeparator_(rows[i])) {\n"
|
|
|
|
|
" separatorIdx = i\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (separatorIdx < 0) return \"\"\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var alignments = parseTableAlignments_(rows[separatorIdx])\n"
|
|
|
|
|
" var html = [\"<table>\", \"<thead>\", \"<tr>\"]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" for (r in 0...separatorIdx) {\n"
|
|
|
|
|
" var headerCells = splitTableCells_(rows[r])\n"
|
|
|
|
|
" for (i in 0...headerCells.count) {\n"
|
|
|
|
|
" var align = i < alignments.count ? alignments[i] : \"left\"\n"
|
|
|
|
|
" var style = align != \"left\" ? \" style=\\\"text-align:%(align)\\\"\" : \"\"\n"
|
|
|
|
|
" html.add(\"<th%(style)>\" + processInline_(headerCells[i].trim(), safeMode) + \"</th>\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" html.add(\"</tr>\")\n"
|
|
|
|
|
" html.add(\"</thead>\")\n"
|
|
|
|
|
" html.add(\"<tbody>\")\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" for (r in (separatorIdx + 1)...rows.count) {\n"
|
|
|
|
|
" var cells = splitTableCells_(rows[r])\n"
|
|
|
|
|
" html.add(\"<tr>\")\n"
|
|
|
|
|
" for (i in 0...cells.count) {\n"
|
|
|
|
|
" var align = i < alignments.count ? alignments[i] : \"left\"\n"
|
|
|
|
|
" var style = align != \"left\" ? \" style=\\\"text-align:%(align)\\\"\" : \"\"\n"
|
|
|
|
|
" html.add(\"<td%(style)>\" + processInline_(cells[i].trim(), safeMode) + \"</td>\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" html.add(\"</tr>\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" html.add(\"</tbody>\")\n"
|
|
|
|
|
" html.add(\"</table>\")\n"
|
|
|
|
|
" return html.join(\"\\n\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" static parseHeading_(line) {\n"
|
|
|
|
|
" var level = 0\n"
|
|
|
|
|
" for (c in line) {\n"
|
|
|
|
|
" if (c == \"#\") {\n"
|
|
|
|
|
" level = level + 1\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (level > 0 && level <= 6 && line.count > level && line[level] == \" \") {\n"
|
|
|
|
|
" return {\"level\": level, \"text\": line[level + 1..-1]}\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return null\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static parseListItem_(line) {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" return parseListItem_(line, false)\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static parseListItem_(line, safeMode) {\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" var trimmed = line\n"
|
|
|
|
|
" var indent = 0\n"
|
|
|
|
|
" while (trimmed.count > 0 && trimmed[0] == \" \") {\n"
|
|
|
|
|
" trimmed = trimmed[1..-1]\n"
|
|
|
|
|
" indent = indent + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (trimmed.count >= 2 && (trimmed[0] == \"-\" || trimmed[0] == \"*\" || trimmed[0] == \"+\") && trimmed[1] == \" \") {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var text = trimmed[2..-1]\n"
|
|
|
|
|
" var taskInfo = parseTaskCheckbox_(text)\n"
|
|
|
|
|
" if (taskInfo) {\n"
|
|
|
|
|
" var checkbox = taskInfo[\"checked\"] ?\n"
|
|
|
|
|
" \"<input type=\\\"checkbox\\\" disabled checked>\" :\n"
|
|
|
|
|
" \"<input type=\\\"checkbox\\\" disabled>\"\n"
|
|
|
|
|
" return {\n"
|
|
|
|
|
" \"type\": \"ul\",\n"
|
|
|
|
|
" \"text\": taskInfo[\"text\"],\n"
|
|
|
|
|
" \"class\": \"task-list\",\n"
|
|
|
|
|
" \"html\": \"<li>\" + checkbox + \" \" + processInline_(taskInfo[\"text\"], safeMode) + \"</li>\"\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return {\n"
|
|
|
|
|
" \"type\": \"ul\",\n"
|
|
|
|
|
" \"text\": text,\n"
|
|
|
|
|
" \"class\": null,\n"
|
|
|
|
|
" \"html\": \"<li>\" + processInline_(text, safeMode) + \"</li>\"\n"
|
|
|
|
|
" }\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
" while (i < trimmed.count) {\n"
|
|
|
|
|
" var c = trimmed[i].codePoints.toList[0]\n"
|
|
|
|
|
" if (c < 48 || c > 57) break\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (i > 0 && i < trimmed.count - 1 && trimmed[i] == \".\" && trimmed[i + 1] == \" \") {\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" var text = trimmed[i + 2..-1]\n"
|
|
|
|
|
" return {\n"
|
|
|
|
|
" \"type\": \"ol\",\n"
|
|
|
|
|
" \"text\": text,\n"
|
|
|
|
|
" \"class\": null,\n"
|
|
|
|
|
" \"html\": \"<li>\" + processInline_(text, safeMode) + \"</li>\"\n"
|
|
|
|
|
" }\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return null\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" static parseTaskCheckbox_(text) {\n"
|
|
|
|
|
" if (text.count >= 3) {\n"
|
|
|
|
|
" if (text.startsWith(\"[ ] \")) {\n"
|
|
|
|
|
" return {\"checked\": false, \"text\": text[4..-1]}\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (text.startsWith(\"[x] \") || text.startsWith(\"[X] \")) {\n"
|
|
|
|
|
" return {\"checked\": true, \"text\": text[4..-1]}\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return null\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" static processInline_(text, safeMode) {\n"
|
|
|
|
|
" if (safeMode) text = Html.quote(text)\n"
|
|
|
|
|
" text = processCode_(text)\n"
|
|
|
|
|
" text = processBold_(text)\n"
|
|
|
|
|
" text = processItalic_(text)\n"
|
|
|
|
|
" text = processStrikethrough_(text)\n"
|
|
|
|
|
" text = processImages_(text)\n"
|
|
|
|
|
" text = processLinks_(text)\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" text = processAutolinks_(text)\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" return text\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" static processAutolinks_(text) {\n"
|
|
|
|
|
" var result = text\n"
|
|
|
|
|
" result = processUrlAutolinks_(result, \"https://\")\n"
|
|
|
|
|
" result = processUrlAutolinks_(result, \"http://\")\n"
|
|
|
|
|
" result = processEmailAutolinks_(result)\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processUrlAutolinks_(text, protocol) {\n"
|
|
|
|
|
" var result = text\n"
|
|
|
|
|
" var searchPos = 0\n"
|
|
|
|
|
" while (true) {\n"
|
|
|
|
|
" if (result.count < protocol.count) break\n"
|
|
|
|
|
" if (searchPos > result.count - protocol.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var idx = findProtocol_(result, protocol, searchPos)\n"
|
|
|
|
|
" if (idx < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (idx > 0 && result[idx - 1] == \"\\\"\") {\n"
|
|
|
|
|
" searchPos = idx + 1\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (idx >= 6) {\n"
|
|
|
|
|
" var prefix = result[idx - 6...idx]\n"
|
|
|
|
|
" if (prefix == \"href=\\\"\" || prefix == \"href='\") {\n"
|
|
|
|
|
" searchPos = idx + 1\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var urlEnd = idx + protocol.count\n"
|
|
|
|
|
" while (urlEnd < result.count) {\n"
|
|
|
|
|
" var c = result[urlEnd]\n"
|
|
|
|
|
" if (c == \" \" || c == \"\\t\" || c == \"\\n\" || c == \"<\" || c == \">\" || c == \"\\\"\" || c == \")\") break\n"
|
|
|
|
|
" urlEnd = urlEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var url = result[idx...urlEnd]\n"
|
|
|
|
|
" var before = result[0...idx]\n"
|
|
|
|
|
" var after = result[urlEnd..-1]\n"
|
|
|
|
|
" var replacement = \"<a href=\\\"%(url)\\\">%(url)</a>\"\n"
|
|
|
|
|
" result = before + replacement + after\n"
|
|
|
|
|
" searchPos = idx + replacement.count\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static findProtocol_(text, protocol, start) {\n"
|
|
|
|
|
" var maxPos = text.count - protocol.count\n"
|
|
|
|
|
" var i = start\n"
|
|
|
|
|
" while (i <= maxPos) {\n"
|
|
|
|
|
" var match = true\n"
|
|
|
|
|
" var j = 0\n"
|
|
|
|
|
" while (j < protocol.count) {\n"
|
|
|
|
|
" if (text[i + j] != protocol[j]) {\n"
|
|
|
|
|
" match = false\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" j = j + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (match) return i\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return -1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processEmailAutolinks_(text) {\n"
|
|
|
|
|
" var result = text\n"
|
|
|
|
|
" var searchPos = 0\n"
|
|
|
|
|
" while (true) {\n"
|
|
|
|
|
" var atIdx = -1\n"
|
|
|
|
|
" for (i in searchPos...result.count) {\n"
|
|
|
|
|
" if (result[i] == \"@\") {\n"
|
|
|
|
|
" atIdx = i\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (atIdx < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (atIdx > 0 && result[atIdx - 1] == \"\\\"\") {\n"
|
|
|
|
|
" searchPos = atIdx + 1\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var localStart = atIdx\n"
|
|
|
|
|
" while (localStart > 0) {\n"
|
|
|
|
|
" var c = result[localStart - 1]\n"
|
|
|
|
|
" if (!isEmailChar_(c)) break\n"
|
|
|
|
|
" localStart = localStart - 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var domainEnd = atIdx + 1\n"
|
|
|
|
|
" var hasDot = false\n"
|
|
|
|
|
" while (domainEnd < result.count) {\n"
|
|
|
|
|
" var c = result[domainEnd]\n"
|
|
|
|
|
" if (c == \".\") hasDot = true\n"
|
|
|
|
|
" if (!isEmailChar_(c) && c != \".\") break\n"
|
|
|
|
|
" domainEnd = domainEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (localStart < atIdx && atIdx + 1 < domainEnd && hasDot) {\n"
|
|
|
|
|
" var email = result[localStart...domainEnd]\n"
|
|
|
|
|
" var before = result[0...localStart]\n"
|
|
|
|
|
" var after = result[domainEnd..-1]\n"
|
|
|
|
|
" var replacement = \"<a href=\\\"mailto:%(email)\\\">%(email)</a>\"\n"
|
|
|
|
|
" result = before + replacement + after\n"
|
|
|
|
|
" searchPos = localStart + replacement.count\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" searchPos = atIdx + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static isEmailChar_(c) {\n"
|
|
|
|
|
" var cp = c.codePoints.toList[0]\n"
|
|
|
|
|
" if (cp >= 97 && cp <= 122) return true\n"
|
|
|
|
|
" if (cp >= 65 && cp <= 90) return true\n"
|
|
|
|
|
" if (cp >= 48 && cp <= 57) return true\n"
|
|
|
|
|
" if (c == \".\" || c == \"-\" || c == \"_\" || c == \"+\") return true\n"
|
|
|
|
|
" return false\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
" static processCode_(text) {\n"
|
|
|
|
|
" var result = \"\"\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
" var chars = text.toList\n"
|
|
|
|
|
" while (i < chars.count) {\n"
|
|
|
|
|
" if (chars[i] == \"`\") {\n"
|
|
|
|
|
" var end = i + 1\n"
|
|
|
|
|
" while (end < chars.count && chars[end] != \"`\") {\n"
|
|
|
|
|
" end = end + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (end < chars.count) {\n"
|
|
|
|
|
" var code = \"\"\n"
|
|
|
|
|
" for (j in (i + 1)...end) {\n"
|
|
|
|
|
" code = code + chars[j]\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" result = result + \"<code>\" + code + \"</code>\"\n"
|
|
|
|
|
" i = end + 1\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" result = result + chars[i]\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" result = result + chars[i]\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processBold_(text) {\n"
|
|
|
|
|
" var result = text\n"
|
|
|
|
|
" while (result.contains(\"**\")) {\n"
|
|
|
|
|
" var start = result.indexOf(\"**\")\n"
|
|
|
|
|
" var rest = result[start + 2..-1]\n"
|
|
|
|
|
" var end = rest.indexOf(\"**\")\n"
|
|
|
|
|
" if (end >= 0) {\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var content = rest[0...end]\n"
|
|
|
|
|
" var after = rest[end + 2..-1]\n"
|
|
|
|
|
" result = before + \"<strong>\" + content + \"</strong>\" + after\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" while (result.contains(\"__\")) {\n"
|
|
|
|
|
" var start = result.indexOf(\"__\")\n"
|
|
|
|
|
" var rest = result[start + 2..-1]\n"
|
|
|
|
|
" var end = rest.indexOf(\"__\")\n"
|
|
|
|
|
" if (end >= 0) {\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var content = rest[0...end]\n"
|
|
|
|
|
" var after = rest[end + 2..-1]\n"
|
|
|
|
|
" result = before + \"<strong>\" + content + \"</strong>\" + after\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processItalic_(text) {\n"
|
|
|
|
|
" var result = text\n"
|
|
|
|
|
" while (result.contains(\"*\")) {\n"
|
|
|
|
|
" var start = result.indexOf(\"*\")\n"
|
|
|
|
|
" if (start > 0 && result[start - 1] == \"<\") {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" var rest = result[start + 1..-1]\n"
|
|
|
|
|
" var end = rest.indexOf(\"*\")\n"
|
|
|
|
|
" if (end >= 0 && end > 0) {\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var content = rest[0...end]\n"
|
|
|
|
|
" var after = rest[end + 1..-1]\n"
|
|
|
|
|
" result = before + \"<em>\" + content + \"</em>\" + after\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processStrikethrough_(text) {\n"
|
|
|
|
|
" var result = text\n"
|
|
|
|
|
" while (result.contains(\"~~\")) {\n"
|
|
|
|
|
" var start = result.indexOf(\"~~\")\n"
|
|
|
|
|
" var rest = result[start + 2..-1]\n"
|
|
|
|
|
" var end = rest.indexOf(\"~~\")\n"
|
|
|
|
|
" if (end >= 0) {\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var content = rest[0...end]\n"
|
|
|
|
|
" var after = rest[end + 2..-1]\n"
|
|
|
|
|
" result = before + \"<del>\" + content + \"</del>\" + after\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processLinks_(text) {\n"
|
|
|
|
|
" var result = text\n"
|
|
|
|
|
" while (result.contains(\"](\")) {\n"
|
|
|
|
|
" var linkEnd = result.indexOf(\"](\")\n"
|
|
|
|
|
" var textStart = linkEnd\n"
|
|
|
|
|
" while (textStart > 0 && result[textStart - 1] != \"[\") {\n"
|
|
|
|
|
" textStart = textStart - 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (textStart > 0 && result[textStart - 1] == \"[\") {\n"
|
|
|
|
|
" var urlStart = linkEnd + 2\n"
|
|
|
|
|
" var urlEnd = urlStart\n"
|
|
|
|
|
" while (urlEnd < result.count && result[urlEnd] != \")\") {\n"
|
|
|
|
|
" urlEnd = urlEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (urlEnd < result.count) {\n"
|
|
|
|
|
" var before = result[0...textStart - 1]\n"
|
|
|
|
|
" var linkText = result[textStart...linkEnd]\n"
|
|
|
|
|
" var url = result[urlStart...urlEnd]\n"
|
|
|
|
|
" var after = result[urlEnd + 1..-1]\n"
|
|
|
|
|
" result = before + \"<a href=\\\"\" + url + \"\\\">\" + linkText + \"</a>\" + after\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processImages_(text) {\n"
|
|
|
|
|
" var result = text\n"
|
|
|
|
|
" while (result.contains(\"![\")) {\n"
|
|
|
|
|
" var start = result.indexOf(\"![\")\n"
|
|
|
|
|
" var altEnd = start + 2\n"
|
|
|
|
|
" while (altEnd < result.count && result[altEnd] != \"]\") {\n"
|
|
|
|
|
" altEnd = altEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (altEnd < result.count && altEnd + 1 < result.count && result[altEnd + 1] == \"(\") {\n"
|
|
|
|
|
" var urlStart = altEnd + 2\n"
|
|
|
|
|
" var urlEnd = urlStart\n"
|
|
|
|
|
" while (urlEnd < result.count && result[urlEnd] != \")\") {\n"
|
|
|
|
|
" urlEnd = urlEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (urlEnd < result.count) {\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var alt = result[start + 2...altEnd]\n"
|
|
|
|
|
" var url = result[urlStart...urlEnd]\n"
|
|
|
|
|
" var after = result[urlEnd + 1..-1]\n"
|
|
|
|
|
" result = before + \"<img src=\\\"\" + url + \"\\\" alt=\\\"\" + alt + \"\\\">\" + after\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
feat: add merge_all_wren utility, strutil demo, and 7 new API manual pages
Add WrenFileReader class in apps/merge_all_wren.wren for recursive .wren file discovery and content printing. Introduce example/strutil_demo.wren demonstrating case conversion, hex encoding, SHA256 hashing, string repetition, padding, HTML/JSON escaping, and URL encoding/decoding. Create manual/api pages for argparse, dataset, html, markdown, uuid, wdantic, and web modules. Update manual/api/index.html sidebar and module count from 21 to 28, adding links and cards for the new modules.
2026-01-25 02:47:47 +01:00
|
|
|
"\n"
|
|
|
|
|
" static fromHtml(html) { fromHtml(html, {}) }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static fromHtml(html, options) {\n"
|
|
|
|
|
" var stripUnknown = options.containsKey(\"stripUnknown\") ? options[\"stripUnknown\"] : true\n"
|
|
|
|
|
" var text = html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" text = removeHiddenTags_(text)\n"
|
|
|
|
|
" text = processBlockElements_(text)\n"
|
|
|
|
|
" text = processInlineFromHtml_(text)\n"
|
|
|
|
|
" text = Html.unquote(text)\n"
|
|
|
|
|
" text = cleanupWhitespace_(text)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return text.trim()\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static removeHiddenTags_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" var tags = [\"script\", \"style\", \"head\", \"meta\", \"link\", \"noscript\"]\n"
|
|
|
|
|
" for (tag in tags) {\n"
|
|
|
|
|
" result = removeTagWithContent_(result, tag)\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static removeTagWithContent_(html, tag) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" var openTag = \"<\" + tag\n"
|
|
|
|
|
" var closeTag = \"</\" + tag + \">\"\n"
|
|
|
|
|
" while (true) {\n"
|
|
|
|
|
" var startLower = result.indexOf(openTag)\n"
|
|
|
|
|
" var startUpper = result.indexOf(\"<\" + tag[0].codePoints.toList[0].toString)\n"
|
|
|
|
|
" var start = -1\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
" while (i < result.count - openTag.count) {\n"
|
|
|
|
|
" if (matchTagName_(result, i, tag)) {\n"
|
|
|
|
|
" start = i\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (start < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var tagEnd = start\n"
|
|
|
|
|
" while (tagEnd < result.count && result[tagEnd] != \">\") {\n"
|
|
|
|
|
" tagEnd = tagEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (tagEnd >= result.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (result[tagEnd - 1] == \"/\") {\n"
|
|
|
|
|
" result = result[0...start] + result[tagEnd + 1..-1]\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(result, tagEnd + 1, tag)\n"
|
|
|
|
|
" if (closeStart < 0) {\n"
|
|
|
|
|
" result = result[0...start] + result[tagEnd + 1..-1]\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < result.count && result[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" result = result[0...start] + result[closeEnd + 1..-1]\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static matchTagName_(html, pos, tag) {\n"
|
|
|
|
|
" if (pos >= html.count || html[pos] != \"<\") return false\n"
|
|
|
|
|
" var rest = html[pos + 1..-1].trim()\n"
|
|
|
|
|
" var tagLower = tag\n"
|
|
|
|
|
" for (i in 0...tag.count) {\n"
|
|
|
|
|
" if (i >= rest.count) return false\n"
|
|
|
|
|
" var c1 = rest[i].codePoints.toList[0]\n"
|
|
|
|
|
" var c2 = tag[i].codePoints.toList[0]\n"
|
|
|
|
|
" if (c1 >= 65 && c1 <= 90) c1 = c1 + 32\n"
|
|
|
|
|
" if (c2 >= 65 && c2 <= 90) c2 = c2 + 32\n"
|
|
|
|
|
" if (c1 != c2) return false\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (tag.count < rest.count) {\n"
|
|
|
|
|
" var next = rest[tag.count]\n"
|
|
|
|
|
" if (next != \" \" && next != \">\" && next != \"/\" && next != \"\\t\" && next != \"\\n\") return false\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return true\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static findCloseTag_(html, start, tag) {\n"
|
|
|
|
|
" var i = start\n"
|
|
|
|
|
" while (i < html.count - tag.count - 2) {\n"
|
|
|
|
|
" if (html[i] == \"<\" && html[i + 1] == \"/\") {\n"
|
|
|
|
|
" var match = true\n"
|
|
|
|
|
" for (j in 0...tag.count) {\n"
|
|
|
|
|
" var c1 = html[i + 2 + j].codePoints.toList[0]\n"
|
|
|
|
|
" var c2 = tag[j].codePoints.toList[0]\n"
|
|
|
|
|
" if (c1 >= 65 && c1 <= 90) c1 = c1 + 32\n"
|
|
|
|
|
" if (c2 >= 65 && c2 <= 90) c2 = c2 + 32\n"
|
|
|
|
|
" if (c1 != c2) {\n"
|
|
|
|
|
" match = false\n"
|
|
|
|
|
" break\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (match) return i\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return -1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processBlockElements_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" result = processHeadingsFromHtml_(result)\n"
|
|
|
|
|
" result = processCodeBlocksFromHtml_(result)\n"
|
|
|
|
|
" result = processBlockquotesFromHtml_(result)\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" result = processTablesFromHtml_(result)\n"
|
feat: add merge_all_wren utility, strutil demo, and 7 new API manual pages
Add WrenFileReader class in apps/merge_all_wren.wren for recursive .wren file discovery and content printing. Introduce example/strutil_demo.wren demonstrating case conversion, hex encoding, SHA256 hashing, string repetition, padding, HTML/JSON escaping, and URL encoding/decoding. Create manual/api pages for argparse, dataset, html, markdown, uuid, wdantic, and web modules. Update manual/api/index.html sidebar and module count from 21 to 28, adding links and cards for the new modules.
2026-01-25 02:47:47 +01:00
|
|
|
" result = processListsFromHtml_(result)\n"
|
|
|
|
|
" result = processHrFromHtml_(result)\n"
|
|
|
|
|
" result = processParagraphsFromHtml_(result)\n"
|
|
|
|
|
" result = processBrFromHtml_(result)\n"
|
|
|
|
|
" result = stripContainerTags_(result)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
2026-01-26 10:21:03 +01:00
|
|
|
" static processTablesFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" while (true) {\n"
|
|
|
|
|
" var start = findTagStart_(result, \"table\")\n"
|
|
|
|
|
" if (start < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var openEnd = start\n"
|
|
|
|
|
" while (openEnd < result.count && result[openEnd] != \">\") {\n"
|
|
|
|
|
" openEnd = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (openEnd >= result.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(result, openEnd + 1, \"table\")\n"
|
|
|
|
|
" if (closeStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var tableContent = result[openEnd + 1...closeStart]\n"
|
|
|
|
|
" var mdTable = convertTableToMarkdown_(tableContent)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < result.count && result[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var after = result[closeEnd + 1..-1]\n"
|
|
|
|
|
" result = before + \"\\n\" + mdTable + \"\\n\" + after\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static convertTableToMarkdown_(tableHtml) {\n"
|
|
|
|
|
" var headers = []\n"
|
|
|
|
|
" var rows = []\n"
|
|
|
|
|
" var alignments = []\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var theadStart = findTagStart_(tableHtml, \"thead\")\n"
|
|
|
|
|
" if (theadStart >= 0) {\n"
|
|
|
|
|
" var theadOpenEnd = theadStart\n"
|
|
|
|
|
" while (theadOpenEnd < tableHtml.count && tableHtml[theadOpenEnd] != \">\") {\n"
|
|
|
|
|
" theadOpenEnd = theadOpenEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" var theadCloseStart = findCloseTag_(tableHtml, theadOpenEnd + 1, \"thead\")\n"
|
|
|
|
|
" if (theadCloseStart >= 0) {\n"
|
|
|
|
|
" var theadContent = tableHtml[theadOpenEnd + 1...theadCloseStart]\n"
|
|
|
|
|
" headers = extractTableCells_(theadContent, \"th\")\n"
|
|
|
|
|
" alignments = extractAlignments_(theadContent, \"th\")\n"
|
|
|
|
|
" if (headers.count == 0) {\n"
|
|
|
|
|
" headers = extractTableCells_(theadContent, \"td\")\n"
|
|
|
|
|
" alignments = extractAlignments_(theadContent, \"td\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var tbodyStart = findTagStart_(tableHtml, \"tbody\")\n"
|
|
|
|
|
" if (tbodyStart >= 0) {\n"
|
|
|
|
|
" var tbodyOpenEnd = tbodyStart\n"
|
|
|
|
|
" while (tbodyOpenEnd < tableHtml.count && tableHtml[tbodyOpenEnd] != \">\") {\n"
|
|
|
|
|
" tbodyOpenEnd = tbodyOpenEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" var tbodyCloseStart = findCloseTag_(tableHtml, tbodyOpenEnd + 1, \"tbody\")\n"
|
|
|
|
|
" if (tbodyCloseStart >= 0) {\n"
|
|
|
|
|
" var tbodyContent = tableHtml[tbodyOpenEnd + 1...tbodyCloseStart]\n"
|
|
|
|
|
" rows = extractTableRows_(tbodyContent)\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (headers.count == 0 && rows.count > 0) {\n"
|
|
|
|
|
" headers = rows[0]\n"
|
|
|
|
|
" rows = rows.count > 1 ? rows[1..-1] : []\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (headers.count == 0) return \"\"\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var mdLines = []\n"
|
|
|
|
|
" mdLines.add(\"| \" + headers.join(\" | \") + \" |\")\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var sep = []\n"
|
|
|
|
|
" for (i in 0...headers.count) {\n"
|
|
|
|
|
" var align = i < alignments.count ? alignments[i] : \"left\"\n"
|
|
|
|
|
" if (align == \"center\") {\n"
|
|
|
|
|
" sep.add(\":---:\")\n"
|
|
|
|
|
" } else if (align == \"right\") {\n"
|
|
|
|
|
" sep.add(\"---:\")\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" sep.add(\"---\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" mdLines.add(\"| \" + sep.join(\" | \") + \" |\")\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" for (row in rows) {\n"
|
|
|
|
|
" mdLines.add(\"| \" + row.join(\" | \") + \" |\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return mdLines.join(\"\\n\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static extractTableCells_(html, cellTag) {\n"
|
|
|
|
|
" var cells = []\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
" while (i < html.count) {\n"
|
|
|
|
|
" var cellStart = findTagStartFrom_(html, i, cellTag)\n"
|
|
|
|
|
" if (cellStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var openEnd = cellStart\n"
|
|
|
|
|
" while (openEnd < html.count && html[openEnd] != \">\") {\n"
|
|
|
|
|
" openEnd = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (openEnd >= html.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(html, openEnd + 1, cellTag)\n"
|
|
|
|
|
" if (closeStart >= 0) {\n"
|
|
|
|
|
" var content = html[openEnd + 1...closeStart]\n"
|
|
|
|
|
" cells.add(stripAllTags_(content).trim())\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < html.count && html[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" i = closeEnd + 1\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" i = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return cells\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static extractAlignments_(html, cellTag) {\n"
|
|
|
|
|
" var alignments = []\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
" while (i < html.count) {\n"
|
|
|
|
|
" var cellStart = findTagStartFrom_(html, i, cellTag)\n"
|
|
|
|
|
" if (cellStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var openEnd = cellStart\n"
|
|
|
|
|
" while (openEnd < html.count && html[openEnd] != \">\") {\n"
|
|
|
|
|
" openEnd = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (openEnd >= html.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var tagContent = html[cellStart...openEnd + 1]\n"
|
|
|
|
|
" var align = \"left\"\n"
|
|
|
|
|
" if (tagContent.contains(\"text-align:center\") || tagContent.contains(\"text-align: center\")) {\n"
|
|
|
|
|
" align = \"center\"\n"
|
|
|
|
|
" } else if (tagContent.contains(\"text-align:right\") || tagContent.contains(\"text-align: right\")) {\n"
|
|
|
|
|
" align = \"right\"\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" alignments.add(align)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(html, openEnd + 1, cellTag)\n"
|
|
|
|
|
" if (closeStart >= 0) {\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < html.count && html[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" i = closeEnd + 1\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" i = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return alignments\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static extractTableRows_(html) {\n"
|
|
|
|
|
" var rows = []\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
" while (i < html.count) {\n"
|
|
|
|
|
" var trStart = findTagStartFrom_(html, i, \"tr\")\n"
|
|
|
|
|
" if (trStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var openEnd = trStart\n"
|
|
|
|
|
" while (openEnd < html.count && html[openEnd] != \">\") {\n"
|
|
|
|
|
" openEnd = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (openEnd >= html.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(html, openEnd + 1, \"tr\")\n"
|
|
|
|
|
" if (closeStart >= 0) {\n"
|
|
|
|
|
" var rowContent = html[openEnd + 1...closeStart]\n"
|
|
|
|
|
" var cells = extractTableCells_(rowContent, \"td\")\n"
|
|
|
|
|
" if (cells.count == 0) cells = extractTableCells_(rowContent, \"th\")\n"
|
|
|
|
|
" if (cells.count > 0) rows.add(cells)\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < html.count && html[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" i = closeEnd + 1\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" i = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return rows\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
feat: add merge_all_wren utility, strutil demo, and 7 new API manual pages
Add WrenFileReader class in apps/merge_all_wren.wren for recursive .wren file discovery and content printing. Introduce example/strutil_demo.wren demonstrating case conversion, hex encoding, SHA256 hashing, string repetition, padding, HTML/JSON escaping, and URL encoding/decoding. Create manual/api pages for argparse, dataset, html, markdown, uuid, wdantic, and web modules. Update manual/api/index.html sidebar and module count from 21 to 28, adding links and cards for the new modules.
2026-01-25 02:47:47 +01:00
|
|
|
" static processHeadingsFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" for (level in 1..6) {\n"
|
|
|
|
|
" var prefix = \"\"\n"
|
|
|
|
|
" for (i in 0...level) prefix = prefix + \"#\"\n"
|
|
|
|
|
" result = replaceTag_(result, \"h\" + level.toString, prefix + \" \", \"\\n\\n\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processCodeBlocksFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" while (true) {\n"
|
|
|
|
|
" var preStart = findTagStart_(result, \"pre\")\n"
|
|
|
|
|
" if (preStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var preOpenEnd = preStart\n"
|
|
|
|
|
" while (preOpenEnd < result.count && result[preOpenEnd] != \">\") {\n"
|
|
|
|
|
" preOpenEnd = preOpenEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (preOpenEnd >= result.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var preCloseStart = findCloseTag_(result, preOpenEnd + 1, \"pre\")\n"
|
|
|
|
|
" if (preCloseStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var content = result[preOpenEnd + 1...preCloseStart]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var codeStart = findTagStart_(content, \"code\")\n"
|
|
|
|
|
" if (codeStart >= 0) {\n"
|
|
|
|
|
" var codeOpenEnd = codeStart\n"
|
|
|
|
|
" while (codeOpenEnd < content.count && content[codeOpenEnd] != \">\") {\n"
|
|
|
|
|
" codeOpenEnd = codeOpenEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" var codeCloseStart = findCloseTag_(content, codeOpenEnd + 1, \"code\")\n"
|
|
|
|
|
" if (codeCloseStart >= 0) {\n"
|
|
|
|
|
" content = content[codeOpenEnd + 1...codeCloseStart]\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var preCloseEnd = preCloseStart\n"
|
|
|
|
|
" while (preCloseEnd < result.count && result[preCloseEnd] != \">\") {\n"
|
|
|
|
|
" preCloseEnd = preCloseEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var before = result[0...preStart]\n"
|
|
|
|
|
" var after = result[preCloseEnd + 1..-1]\n"
|
|
|
|
|
" result = before + \"\\n```\\n\" + content.trim() + \"\\n```\\n\" + after\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processBlockquotesFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" while (true) {\n"
|
|
|
|
|
" var start = findTagStart_(result, \"blockquote\")\n"
|
|
|
|
|
" if (start < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var openEnd = start\n"
|
|
|
|
|
" while (openEnd < result.count && result[openEnd] != \">\") {\n"
|
|
|
|
|
" openEnd = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (openEnd >= result.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(result, openEnd + 1, \"blockquote\")\n"
|
|
|
|
|
" if (closeStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var content = result[openEnd + 1...closeStart].trim()\n"
|
|
|
|
|
" var lines = content.split(\"\\n\")\n"
|
|
|
|
|
" var quoted = []\n"
|
|
|
|
|
" for (line in lines) {\n"
|
|
|
|
|
" var trimmed = line.trim()\n"
|
|
|
|
|
" if (trimmed.count > 0) {\n"
|
|
|
|
|
" quoted.add(\"> \" + trimmed)\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < result.count && result[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var after = result[closeEnd + 1..-1]\n"
|
|
|
|
|
" result = before + \"\\n\" + quoted.join(\"\\n\") + \"\\n\" + after\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processListsFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" result = processListType_(result, \"ul\", \"-\")\n"
|
|
|
|
|
" result = processListType_(result, \"ol\", \"1.\")\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processListType_(html, tag, marker) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" while (true) {\n"
|
|
|
|
|
" var start = findTagStart_(result, tag)\n"
|
|
|
|
|
" if (start < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var openEnd = start\n"
|
|
|
|
|
" while (openEnd < result.count && result[openEnd] != \">\") {\n"
|
|
|
|
|
" openEnd = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (openEnd >= result.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(result, openEnd + 1, tag)\n"
|
|
|
|
|
" if (closeStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var content = result[openEnd + 1...closeStart]\n"
|
|
|
|
|
" var items = extractListItems_(content)\n"
|
|
|
|
|
" var mdItems = []\n"
|
|
|
|
|
" var num = 1\n"
|
|
|
|
|
" for (item in items) {\n"
|
|
|
|
|
" if (tag == \"ol\") {\n"
|
|
|
|
|
" mdItems.add(num.toString + \". \" + item.trim())\n"
|
|
|
|
|
" num = num + 1\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" mdItems.add(marker + \" \" + item.trim())\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < result.count && result[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var after = result[closeEnd + 1..-1]\n"
|
|
|
|
|
" result = before + \"\\n\" + mdItems.join(\"\\n\") + \"\\n\" + after\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static extractListItems_(html) {\n"
|
|
|
|
|
" var items = []\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
" while (i < html.count) {\n"
|
|
|
|
|
" var liStart = findTagStartFrom_(html, i, \"li\")\n"
|
|
|
|
|
" if (liStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var openEnd = liStart\n"
|
|
|
|
|
" while (openEnd < html.count && html[openEnd] != \">\") {\n"
|
|
|
|
|
" openEnd = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (openEnd >= html.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(html, openEnd + 1, \"li\")\n"
|
|
|
|
|
" var content = \"\"\n"
|
|
|
|
|
" if (closeStart >= 0) {\n"
|
|
|
|
|
" content = html[openEnd + 1...closeStart]\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < html.count && html[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" i = closeEnd + 1\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" var nextLi = findTagStartFrom_(html, openEnd + 1, \"li\")\n"
|
|
|
|
|
" if (nextLi >= 0) {\n"
|
|
|
|
|
" content = html[openEnd + 1...nextLi]\n"
|
|
|
|
|
" i = nextLi\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" content = html[openEnd + 1..-1]\n"
|
|
|
|
|
" i = html.count\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" items.add(stripAllTags_(content).trim())\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return items\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static findTagStartFrom_(html, start, tag) {\n"
|
|
|
|
|
" var i = start\n"
|
|
|
|
|
" while (i < html.count) {\n"
|
|
|
|
|
" if (matchTagName_(html, i, tag)) return i\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return -1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processHrFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
" while (i < result.count) {\n"
|
|
|
|
|
" if (matchTagName_(result, i, \"hr\")) {\n"
|
|
|
|
|
" var end = i\n"
|
|
|
|
|
" while (end < result.count && result[end] != \">\") {\n"
|
|
|
|
|
" end = end + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" result = result[0...i] + \"\\n---\\n\" + result[end + 1..-1]\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processParagraphsFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" result = replaceTag_(result, \"p\", \"\", \"\\n\\n\")\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processBrFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
" while (i < result.count) {\n"
|
|
|
|
|
" if (matchTagName_(result, i, \"br\")) {\n"
|
|
|
|
|
" var end = i\n"
|
|
|
|
|
" while (end < result.count && result[end] != \">\") {\n"
|
|
|
|
|
" end = end + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" result = result[0...i] + \"\\n\" + result[end + 1..-1]\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static stripContainerTags_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" var tags = [\"div\", \"span\", \"section\", \"article\", \"main\", \"header\", \"footer\", \"nav\", \"html\", \"body\"]\n"
|
|
|
|
|
" for (tag in tags) {\n"
|
|
|
|
|
" result = replaceTag_(result, tag, \"\", \"\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processInlineFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" result = processStrongFromHtml_(result)\n"
|
|
|
|
|
" result = processEmFromHtml_(result)\n"
|
|
|
|
|
" result = processCodeFromHtml_(result)\n"
|
|
|
|
|
" result = processDelFromHtml_(result)\n"
|
|
|
|
|
" result = processLinksFromHtml_(result)\n"
|
|
|
|
|
" result = processImagesFromHtml_(result)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processStrongFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" result = replaceTag_(result, \"strong\", \"**\", \"**\")\n"
|
|
|
|
|
" result = replaceTag_(result, \"b\", \"**\", \"**\")\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processEmFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" result = replaceTag_(result, \"em\", \"*\", \"*\")\n"
|
|
|
|
|
" result = replaceTag_(result, \"i\", \"*\", \"*\")\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processCodeFromHtml_(html) {\n"
|
|
|
|
|
" return replaceTag_(html, \"code\", \"`\", \"`\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processDelFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" result = replaceTag_(result, \"del\", \"~~\", \"~~\")\n"
|
|
|
|
|
" result = replaceTag_(result, \"s\", \"~~\", \"~~\")\n"
|
|
|
|
|
" result = replaceTag_(result, \"strike\", \"~~\", \"~~\")\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processLinksFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" while (true) {\n"
|
|
|
|
|
" var start = findTagStart_(result, \"a\")\n"
|
|
|
|
|
" if (start < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var openEnd = start\n"
|
|
|
|
|
" while (openEnd < result.count && result[openEnd] != \">\") {\n"
|
|
|
|
|
" openEnd = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (openEnd >= result.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var tagContent = result[start...openEnd + 1]\n"
|
|
|
|
|
" var href = extractAttr_(tagContent, \"href\")\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(result, openEnd + 1, \"a\")\n"
|
|
|
|
|
" if (closeStart < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var linkText = result[openEnd + 1...closeStart]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < result.count && result[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var after = result[closeEnd + 1..-1]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (href != null && href.count > 0) {\n"
|
|
|
|
|
" result = before + \"[\" + stripAllTags_(linkText) + \"](\" + href + \")\" + after\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" result = before + stripAllTags_(linkText) + after\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static processImagesFromHtml_(html) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
" var i = 0\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" while (i < result.count) {\n"
|
|
|
|
|
" if (matchTagName_(result, i, \"img\")) {\n"
|
|
|
|
|
" var end = i\n"
|
|
|
|
|
" while (end < result.count && result[end] != \">\") {\n"
|
|
|
|
|
" end = end + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var tagContent = result[i...end + 1]\n"
|
|
|
|
|
" var src = extractAttr_(tagContent, \"src\")\n"
|
|
|
|
|
" var alt = extractAttr_(tagContent, \"alt\")\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (src == null) src = \"\"\n"
|
|
|
|
|
" if (alt == null) alt = \"\"\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var mdImg = \"\"\n"
|
|
|
|
|
" result = result[0...i] + mdImg + result[end + 1..-1]\n"
|
|
|
|
|
" i = i + mdImg.count\n"
|
|
|
|
|
" } else {\n"
|
|
|
|
|
" i = i + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static extractAttr_(tag, name) {\n"
|
|
|
|
|
" var search = name + \"=\\\"\"\n"
|
|
|
|
|
" var start = tag.indexOf(search)\n"
|
|
|
|
|
" if (start < 0) {\n"
|
|
|
|
|
" search = name + \"='\"\n"
|
|
|
|
|
" start = tag.indexOf(search)\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (start < 0) return null\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var valueStart = start + search.count\n"
|
|
|
|
|
" var quote = search[-1]\n"
|
|
|
|
|
" var valueEnd = valueStart\n"
|
|
|
|
|
" while (valueEnd < tag.count && tag[valueEnd] != quote) {\n"
|
|
|
|
|
" valueEnd = valueEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return tag[valueStart...valueEnd]\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static replaceTag_(html, tag, prefix, suffix) {\n"
|
|
|
|
|
" var result = html\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" while (true) {\n"
|
|
|
|
|
" var start = findTagStart_(result, tag)\n"
|
|
|
|
|
" if (start < 0) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var openEnd = start\n"
|
|
|
|
|
" while (openEnd < result.count && result[openEnd] != \">\") {\n"
|
|
|
|
|
" openEnd = openEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" if (openEnd >= result.count) break\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" if (result[openEnd - 1] == \"/\") {\n"
|
|
|
|
|
" result = result[0...start] + result[openEnd + 1..-1]\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeStart = findCloseTag_(result, openEnd + 1, tag)\n"
|
|
|
|
|
" if (closeStart < 0) {\n"
|
|
|
|
|
" result = result[0...start] + result[openEnd + 1..-1]\n"
|
|
|
|
|
" continue\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var content = result[openEnd + 1...closeStart]\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var closeEnd = closeStart\n"
|
|
|
|
|
" while (closeEnd < result.count && result[closeEnd] != \">\") {\n"
|
|
|
|
|
" closeEnd = closeEnd + 1\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var before = result[0...start]\n"
|
|
|
|
|
" var after = result[closeEnd + 1..-1]\n"
|
|
|
|
|
" result = before + prefix + content + suffix + after\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static findTagStart_(html, tag) {\n"
|
|
|
|
|
" return findTagStartFrom_(html, 0, tag)\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static stripAllTags_(html) {\n"
|
|
|
|
|
" var result = \"\"\n"
|
|
|
|
|
" var inTag = false\n"
|
|
|
|
|
" for (c in html) {\n"
|
|
|
|
|
" if (c == \"<\") {\n"
|
|
|
|
|
" inTag = true\n"
|
|
|
|
|
" } else if (c == \">\") {\n"
|
|
|
|
|
" inTag = false\n"
|
|
|
|
|
" } else if (!inTag) {\n"
|
|
|
|
|
" result = result + c\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
" return result\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" static cleanupWhitespace_(text) {\n"
|
|
|
|
|
" var result = text\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" while (result.contains(\"\\n\\n\\n\")) {\n"
|
|
|
|
|
" result = result.replace(\"\\n\\n\\n\", \"\\n\\n\")\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" var lines = result.split(\"\\n\")\n"
|
|
|
|
|
" var cleaned = []\n"
|
|
|
|
|
" for (line in lines) {\n"
|
|
|
|
|
" cleaned.add(line.trim())\n"
|
|
|
|
|
" }\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" return cleaned.join(\"\\n\")\n"
|
|
|
|
|
" }\n"
|
feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules
Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
2026-01-24 23:40:22 +01:00
|
|
|
"}\n";
|