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.
This commit is contained in:
Vendored
+328
@@ -0,0 +1,328 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "html" for Html
|
||||
|
||||
class Markdown {
|
||||
static toHtml(text) { toHtml(text, {}) }
|
||||
|
||||
static toHtml(text, options) {
|
||||
var safeMode = options.containsKey("safeMode") ? options["safeMode"] : false
|
||||
var lines = text.split("\n")
|
||||
var result = []
|
||||
var inCodeBlock = false
|
||||
var codeBlockContent = []
|
||||
var inList = false
|
||||
var listType = null
|
||||
var inBlockquote = false
|
||||
|
||||
for (i in 0...lines.count) {
|
||||
var line = lines[i]
|
||||
|
||||
if (line.startsWith("```")) {
|
||||
if (inCodeBlock) {
|
||||
result.add("<pre><code>" + (safeMode ? Html.quote(codeBlockContent.join("\n")) : codeBlockContent.join("\n")) + "</code></pre>")
|
||||
codeBlockContent = []
|
||||
inCodeBlock = false
|
||||
} else {
|
||||
closeList_(result, inList, listType)
|
||||
inList = false
|
||||
inCodeBlock = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (inCodeBlock) {
|
||||
codeBlockContent.add(line)
|
||||
continue
|
||||
}
|
||||
|
||||
if (line.count == 0) {
|
||||
closeList_(result, inList, listType)
|
||||
inList = false
|
||||
if (inBlockquote) {
|
||||
result.add("</blockquote>")
|
||||
inBlockquote = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (line.startsWith("> ")) {
|
||||
closeList_(result, inList, listType)
|
||||
inList = false
|
||||
if (!inBlockquote) {
|
||||
result.add("<blockquote>")
|
||||
inBlockquote = true
|
||||
}
|
||||
result.add("<p>" + processInline_(line[2..-1], safeMode) + "</p>")
|
||||
continue
|
||||
}
|
||||
|
||||
if (line.startsWith("---") || line.startsWith("***") || line.startsWith("___")) {
|
||||
var isHr = true
|
||||
for (c in line) {
|
||||
if (c != "-" && c != "*" && c != "_" && c != " ") {
|
||||
isHr = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (isHr && line.count >= 3) {
|
||||
closeList_(result, inList, listType)
|
||||
inList = false
|
||||
result.add("<hr>")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var heading = parseHeading_(line)
|
||||
if (heading) {
|
||||
closeList_(result, inList, listType)
|
||||
inList = false
|
||||
result.add("<h%(heading["level"])>" + processInline_(heading["text"], safeMode) + "</h%(heading["level"])>")
|
||||
continue
|
||||
}
|
||||
|
||||
var listItem = parseListItem_(line)
|
||||
if (listItem) {
|
||||
var newType = listItem["type"]
|
||||
if (!inList || listType != newType) {
|
||||
closeList_(result, inList, listType)
|
||||
result.add(newType == "ul" ? "<ul>" : "<ol>")
|
||||
inList = true
|
||||
listType = newType
|
||||
}
|
||||
result.add("<li>" + processInline_(listItem["text"], safeMode) + "</li>")
|
||||
continue
|
||||
}
|
||||
|
||||
closeList_(result, inList, listType)
|
||||
inList = false
|
||||
result.add("<p>" + processInline_(line, safeMode) + "</p>")
|
||||
}
|
||||
|
||||
closeList_(result, inList, listType)
|
||||
if (inBlockquote) {
|
||||
result.add("</blockquote>")
|
||||
}
|
||||
if (inCodeBlock) {
|
||||
result.add("<pre><code>" + (safeMode ? Html.quote(codeBlockContent.join("\n")) : codeBlockContent.join("\n")) + "</code></pre>")
|
||||
}
|
||||
|
||||
return result.join("\n")
|
||||
}
|
||||
|
||||
static closeList_(result, inList, listType) {
|
||||
if (inList) {
|
||||
result.add(listType == "ul" ? "</ul>" : "</ol>")
|
||||
}
|
||||
}
|
||||
|
||||
static parseHeading_(line) {
|
||||
var level = 0
|
||||
for (c in line) {
|
||||
if (c == "#") {
|
||||
level = level + 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (level > 0 && level <= 6 && line.count > level && line[level] == " ") {
|
||||
return {"level": level, "text": line[level + 1..-1]}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
static parseListItem_(line) {
|
||||
var trimmed = line
|
||||
var indent = 0
|
||||
while (trimmed.count > 0 && trimmed[0] == " ") {
|
||||
trimmed = trimmed[1..-1]
|
||||
indent = indent + 1
|
||||
}
|
||||
|
||||
if (trimmed.count >= 2 && (trimmed[0] == "-" || trimmed[0] == "*" || trimmed[0] == "+") && trimmed[1] == " ") {
|
||||
return {"type": "ul", "text": trimmed[2..-1]}
|
||||
}
|
||||
|
||||
var i = 0
|
||||
while (i < trimmed.count) {
|
||||
var c = trimmed[i].codePoints.toList[0]
|
||||
if (c < 48 || c > 57) break
|
||||
i = i + 1
|
||||
}
|
||||
if (i > 0 && i < trimmed.count - 1 && trimmed[i] == "." && trimmed[i + 1] == " ") {
|
||||
return {"type": "ol", "text": trimmed[i + 2..-1]}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
static processInline_(text, safeMode) {
|
||||
if (safeMode) text = Html.quote(text)
|
||||
text = processCode_(text)
|
||||
text = processBold_(text)
|
||||
text = processItalic_(text)
|
||||
text = processStrikethrough_(text)
|
||||
text = processImages_(text)
|
||||
text = processLinks_(text)
|
||||
return text
|
||||
}
|
||||
|
||||
static processCode_(text) {
|
||||
var result = ""
|
||||
var i = 0
|
||||
var chars = text.toList
|
||||
while (i < chars.count) {
|
||||
if (chars[i] == "`") {
|
||||
var end = i + 1
|
||||
while (end < chars.count && chars[end] != "`") {
|
||||
end = end + 1
|
||||
}
|
||||
if (end < chars.count) {
|
||||
var code = ""
|
||||
for (j in (i + 1)...end) {
|
||||
code = code + chars[j]
|
||||
}
|
||||
result = result + "<code>" + code + "</code>"
|
||||
i = end + 1
|
||||
} else {
|
||||
result = result + chars[i]
|
||||
i = i + 1
|
||||
}
|
||||
} else {
|
||||
result = result + chars[i]
|
||||
i = i + 1
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static processBold_(text) {
|
||||
var result = text
|
||||
while (result.contains("**")) {
|
||||
var start = result.indexOf("**")
|
||||
var rest = result[start + 2..-1]
|
||||
var end = rest.indexOf("**")
|
||||
if (end >= 0) {
|
||||
var before = result[0...start]
|
||||
var content = rest[0...end]
|
||||
var after = rest[end + 2..-1]
|
||||
result = before + "<strong>" + content + "</strong>" + after
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
while (result.contains("__")) {
|
||||
var start = result.indexOf("__")
|
||||
var rest = result[start + 2..-1]
|
||||
var end = rest.indexOf("__")
|
||||
if (end >= 0) {
|
||||
var before = result[0...start]
|
||||
var content = rest[0...end]
|
||||
var after = rest[end + 2..-1]
|
||||
result = before + "<strong>" + content + "</strong>" + after
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static processItalic_(text) {
|
||||
var result = text
|
||||
while (result.contains("*")) {
|
||||
var start = result.indexOf("*")
|
||||
if (start > 0 && result[start - 1] == "<") {
|
||||
break
|
||||
}
|
||||
var rest = result[start + 1..-1]
|
||||
var end = rest.indexOf("*")
|
||||
if (end >= 0 && end > 0) {
|
||||
var before = result[0...start]
|
||||
var content = rest[0...end]
|
||||
var after = rest[end + 1..-1]
|
||||
result = before + "<em>" + content + "</em>" + after
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static processStrikethrough_(text) {
|
||||
var result = text
|
||||
while (result.contains("~~")) {
|
||||
var start = result.indexOf("~~")
|
||||
var rest = result[start + 2..-1]
|
||||
var end = rest.indexOf("~~")
|
||||
if (end >= 0) {
|
||||
var before = result[0...start]
|
||||
var content = rest[0...end]
|
||||
var after = rest[end + 2..-1]
|
||||
result = before + "<del>" + content + "</del>" + after
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static processLinks_(text) {
|
||||
var result = text
|
||||
while (result.contains("](")) {
|
||||
var linkEnd = result.indexOf("](")
|
||||
var textStart = linkEnd
|
||||
while (textStart > 0 && result[textStart - 1] != "[") {
|
||||
textStart = textStart - 1
|
||||
}
|
||||
if (textStart > 0 && result[textStart - 1] == "[") {
|
||||
var urlStart = linkEnd + 2
|
||||
var urlEnd = urlStart
|
||||
while (urlEnd < result.count && result[urlEnd] != ")") {
|
||||
urlEnd = urlEnd + 1
|
||||
}
|
||||
if (urlEnd < result.count) {
|
||||
var before = result[0...textStart - 1]
|
||||
var linkText = result[textStart...linkEnd]
|
||||
var url = result[urlStart...urlEnd]
|
||||
var after = result[urlEnd + 1..-1]
|
||||
result = before + "<a href=\"" + url + "\">" + linkText + "</a>" + after
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
static processImages_(text) {
|
||||
var result = text
|
||||
while (result.contains("![")) {
|
||||
var start = result.indexOf("![")
|
||||
var altEnd = start + 2
|
||||
while (altEnd < result.count && result[altEnd] != "]") {
|
||||
altEnd = altEnd + 1
|
||||
}
|
||||
if (altEnd < result.count && altEnd + 1 < result.count && result[altEnd + 1] == "(") {
|
||||
var urlStart = altEnd + 2
|
||||
var urlEnd = urlStart
|
||||
while (urlEnd < result.count && result[urlEnd] != ")") {
|
||||
urlEnd = urlEnd + 1
|
||||
}
|
||||
if (urlEnd < result.count) {
|
||||
var before = result[0...start]
|
||||
var alt = result[start + 2...altEnd]
|
||||
var url = result[urlStart...urlEnd]
|
||||
var after = result[urlEnd + 1..-1]
|
||||
result = before + "<img src=\"" + url + "\" alt=\"" + alt + "\">" + after
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user