tacker

a simple web bundler
git clone https://tongong.net/git/tacker.git
Log | Files | Refs | README

commit 17839623927e816114d4f6858520958748d0ede2
parent dc7d92ffbab9cda6929046f9b5fbea1a625d807f
Author: tongong <tongong@gmx.net>
Date:   Wed, 29 Jun 2022 18:20:48 +0200

added html->binary bundling

Diffstat:
Mbundle_binary.ha | 2+-
Mbundle_html.ha | 54++++++++++++++++++++++++++++++++++++++----------------
Msearchio/searchio.ha | 29+++++++++++++++++------------
Atest-page/example.png | 0
Mtest-page/index.html | 2++
5 files changed, 58 insertions(+), 29 deletions(-)

diff --git a/bundle_binary.ha b/bundle_binary.ha @@ -5,7 +5,7 @@ use os; fn tacker_binary(inputpath: str, ofile: io::handle) void = { const ifile = os::open(inputpath)!; defer io::close(ifile)!; - const enc = base64::newencoder(&base64::url_encoding, ofile); + const enc = base64::newencoder(&base64::std_encoding, ofile); io::copy(&enc, ifile)!; io::close(&enc)!; }; diff --git a/bundle_html.ha b/bundle_html.ha @@ -25,16 +25,23 @@ fn tacker_html(inputpath: str, ofile: io::handle) void = { const m = searchio::search(ifile, ofile, p_main); if (m is size) { const m = m: size; - if (m == 0) { // html comments + + let tagbuf = bufio::dynamic(io::mode::RDWR); + defer io::close(&tagbuf)!; + if (m != 0) { + fmt::fprint(&tagbuf, p_main.original[m])!; + searchio::search(ifile, &tagbuf, p_tagclose); + fmt::fprint(&tagbuf, ">")!; + }; + + if (m == 0) { + // html comments fmt::fprint(ofile, "<!--")!; searchio::search(ifile, ofile, p_comment); fmt::fprint(ofile, "-->")!; - } else if (m == 1) { // <script> - let tagbuf = bufio::dynamic(io::mode::RDWR); - defer io::close(&tagbuf)!; - fmt::fprint(&tagbuf, "<script")!; - searchio::search(ifile, &tagbuf, p_tagclose); - fmt::fprint(&tagbuf, ">")!; + } else if (m == 1) { + // <script> -> look at src and replace the whole + // tag const src = tag_get_attr(tagbuf.buf, strings::toutf8("src")); if (src is not_found) { @@ -51,12 +58,9 @@ fn tacker_html(inputpath: str, ofile: io::handle) void = { tacker_js(src, ofile); fmt::fprint(ofile, "</script>")!; }; - } else if (m == 2) { // stylesheets - let tagbuf = bufio::dynamic(io::mode::RDWR); - defer io::close(&tagbuf)!; - fmt::fprint(&tagbuf, "<link")!; - searchio::search(ifile, &tagbuf, p_tagclose); - fmt::fprint(&tagbuf, ">")!; + } else if (m == 2) { + // stylesheets -> look at rel and href and + // replace the whole tag const rel = tag_get_attr(tagbuf.buf, strings::toutf8("rel")); let is_style = rel is tag_split; @@ -73,7 +77,9 @@ fn tacker_html(inputpath: str, ofile: io::handle) void = { const href = tag_get_attr(tagbuf.buf, strings::toutf8("href")); if (href is not_found) - fixed_fatalf("broken style tag \"{}\".", strings::fromutf8(tagbuf.buf)); + fixed_fatalf("broken style tag \"{}\".", + strings::fromutf8( + tagbuf.buf)); const href = href: tag_split; const href = strings::fromutf8(href.1); fmt::fprint(ofile, "<style>\n")!; @@ -84,8 +90,24 @@ fn tacker_html(inputpath: str, ofile: io::handle) void = { fmt::fprint(ofile, "</style>")!; }; } else { - // TODO other embeds - fmt::fatal("[TODO] unimplemented html tag transform"); + // media tags -> look at src and replace only + // src, not the whole tag + const src = tag_get_attr(tagbuf.buf, + strings::toutf8("src")); + if (src is not_found) { + io::write(ofile, tagbuf.buf)!; + } else { + const src = src: tag_split; + const srctext = strings::fromutf8( + src.1); + const srctext = resolve_path(srctext, + inputpath); + defer free(srctext); + io::write(ofile, src.0)!; + fmt::fprint(ofile, "data:;base64,")!; + tacker_binary(srctext, ofile); + io::write(ofile, src.2)!; + }; }; } else break; }; diff --git a/searchio/searchio.ha b/searchio/searchio.ha @@ -4,8 +4,11 @@ use os; use sort; use strings; -// sorted -export type pattern = []patternelem; +export type pattern = struct { + elems: []patternelem, // sorted + // reference to the string list before compile + original: []str, +}; export type patternelem = struct { // if the first n bytes are identical to the first n bytes in the string // before they are set to 0 @@ -29,7 +32,7 @@ fn patternelem_cmp(a: *void, b: *void) int = { // pattern has to be finished export fn compile(s: []str) pattern = { - let p: pattern = []; + let p: []patternelem = []; for (let i = 0z; i < len(s); i += 1) { append(p, patternelem { data = strings::toutf8(strings::dup(s[i])), @@ -46,12 +49,12 @@ export fn compile(s: []str) pattern = { } else break; }; }; - return p; + return pattern { elems = p, original = s }; }; export fn finish(p: pattern) void = { - for (let i = 0z; i < len(p); i += 1) { - free(p[i].data); + for (let i = 0z; i < len(p.elems); i += 1) { + free(p.elems[i].data); }; }; @@ -78,8 +81,8 @@ export fn search(ifile: io::handle, ofile: io::handle, end: pattern) const buf = buf[0]; let nomatches = true; - for (let i = curr_elem; i < len(end); i += 1) { - const e = end[i].data; + for (let i = curr_elem; i < len(end.elems); i += 1) { + const e = end.elems[i].data; if (curr_index != 0 && i != curr_elem && e[curr_index - 1] != 0) break; if (e[curr_index] != 0 && e[curr_index] > buf) break; @@ -87,8 +90,9 @@ export fn search(ifile: io::handle, ofile: io::handle, end: pattern) curr_elem = i; curr_index += 1; nomatches = false; - if (curr_index == len(end[curr_elem].data)) - return end[curr_elem].index; + if (curr_index == len(end.elems[curr_elem] + .data)) + return end.elems[curr_elem].index; break; }; }; @@ -96,10 +100,11 @@ export fn search(ifile: io::handle, ofile: io::handle, end: pattern) if (curr_index != 0) { for (let i = 0z; i < curr_index; i += 1) { let elem = curr_elem; - for (end[elem].data[i] == 0) { + for (end.elems[elem].data[i] == 0) { elem -= 1; }; - io::write(ofile, [end[elem].data[i]])!; + io::write(ofile, [end.elems[elem] + .data[i]])!; }; curr_elem = 0; curr_index = 0; diff --git a/test-page/example.png b/test-page/example.png Binary files differ. diff --git a/test-page/index.html b/test-page/index.html @@ -11,5 +11,7 @@ </head> <body> <h1>test page</h1> + a nice image: + <img src=./example.png alt="example image"/> </body> </html>