diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 01072ca..0000000 --- a/.editorconfig +++ /dev/null @@ -1,8 +0,0 @@ -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true - -[*.v] -indent_style = tab diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 9a98968..0000000 --- a/.gitattributes +++ /dev/null @@ -1,8 +0,0 @@ -* text=auto eol=lf -*.bat eol=crlf - -*.v linguist-language=V -*.vv linguist-language=V -*.vsh linguist-language=V -v.mod linguist-language=V -.vdocignore linguist-language=ignore diff --git a/.gitignore b/.gitignore index abb6030..22b8c39 100644 --- a/.gitignore +++ b/.gitignore @@ -1,27 +1,2 @@ -# Binaries for programs and plugins -main TypoML -*.exe -*.exe~ -*.so -*.dylib -*.dll - -# Ignore binary output folders -bin/ - -# Ignore common editor/system specific metadata -.DS_Store -.idea/ -.vscode/ -*.iml - -# ENV -.env - -# Web assets and local databases -*.db -*.js - -# Ignore installed modules through `v install --local`: -modules/ +src.bin diff --git a/Makefile b/Makefile index fb1266a..df29639 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ all: build build: - v src/ + odin build src/ -out:TypoML run: - v run src/ + odin run src/ clean: rm -f TypoML format: - v fmt -w src/ + odinfmt -w src/ diff --git a/preview b/preview index eff50f0..758a11d 100755 --- a/preview +++ b/preview @@ -1,10 +1,9 @@ #!/bin/sh input=$(cat -) -input="${input#v run src/}" +input="${input#odin run src/}" style="" start="TypoML Preview$style" end="" output="$start$input$end" echo "$output" > /tmp/preview.html xdg-open /tmp/preview.html - diff --git a/src/embed.odin b/src/embed.odin new file mode 100644 index 0000000..d10c6bd --- /dev/null +++ b/src/embed.odin @@ -0,0 +1,374 @@ +package main + +import "core:strings" + +get_ext :: proc(url: string) -> string { + clean := url + if question := strings.index_byte(clean, '?'); question != -1 { + clean = clean[:question] + } + if hash := strings.index_byte(clean, '#'); hash != -1 { + clean = clean[:hash] + } + if dot := strings.last_index_byte(clean, '.'); dot != -1 { + return strings.to_lower(clean[dot:], context.temp_allocator) + } + return "" +} + +detect_type :: proc(url: string) -> string { + ext := get_ext(url) + switch ext { + case ".jpg", + ".jpeg", + ".jpe", + ".jfif", + ".jif", + ".pjpeg", + ".pjp", + ".png", + ".apng", + ".gif", + ".webp", + ".avif", + ".heic", + ".heif", + ".hif", + ".bmp", + ".dib", + ".tif", + ".tiff", + ".ico", + ".cur", + ".svg", + ".svgz", + ".raw", + ".cr2", + ".cr3", + ".nef", + ".nrw", + ".orf", + ".sr2", + ".arw", + ".srf", + ".rw2", + ".pef", + ".raf", + ".dng", + ".3fr", + ".ari", + ".bay", + ".cap", + ".dcr", + ".erf", + ".fff", + ".iiq", + ".k25", + ".kdc", + ".mdc", + ".mos", + ".mrw", + ".obm", + ".ptx", + ".pxn", + ".r3d", + ".rwl", + ".rwz", + ".srw", + ".x3f", + ".gpr", + ".pgm", + ".ppm", + ".pbm", + ".pnm", + ".pam", + ".pfm", + ".tga", + ".icb", + ".vda", + ".vst", + ".pcx", + ".xbm", + ".xpm", + ".xwd", + ".sgi", + ".rgb", + ".rgba", + ".bw", + ".jp2", + ".j2k", + ".j2c", + ".jpf", + ".jpx", + ".jpm", + ".mj2", + ".wbmp", + ".emf", + ".wmf", + ".eps", + ".epsi", + ".epsf", + ".psd", + ".psb", + ".ai", + ".cdr", + ".xcf", + ".gbr", + ".gih", + ".pat", + ".art", + ".jxl", + ".jxr", + ".wdp", + ".hdp", + ".exr", + ".hdr", + ".dpx", + ".cin", + ".fits", + ".fit", + ".fts", + ".icns", + ".flif", + ".dds", + ".ktx", + ".ktx2", + ".astc", + ".kodak", + ".fpx", + ".pcd", + ".cmx", + ".drw", + ".cgm", + ".plt", + ".hpgl", + ".iff", + ".ilbm", + ".lbm", + ".mac", + ".msp", + ".pct", + ".pic", + ".pict", + ".pntg", + ".qtif", + ".qti", + ".ras", + ".sun", + ".tpic", + ".wpg", + ".g3", + ".g4", + ".dcm", + ".dicom", + ".ora", + ".kra", + ".clip": + return "image" + case ".mp3", + ".mp2", + ".mp1", + ".mpa", + ".mpga", + ".ogg", + ".oga", + ".opus", + ".spx", + ".wav", + ".wave", + ".flac", + ".aac", + ".adts", + ".wma", + ".m4a", + ".m4b", + ".m4p", + ".m4r", + ".aif", + ".aiff", + ".aifc", + ".au", + ".snd", + ".mid", + ".midi", + ".rmi", + ".kar", + ".ra", + ".ram", + ".mka", + ".ape", + ".wv", + ".ac3", + ".ec3", + ".eac3", + ".dts", + ".dtshd", + ".amr", + ".awb", + ".caf", + ".gsm", + ".mpc", + ".shn", + ".tta", + ".voc", + ".vox", + ".8svx", + ".mod", + ".s3m", + ".xm", + ".it", + ".stm", + ".med", + ".mtm", + ".umx", + ".669", + ".far", + ".amf", + ".dsm", + ".gdm", + ".imf", + ".okt", + ".sfx", + ".ult", + ".uni", + ".psm", + ".j2b", + ".dbm", + ".digi", + ".dtm", + ".plm", + ".nsf", + ".nsfe", + ".spc", + ".gym", + ".vgm", + ".vgz", + ".gbs", + ".hes", + ".ay", + ".sid", + ".oma", + ".aa3", + ".at3", + ".at9", + ".qcp", + ".tak", + ".ofr", + ".ofs", + ".sox", + ".weba", + ".dss", + ".alac", + ".vqf", + ".vql", + ".mxmf", + ".ota", + ".imy", + ".rtttl", + ".rtx", + ".xmf", + ".w64", + ".rf64", + ".bwf", + ".cda", + ".aup": + return "audio" + case ".mp4", + ".m4v", + ".mp4v", + ".webm", + ".mov", + ".qt", + ".avi", + ".mkv", + ".flv", + ".f4v", + ".f4p", + ".f4a", + ".f4b", + ".wmv", + ".mpg", + ".mpeg", + ".mpe", + ".m1v", + ".m2v", + ".mpv", + ".mp2v", + ".mpv2", + ".ogv", + ".ogx", + ".3gp", + ".3g2", + ".3gpp", + ".3gpp2", + ".asf", + ".asx", + ".vob", + ".ts", + ".mts", + ".m2ts", + ".tsv", + ".tsa", + ".divx", + ".xvid", + ".rm", + ".rmvb", + ".swf", + ".dv", + ".dif", + ".gifv", + ".roq", + ".nsv", + ".svi", + ".annodex", + ".axv", + ".amv", + ".bik", + ".bk2", + ".smk", + ".ivf", + ".mxf", + ".nut", + ".ogm", + ".fli", + ".flc", + ".y4m", + ".264", + ".h264", + ".265", + ".h265", + ".hevc", + ".av1", + ".vc1", + ".vp8", + ".vp9", + ".wtv", + ".yuv", + ".str", + ".pva", + ".trp", + ".rec", + ".vid", + ".rv", + ".cpk", + ".film": + return "video" + case: + return "iframe" + } +} + +parse_type_hint :: proc(type_hint: string) -> string { + switch type_hint { + case "i", "image", "img": + return "image" + case "a", "audio": + return "audio" + case "v", "video": + return "video" + case "f", "iframe", "frame": + return "iframe" + case: + return "" + } +} diff --git a/src/embed.v b/src/embed.v deleted file mode 100644 index 5be260c..0000000 --- a/src/embed.v +++ /dev/null @@ -1,74 +0,0 @@ -fn get_ext(url string) string { - mut clean := url - if question := clean.index('?') { - clean = clean[..question] - } - if hash := clean.index('#') { - clean = clean[..hash] - } - if dot := clean.last_index('.') { - return clean[dot..].to_lower() - } - return '' -} - -fn detect_type(url string) string { - ext := get_ext(url) - return match ext { - '.jpg', '.jpeg', '.jpe', '.jfif', '.jif', '.pjpeg', '.pjp', '.png', '.apng', '.gif', - '.webp', '.avif', '.heic', '.heif', '.hif', '.bmp', '.dib', '.tif', '.tiff', '.ico', - '.cur', '.svg', '.svgz', '.raw', '.cr2', '.cr3', '.nef', '.nrw', '.orf', '.sr2', '.arw', - '.srf', '.rw2', '.pef', '.raf', '.dng', '.3fr', '.ari', '.bay', '.cap', '.dcr', '.erf', - '.fff', '.iiq', '.k25', '.kdc', '.mdc', '.mos', '.mrw', '.obm', '.ptx', '.pxn', '.r3d', - '.rwl', '.rwz', '.srw', '.x3f', '.gpr', '.pgm', '.ppm', '.pbm', '.pnm', '.pam', '.pfm', - '.tga', '.icb', '.vda', '.vst', '.pcx', '.xbm', '.xpm', '.xwd', '.sgi', '.rgb', '.rgba', - '.bw', '.jp2', '.j2k', '.j2c', '.jpf', '.jpx', '.jpm', '.mj2', '.wbmp', '.emf', '.wmf', - '.eps', '.epsi', '.epsf', '.psd', '.psb', '.ai', '.cdr', '.xcf', '.gbr', '.gih', '.pat', - '.art', '.jxl', '.jxr', '.wdp', '.hdp', '.exr', '.hdr', '.dpx', '.cin', '.fits', '.fit', - '.fts', '.icns', '.flif', '.dds', '.ktx', '.ktx2', '.astc', '.kodak', '.fpx', '.pcd', - '.cmx', '.drw', '.cgm', '.plt', '.hpgl', '.iff', '.ilbm', '.lbm', '.mac', '.msp', '.pct', - '.pic', '.pict', '.pntg', '.qtif', '.qti', '.ras', '.sun', '.tpic', '.wpg', '.g3', '.g4', - '.dcm', '.dicom', '.ora', '.kra', '.clip' { - 'image' - } - '.mp3', '.mp2', '.mp1', '.mpa', '.mpga', '.ogg', '.oga', '.opus', '.spx', '.wav', '.wave', - '.flac', '.aac', '.adts', '.wma', '.m4a', '.m4b', '.m4p', '.m4r', '.aif', '.aiff', '.aifc', - '.au', '.snd', '.mid', '.midi', '.rmi', '.kar', '.ra', '.ram', '.mka', '.ape', '.wv', - '.ac3', '.ec3', '.eac3', '.dts', '.dtshd', '.amr', '.awb', '.caf', '.gsm', '.mpc', '.shn', - '.tta', '.voc', '.vox', '.8svx', '.mod', '.s3m', '.xm', '.it', '.stm', '.med', '.mtm', - '.umx', '.669', '.far', '.amf', '.dsm', '.gdm', '.imf', '.okt', '.sfx', '.ult', '.uni', - '.psm', '.j2b', '.dbm', '.digi', '.dtm', '.plm', '.nsf', '.nsfe', '.spc', '.gym', '.vgm', - '.vgz', '.gbs', '.hes', '.ay', '.sid', '.oma', '.aa3', '.at3', '.at9', '.qcp', '.tak', - '.ofr', '.ofs', '.sox', '.weba', '.dss', '.alac', '.vqf', '.vql', '.mxmf', '.ota', '.imy', - '.rtttl', '.rtx', '.xmf', '.w64', '.rf64', '.bwf', '.cda', '.aup' { - 'audio' - } - '.mp4', '.m4v', '.mp4v', '.webm', '.mov', '.qt', '.avi', '.mkv', '.flv', '.f4v', '.f4p', - '.f4a', '.f4b', '.wmv', '.mpg', '.mpeg', '.mpe', '.m1v', '.m2v', '.mpv', '.mp2v', '.mpv2', - '.ogv', '.ogx', '.3gp', '.3g2', '.3gpp', '.3gpp2', '.asf', '.asx', '.vob', '.ts', '.mts', - '.m2ts', '.tsv', '.tsa', '.divx', '.xvid', '.rm', '.rmvb', '.swf', '.dv', '.dif', '.gifv', - '.roq', '.nsv', '.svi', '.annodex', '.axv', '.amv', '.bik', '.bk2', '.smk', '.ivf', '.mxf', - '.nut', '.ogm', '.fli', '.flc', '.y4m', '.264', '.h264', '.265', '.h265', '.hevc', '.av1', - '.vc1', '.vp8', '.vp9', '.wtv', '.yuv', '.str', '.pva', '.trp', '.rec', '.vid', '.rv', - '.cpk', '.film' { - 'video' - } - else { - 'iframe' - } - } -} - -// will look like this: -// $[https://krzak.org/krzak-icon.png|i] -// $(https://krzak.org/krzak-icon.png|image) -// $[Krzak.org icon](https://krzak.org/krzak-icon.png|i) -fn parse_type_hint(type_hint string) string { - return match type_hint { - 'i', 'image', 'img' { 'image' } - 'a', 'audio' { 'audio' } - 'v', 'video' { 'video' } - 'f', 'iframe' { 'iframe' } - else { '' } - } -} diff --git a/src/main.odin b/src/main.odin new file mode 100644 index 0000000..b21bb0c --- /dev/null +++ b/src/main.odin @@ -0,0 +1,58 @@ +package main + +import "core:fmt" +import "core:os" +import "core:strings" + +read_stdin :: proc() -> []string { + data, err := os.read_entire_file_from_file(os.stdin, context.allocator) + content := string(data) + return strings.split_lines(content) +} + +print_token :: proc(token: Token, depth: int = 0) { + indent := strings.repeat(" ", depth, context.temp_allocator) + + type_str := "" + switch token.type { + case TokenType.Root: + type_str = "Root" + case TokenType.Text: + type_str = "Text" + case TokenType.Italics: + type_str = "Italics" + case TokenType.Bold: + type_str = "Bold" + case TokenType.BreakLine: + type_str = "BreakLine" + case TokenType.Heading: + type_str = "Heading" + case TokenType.Paragraph: + type_str = "Paragraph" + } + + value_str := "" + switch v in token.value { + case string: + value_str = v + case int: + value_str = fmt.aprintf("%d", v, allocator = context.temp_allocator) + } + + if value_str != "" { + fmt.printf("%s%s(%s)", indent, type_str, value_str) + } else { + fmt.printf("%s%s", indent, type_str) + } + fmt.println() + + for child in token.children { + print_token(child, depth + 1) + } +} + +main :: proc() { + lines := read_stdin() + parsed := parse(lines) + print_token(parsed) +} diff --git a/src/main.v b/src/main.v deleted file mode 100644 index 421f414..0000000 --- a/src/main.v +++ /dev/null @@ -1,18 +0,0 @@ -import os - -fn read_stdin() []string { - mut lines := []string{} - for { - line := os.get_line() - if line.len == 0 && os.stdin().eof() { - break - } - lines << line - } - return lines -} - -fn main() { - lines := read_stdin() - println(parse(lines)) -} diff --git a/src/parser.odin b/src/parser.odin new file mode 100644 index 0000000..ceac532 --- /dev/null +++ b/src/parser.odin @@ -0,0 +1,90 @@ +package main + +import "core:fmt" +import "core:strings" + +TokenType :: enum { + Text, + Italics, + Bold, + BreakLine, + Heading, + Paragraph, + Root, +} + +TokenValue :: union { + string, + int, +} + +Token :: struct { + type: TokenType, + value: TokenValue, + children: [dynamic]Token, + parent: ^Token, +} + +current_token: ^Token + +replace_text :: proc(text: string, start: int, len_: int, repl: string) -> string { + builder := strings.builder_make(context.temp_allocator) + strings.write_string(&builder, text[:start]) + strings.write_string(&builder, repl) + strings.write_string(&builder, text[start + len_:]) + return strings.to_string(builder) +} + +parse_header :: proc(line: string) -> (int, string) { + if len(line) == 0 { + return 0, line + } + + lvl := 0 + for lvl < len(line) && line[lvl] == '!' { + lvl += 1 + } + if lvl == 0 || lvl >= len(line) || line[lvl] != ' ' { + return 0, line + } + return lvl, line[lvl + 1:] +} + +parse :: proc(lines: []string, allocator := context.allocator) -> Token { + root := Token{TokenType.Root, nil, nil, nil} + current_token := &root + append(¤t_token.children, Token{TokenType.Paragraph, nil, nil, current_token}) + current_token = ¤t_token.children[0] + + for untrimmed_line, line_index in lines { + line := strings.trim_space(untrimmed_line) + + if len(line) == 0 && line_index != len(lines) - 1 { + if current_token.parent != nil { + current_token = current_token.parent + } + + append(¤t_token.children, Token{TokenType.Paragraph, nil, nil, current_token}) + current_token = ¤t_token.children[len(current_token.children) - 1] + continue + } + + append(¤t_token.children, Token{TokenType.Text, line, nil, current_token}) + + // lvl, text := parse_header(trimmed) + // is_header := lvl > 0 + + // if is_header { + // fmt.sbprintf(&builder, "", lvl) + // strings.write_string(&builder, text) + // fmt.sbprintf(&builder, "", lvl) + // } else { + // strings.write_string(&builder, text) + // strings.write_string(&builder, "
") + // } + + // strings.write_string(&builder, "\n") + } + + return root +} diff --git a/src/parser.v b/src/parser.v deleted file mode 100644 index 17370be..0000000 --- a/src/parser.v +++ /dev/null @@ -1,47 +0,0 @@ -fn replace(text string, start int, len int, repl string) string { - return text[..start] + repl + text[start + len..] -} - -fn parse_header(line string) (int, string) { - if line.len == 0 { - return 0, line - } - - mut lvl := 0 - for lvl < line.len && line[lvl] == '!'.bytes()[0] { - lvl++ - } - if lvl == 0 || lvl >= line.len || line[lvl] != ' '.bytes()[0] { - return 0, line - } - return lvl, line[lvl + 1..] -} - -fn parse(lines []string) string { - mut output := '

' - for line in lines { - mut trimmed := line.trim_space() - - if trimmed.len == 0 { - output += '
\n' - continue - } - - lvl, mut text := parse_header(trimmed) - - is_header := lvl > 0 - - if is_header { - output += '' - output += text + '' - } else { - output += text - output += '
' - } - - output += '\n' - } - - output += '

' - return output -} diff --git a/test b/test index 0f4ed1c..c36a7d9 100755 --- a/test +++ b/test @@ -1 +1 @@ -clear && make format && cat README.tlm | make run | ./preview +clear && make format && cat README.tlm | make run # | ./preview diff --git a/v.mod b/v.mod deleted file mode 100644 index 152bf4f..0000000 --- a/v.mod +++ /dev/null @@ -1,7 +0,0 @@ -Module { - name: 'TypoML' - description: '' - version: '0.0.0' - license: 'ISC' - dependencies: [] -}