Arguments
This commit is contained in:
@@ -3,9 +3,6 @@ all: build
|
|||||||
build:
|
build:
|
||||||
odin build src/ -out:TypoML
|
odin build src/ -out:TypoML
|
||||||
|
|
||||||
run:
|
|
||||||
odin run src/
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f TypoML
|
rm -f TypoML
|
||||||
|
|
||||||
|
|||||||
+25
@@ -18,6 +18,31 @@ TypoML reads from stdin and outputs HTML to stdout:
|
|||||||
cat input.tlm | ./TypoML > output.html
|
cat input.tlm | ./TypoML > output.html
|
||||||
```
|
```
|
||||||
|
|
||||||
|
It can also read one or more (added in the order of command line arguments) `.tlm` files:
|
||||||
|
|
||||||
|
```
|
||||||
|
./TypoML input.tlm > output.html
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `./TypoML --help` for the full list of options.
|
||||||
|
|
||||||
|
!! Options
|
||||||
|
|
||||||
|
- `--title <text>` - Set the HTML document `<title>` (default: `TypoML`)
|
||||||
|
- `--plain` - Don't wrap the output in `<html>`, `<head>`, `<body>` and `<style>` tags
|
||||||
|
- `--no-js` - Don't include the JavaScript variable proxy
|
||||||
|
- `--no-wrapper` - Shortcut for `--plain` and `--no-js` at once
|
||||||
|
- `--print-tree` - Print the token tree instead of HTML
|
||||||
|
- `-h`, `--help` - Show the help text and exit
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```
|
||||||
|
./TypoML doc.tlm --title "TITLE" > doc.html
|
||||||
|
./TypoML doc.tlm --no-wrapper > fragment.html
|
||||||
|
./TypoML doc.tlm --print-tree
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
!! Syntax
|
!! Syntax
|
||||||
|
|||||||
@@ -1,39 +1,3 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
input=$(cat -)
|
cat - > preview.html
|
||||||
input="${input#odin run src/}"
|
|
||||||
style="<style>$(cat styles.css)</style>"
|
|
||||||
doctype='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
|
|
||||||
meta='<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
|
|
||||||
start="$doctype<html><head><title>TypoML Preview</title>$meta$style</head><body>"
|
|
||||||
script='
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
var defs = {};
|
|
||||||
var spans = document.querySelectorAll("[data-tlm-def]");
|
|
||||||
for (var i = 0; i < spans.length; i++) {
|
|
||||||
var el = spans[i];
|
|
||||||
defs[el.dataset.tlmDef] = el.dataset.tlmValue;
|
|
||||||
}
|
|
||||||
var tlm = new Proxy({}, {
|
|
||||||
get: function (_, name) {
|
|
||||||
return defs[name];
|
|
||||||
},
|
|
||||||
set: function (_, name, value) {
|
|
||||||
defs[name] = value;
|
|
||||||
var refs = document.querySelectorAll("[data-tlm-var=\"" + name + "\"]");
|
|
||||||
for (var i = 0; i < refs.length; i++) {
|
|
||||||
refs[i].textContent = value;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
ownKeys: function () {
|
|
||||||
return Object.keys(defs);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
window.tlm = tlm;
|
|
||||||
})();
|
|
||||||
</script>'
|
|
||||||
end="$script</body></html>"
|
|
||||||
output="$start$input$end"
|
|
||||||
echo "$output" > preview.html
|
|
||||||
nohup xdg-open preview.html > /dev/null 2>&1 &
|
nohup xdg-open preview.html > /dev/null 2>&1 &
|
||||||
|
|||||||
+79
-5
@@ -7,12 +7,28 @@ import "core:fmt"
|
|||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
read_stdin :: proc() -> []string {
|
read_input :: proc(paths: []string) -> []string {
|
||||||
|
if len(paths) == 0 {
|
||||||
data, err := os.read_entire_file_from_file(os.stdin, context.allocator)
|
data, err := os.read_entire_file_from_file(os.stdin, context.allocator)
|
||||||
content := string(data)
|
content := string(data)
|
||||||
return strings.split_lines(content)
|
return strings.split_lines(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b := strings.builder_make(context.allocator)
|
||||||
|
for path, i in paths {
|
||||||
|
data, err := os.read_entire_file(path, context.allocator)
|
||||||
|
if err != nil {
|
||||||
|
fmt.eprintf("typoml: cannot read file '%s': %v\n", path, err)
|
||||||
|
os.exit(1)
|
||||||
|
}
|
||||||
|
if i > 0 {
|
||||||
|
strings.write_string(&b, "\n")
|
||||||
|
}
|
||||||
|
strings.write_string(&b, string(data))
|
||||||
|
}
|
||||||
|
return strings.split_lines(strings.to_string(b))
|
||||||
|
}
|
||||||
|
|
||||||
print_token :: proc(tok: ^token.Token, depth: int = 0) {
|
print_token :: proc(tok: ^token.Token, depth: int = 0) {
|
||||||
indent := strings.repeat(" ", depth, context.temp_allocator)
|
indent := strings.repeat(" ", depth, context.temp_allocator)
|
||||||
|
|
||||||
@@ -116,8 +132,66 @@ print_token :: proc(tok: ^token.Token, depth: int = 0) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: proc() {
|
HELP_TEXT :: `Usage:
|
||||||
lines := read_stdin()
|
TypoML [options] [file...]
|
||||||
parsed := parser.parse(lines)
|
|
||||||
renderer.print_html(&parsed)
|
If there is no file provided, TypoML reads from stdin.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--title <text> Set the HTML document title (default: "TypoML")
|
||||||
|
--plain Don't wrap the output in <html>, <head>, <body> and <style> tags
|
||||||
|
--no-js Don't include the JavaScript variable proxy (<script>)
|
||||||
|
--no-wrapper Shortcut for --plain and --no-js at once
|
||||||
|
--print-tree Print the token tree instead of HTML
|
||||||
|
-h, --help Show this help and exit
|
||||||
|
`
|
||||||
|
|
||||||
|
parse_args :: proc(args: []string) -> (files: [dynamic]string, flags: renderer.DocumentFlags) {
|
||||||
|
for i := 0; i < len(args); i += 1 {
|
||||||
|
arg := args[i]
|
||||||
|
switch arg {
|
||||||
|
case "-h", "--help":
|
||||||
|
flags.help = true
|
||||||
|
case "--plain":
|
||||||
|
flags.plain = true
|
||||||
|
case "--no-js":
|
||||||
|
flags.no_js = true
|
||||||
|
case "--no-wrapper":
|
||||||
|
flags.plain = true
|
||||||
|
flags.no_js = true
|
||||||
|
case "--title":
|
||||||
|
if i + 1 < len(args) {
|
||||||
|
i += 1
|
||||||
|
flags.title = args[i]
|
||||||
|
}
|
||||||
|
case "--print-tree":
|
||||||
|
flags.print_tree = true
|
||||||
|
case:
|
||||||
|
if strings.has_prefix(arg, "--") {
|
||||||
|
fmt.eprintf("typoml: unknown option '%s'\n", arg)
|
||||||
|
os.exit(1)
|
||||||
|
}
|
||||||
|
append(&files, arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
main :: proc() {
|
||||||
|
files, flags := parse_args(os.args[1:])
|
||||||
|
|
||||||
|
if flags.help {
|
||||||
|
fmt.print(HELP_TEXT)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := read_input(files[:])
|
||||||
|
parsed := parser.parse(lines)
|
||||||
|
|
||||||
|
if flags.print_tree {
|
||||||
|
print_token(&parsed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.print_document(&parsed, flags)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,75 @@ render_media_object :: proc(tok: ^token.Token, mime_type: string) {
|
|||||||
fmt.print("</object>\n")
|
fmt.print("</object>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEMPLATE_PROXY_SCRIPT :: `
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var defs = {};
|
||||||
|
var spans = document.querySelectorAll("[data-tlm-def]");
|
||||||
|
for (var i = 0; i < spans.length; i++) {
|
||||||
|
var el = spans[i];
|
||||||
|
defs[el.dataset.tlmDef] = el.dataset.tlmValue;
|
||||||
|
}
|
||||||
|
var tlm = new Proxy({}, {
|
||||||
|
get: function (_, name) {
|
||||||
|
return defs[name];
|
||||||
|
},
|
||||||
|
set: function (_, name, value) {
|
||||||
|
defs[name] = value;
|
||||||
|
var refs = document.querySelectorAll("[data-tlm-var=\"" + name + "\"]");
|
||||||
|
for (var i = 0; i < refs.length; i++) {
|
||||||
|
refs[i].textContent = value;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
ownKeys: function () {
|
||||||
|
return Object.keys(defs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window.tlm = tlm;
|
||||||
|
})();
|
||||||
|
</script>`
|
||||||
|
|
||||||
|
print_document :: proc(root: ^token.Token, flags: DocumentFlags) {
|
||||||
|
if flags.plain {
|
||||||
|
for child in root.children {
|
||||||
|
print_html(child)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
doctype := "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"
|
||||||
|
meta := "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
|
||||||
|
style := "<style>" + DEFAULT_STYLE + "</style>"
|
||||||
|
title := flags.title
|
||||||
|
if title == "" {
|
||||||
|
title = "TypoML"
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.printf(
|
||||||
|
"%s\n<html><head><title>%s</title>%s%s</head>\n<body>\n",
|
||||||
|
doctype,
|
||||||
|
escape_html(title),
|
||||||
|
meta,
|
||||||
|
style,
|
||||||
|
)
|
||||||
|
for child in root.children {
|
||||||
|
print_html(child)
|
||||||
|
}
|
||||||
|
if !flags.no_js {
|
||||||
|
fmt.print("\n" + TEMPLATE_PROXY_SCRIPT + "\n")
|
||||||
|
}
|
||||||
|
fmt.print("</body></html>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
DocumentFlags :: struct {
|
||||||
|
plain: bool,
|
||||||
|
no_js: bool,
|
||||||
|
title: string,
|
||||||
|
print_tree: bool,
|
||||||
|
help: bool,
|
||||||
|
}
|
||||||
|
|
||||||
print_html :: proc(tok: ^token.Token) {
|
print_html :: proc(tok: ^token.Token) {
|
||||||
switch tok.type {
|
switch tok.type {
|
||||||
case token.TokenType.Root:
|
case token.TokenType.Root:
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
package renderer
|
||||||
|
|
||||||
|
DEFAULT_STYLE :: `
|
||||||
body {
|
body {
|
||||||
font-family: Georgia, "Times New Roman", Times, serif;
|
font-family: Georgia, "Times New Roman", Times, serif;
|
||||||
color: #e0e0e0;
|
color: #e0e0e0;
|
||||||
@@ -72,3 +75,4 @@ hr.footnotes-sep {
|
|||||||
.footnote a {
|
.footnote a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
`
|
||||||
Reference in New Issue
Block a user