diff --git a/scripts/deps-docker/Dockerfile b/scripts/deps-docker/Dockerfile index b65e85ad..f1307ca5 100644 --- a/scripts/deps-docker/Dockerfile +++ b/scripts/deps-docker/Dockerfile @@ -7,6 +7,7 @@ ENV ver_asmcrypto=c72492f4a66e17a0e5dd8ad7874de354f3ccdaa5 \ ver_mde=2.18.0 \ ver_codemirror=5.65.12 \ ver_fontawesome=5.13.0 \ + ver_prism=1.29.0 \ ver_zopfli=1.0.3 # versioncheck: @@ -30,6 +31,7 @@ RUN mkdir -p /z/dist/no-pk \ && wget https://github.com/FortAwesome/Font-Awesome/releases/download/$ver_fontawesome/fontawesome-free-$ver_fontawesome-web.zip -O fontawesome.zip \ && wget https://github.com/google/zopfli/archive/zopfli-$ver_zopfli.tar.gz -O zopfli.tgz \ && wget https://github.com/Daninet/hash-wasm/releases/download/v$ver_hashwasm/hash-wasm@$ver_hashwasm.zip -O hash-wasm.zip \ + && wget https://github.com/PrismJS/prism/archive/refs/tags/v$ver_prism.tar.gz -O prism.tgz \ && (mkdir hash-wasm \ && cd hash-wasm \ && unzip ../hash-wasm.zip) \ @@ -47,14 +49,11 @@ RUN mkdir -p /z/dist/no-pk \ && cd easy-markdown-editor* \ && npm install \ && npm i gulp-cli -g ) \ + && tar -xf prism.tgz \ && unzip fontawesome.zip \ && tar -xf zopfli.tgz -# todo -# https://prismjs.com/download.html#themes=prism-funky&languages=markup+css+clike+javascript+autohotkey+bash+basic+batch+c+csharp+cpp+cmake+diff+docker+go+ini+java+json+kotlin+latex+less+lisp+lua+makefile+objectivec+perl+powershell+python+r+jsx+ruby+rust+sass+scss+sql+swift+systemd+toml+typescript+vbnet+verilog+vhdl+yaml&plugins=line-highlight+line-numbers+autolinker - - # build fonttools (which needs zopfli) RUN tar -xf zopfli.tgz \ && cd zopfli* \ @@ -129,6 +128,12 @@ COPY shiftbase.py /z RUN /bin/ash /z/mini-fa.sh +# build prismjs +COPY genprism.py /z +COPY genprism.sh /z +RUN ./genprism.sh $ver_prism + + # compress COPY zopfli.makefile /z/dist/Makefile RUN cd /z/dist \ diff --git a/scripts/deps-docker/Makefile b/scripts/deps-docker/Makefile index ab3d96a9..4951d11e 100644 --- a/scripts/deps-docker/Makefile +++ b/scripts/deps-docker/Makefile @@ -13,6 +13,7 @@ all: docker run --rm -i build-copyparty-deps:latest | \ tar -xvC $(vend) --strip-components=1 + touch $(vend)/__init__.py chown -R `stat $(self) -c %u:%g` $(vend) purge: diff --git a/scripts/deps-docker/genprism.py b/scripts/deps-docker/genprism.py new file mode 100755 index 00000000..c7548372 --- /dev/null +++ b/scripts/deps-docker/genprism.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 + +# author: @chinponya + + +import argparse +import json +from pathlib import Path +from urllib.parse import urlparse, parse_qsl + + +def read_json(path): + return json.loads(path.read_text()) + + +def get_prism_version(prism_path): + package_json_path = prism_path / "package.json" + package_json = read_json(package_json_path) + return package_json["version"] + + +def get_prism_components(prism_path): + components_json_path = prism_path / "components.json" + components_json = read_json(components_json_path) + return components_json + + +def parse_prism_configuration(url_str): + url = urlparse(url_str) + # prism.com uses a non-standard query string-like encoding + query = {k: v.split(" ") for k, v in parse_qsl(url.fragment)} + return query + + +def paths_of_component(prism_path, kind, components, name, minified): + component = components[kind][name] + meta = components[kind]["meta"] + path_format = meta["path"] + path_base = prism_path / path_format.replace("{id}", name) + + if isinstance(component, str): + # 'core' component has a different shape, so we convert it to be consistent + component = {"title": component} + + if meta.get("noCSS") or component.get("noCSS"): + extensions = ["js"] + elif kind == "themes": + extensions = ["css"] + else: + extensions = ["js", "css"] + + if path_base.is_dir(): + result = {ext: path_base / f"{name}.{ext}" for ext in extensions} + elif path_base.suffix: + ext = path_base.suffix.replace(".", "") + result = {ext: path_base} + else: + result = {ext: path_base.with_suffix(f".{ext}") for ext in extensions} + + if minified: + result = { + ext: path.with_suffix(".min" + path.suffix) for ext, path in result.items() + } + + return result + + +def read_component_contents(kv_paths): + return {k: path.read_text() for k, path in kv_paths.items()} + + +def get_language_dependencies(components, name): + dependencies = components["languages"][name].get("require") + + if isinstance(dependencies, list): + return dependencies + elif isinstance(dependencies, str): + return [dependencies] + else: + return [] + + +def make_header(prism_path, url): + version = get_prism_version(prism_path) + header = f"/* PrismJS {version}\n{url} */" + return {"js": header, "css": header} + + +def make_core(prism_path, components, minified): + kv_paths = paths_of_component(prism_path, "core", components, "core", minified) + return read_component_contents(kv_paths) + + +def make_theme(prism_path, components, name, minified): + kv_paths = paths_of_component(prism_path, "themes", components, name, minified) + return read_component_contents(kv_paths) + + +def make_language(prism_path, components, name, minified): + kv_paths = paths_of_component(prism_path, "languages", components, name, minified) + return read_component_contents(kv_paths) + + +def make_languages(prism_path, components, names, minified): + names_with_dependencies = sum( + ([*get_language_dependencies(components, name), name] for name in names), [] + ) + + seen = set() + names_with_dependencies = [ + x for x in names_with_dependencies if not (x in seen or seen.add(x)) + ] + + kv_code = [ + make_language(prism_path, components, name, minified) + for name in names_with_dependencies + ] + + return kv_code + + +def make_plugin(prism_path, components, name, minified): + kv_paths = paths_of_component(prism_path, "plugins", components, name, minified) + return read_component_contents(kv_paths) + + +def make_plugins(prism_path, components, names, minified): + kv_code = [make_plugin(prism_path, components, name, minified) for name in names] + return kv_code + + +def make_code(prism_path, url, minified): + components = get_prism_components(prism_path) + configuration = parse_prism_configuration(url) + theme_name = configuration["themes"][0] + code = [ + make_header(prism_path, url), + make_core(prism_path, components, minified), + make_theme(prism_path, components, theme_name, minified), + ] + + if configuration.get("languages"): + code.extend( + make_languages(prism_path, components, configuration["languages"], minified) + ) + + if configuration.get("plugins"): + code.extend( + make_plugins(prism_path, components, configuration["plugins"], minified) + ) + + return code + + +def join_code(kv_code): + result = {"js": "", "css": ""} + + for row in kv_code: + for key, code in row.items(): + result[key] += code + result[key] += "\n" + + return result + + +def write_code(kv_code, js_out, css_out): + code = join_code(kv_code) + + with js_out.open("w") as f: + f.write(code["js"]) + print(f"written {js_out}") + + with css_out.open("w") as f: + f.write(code["css"]) + print(f"written {css_out}") + + +def parse_args(): + # fmt: off + parser = argparse.ArgumentParser() + parser.add_argument("url", help="configured prism download url") + parser.add_argument("--dir", type=Path, default=Path("."), help="prism repo directory") + parser.add_argument("--minify", default=True, action=argparse.BooleanOptionalAction, help="use minified files",) + parser.add_argument("--js-out", type=Path, default=Path("prism.js"), help="JS output file path") + parser.add_argument("--css-out", type=Path, default=Path("prism.css"), help="CSS output file path") + # fmt: on + args = parser.parse_args() + return args + + +def main(): + args = parse_args() + code = make_code(args.dir, args.url, args.minify) + write_code(code, args.js_out, args.css_out) + + +if __name__ == "__main__": + main() diff --git a/scripts/deps-docker/genprism.sh b/scripts/deps-docker/genprism.sh new file mode 100755 index 00000000..0a9ff227 --- /dev/null +++ b/scripts/deps-docker/genprism.sh @@ -0,0 +1,66 @@ +#!/bin/bash +set -e + +langs=( + markup + css + clike + javascript + autohotkey + bash + basic + batch + c + csharp + cpp + cmake + diff + docker + elixir + glsl + go + ini + java + json + kotlin + latex + less + lisp + lua + makefile + matlab + moonscript + nim + objectivec + perl + powershell + python + r + jsx + ruby + rust + sass + scss + sql + swift + systemd + toml + typescript + vbnet + verilog + vhdl + yaml + zig +) + +slangs="${langs[*]}" +slangs="${slangs// /+}" + +for theme in prism-funky prism ; do + u="https://prismjs.com/download.html#themes=$theme&languages=$slangs&plugins=line-highlight+line-numbers+autolinker" + echo "$u" + ./genprism.py --dir prism-$1 --js-out prism.js --css-out $theme.css "$u" +done + +mv prism-funky.css prismd.css +mv prismd.css prism.css prism.js /z/dist/