@benev/turtle
Advanced tools
Comparing version 0.2.1 to 0.3.0
{ | ||
"name": "@benev/turtle", | ||
"version": "0.2.1", | ||
"version": "0.3.0", | ||
"description": "static site generator", | ||
@@ -21,3 +21,4 @@ "license": "MIT", | ||
"watch": "tsc -w", | ||
"demo": "node x/cli.js --in s/demo:x/demo --out x/demo --exclude **/*.partial.html.js +verbose", | ||
"watch-test": "chokidar 'x/**/*.js' -c 'npm test'", | ||
"demo": "node x/cli.js --in='s/demo:x/demo' --out='x/demo' --exclude='**/*.partial.html.js' +verbose", | ||
"help": "node x/cli.js +help", | ||
@@ -34,2 +35,4 @@ "test": "cynic node x/tests.test.js" | ||
"@types/node": "^20.3.0", | ||
"chokidar": "^3.5.3", | ||
"chokidar-cli": "^3.0.0", | ||
"cynic": "^0.2.1", | ||
@@ -36,0 +39,0 @@ "http-server": "^14.1.1", |
@@ -21,6 +21,6 @@ | ||
### run turtle to generate a website | ||
### generate a website with turtle's cli | ||
```sh | ||
npx @benev/turtle --in="s/demo:x/demo" --out="x/demo" --verbose="true" | ||
npx @benev/turtle --in="s/demo:x/demo" --out="x/demo" --exclude="**/*.partial.html.js" --verbose="true" | ||
``` | ||
@@ -47,5 +47,6 @@ | ||
```js | ||
import {webpage, html} from "@benev/turtle" | ||
import {template, html} from "@benev/turtle" | ||
const {url} = import.meta.url | ||
export default webpage(async({v}) => html` | ||
export default template(async({path}) => html` | ||
<!doctype html> | ||
@@ -55,3 +56,3 @@ <html> | ||
<title>@benev/turtle</title> | ||
<link rel="stylesheet" href="${v("/style.css")}"/> | ||
<link rel="stylesheet" href="${path(url).version.root('style.css')}"/> | ||
</head> | ||
@@ -76,6 +77,6 @@ <body> | ||
```ts | ||
import {webpage, html} from "@benev/turtle" | ||
import {template, html} from "@benev/turtle" | ||
const {url} = import.meta | ||
export default webpage<{x: number}>(async({v}, {x}) => html` | ||
export default template(async({path}, x: number) => html` | ||
<!doctype html> | ||
@@ -86,3 +87,3 @@ <html> | ||
<title>@benev/turtle - stamp test</title> | ||
<link rel="stylesheet" href="${v("/style.css")}"/> | ||
<link rel="stylesheet" href="${path(url).version.root('style.css')}"/> | ||
</head> | ||
@@ -94,3 +95,2 @@ <body> | ||
</html> | ||
`) | ||
@@ -131,3 +131,3 @@ ``` | ||
// provide the x value in the context | ||
context: {x}, | ||
context: x, | ||
@@ -144,5 +144,5 @@ // specify the destination relative | ||
### you've gotta get into *hash versioning!* | ||
- that's what the above example is doing with that `v` function | ||
- you use `v` on your urls, and `v` will attach that file's hash as a suffix | ||
### you've gotta get into *file path hash versioning!* | ||
- that's what the above example is doing with that `path` function | ||
- if you use `.version` then it will attach the file's hash as a suffix | ||
- so `/style.css` becomes `/style.css?v=c252882f` | ||
@@ -153,2 +153,43 @@ - now when you deploy your site, your users won't see old cached css files that break your website -- now the browser cache becomes *version aware!* 🤯 | ||
### use `path` in your templates | ||
turtle gives you a `path` utility that allows you to link to file from different reference points. it can also do *file path hash versioning* for you. | ||
to understand it, consider a hypothetical file structure like this: | ||
``` | ||
s/ <-- (source directory) | ||
favicon.png | ||
cool/ | ||
awesome.html.ts <-- (your turtle template) | ||
style.css | ||
``` | ||
also, we'll assume you've set `const {url} = import.meta` | ||
- `path(url).root("favicon.png")` | ||
use *root* to reference files relative to the website root. | ||
result: `../favicon.png` | ||
- `path(url).local("style.css")` | ||
use *local* to reference files relative to the current template module. | ||
result: `style.css` | ||
- `path(url).dest("rofl.jpg")` | ||
use *dest* for special cases, to reference files relative to the *destination html file* that it output. | ||
this is for custom turtle script builds, where the destination html file output will be written into a different directory structure than the location of the current template module. | ||
okay, this might make more sense when you consider file path versioning. | ||
simply add `.version` to the above commands, and turtle will attach a hash query param suffix, which will magically fix all your browser caching problems: | ||
- `path(url).version.root("favicon.png")` | ||
result: `../favicon.png?v=f6dd3bc1` | ||
- `path(url).version.local("style.css")` | ||
result: `style.css?v=ce5f3acd` | ||
- `path(url).version.dest("rofl.jpg")` | ||
<br/> | ||
### remember, the templates are just async js functions | ||
@@ -155,0 +196,0 @@ - so you can import other modules, read and write files, whatever you want |
import {WebpageMaker} from "../../html/webpage.js" | ||
import {Template} from "../template.js" | ||
export async function load_template_function<xContext extends {}>( | ||
export async function load_template_function<C>( | ||
import_path_for_template_module: string, | ||
@@ -9,4 +9,4 @@ ) { | ||
const template_module = await import(import_path_for_template_module) | ||
return template_module.default as WebpageMaker<xContext> | ||
return template_module.default as Template<C> | ||
} | ||
import {join, resolve} from "path" | ||
import {Template} from "../template.js" | ||
import {Path} from "../../utils/path.js" | ||
import {untab} from "../../html/untab.js" | ||
import {debase_path} from "./debase_path.js" | ||
import {PathRouter} from "./path/path_router.js" | ||
import {OutputLogger} from "../types/loggers.js" | ||
import {WebpageMaker} from "../../html/webpage.js" | ||
import {write_file} from "../../utils/write_file.js" | ||
import {make_template_basics} from "./make_template_basics.js" | ||
import {TemplateBasics} from "../types/template_basics.js" | ||
export async function write_webpage<xContext extends {}>({ | ||
export async function write_webpage<C>({ | ||
path, | ||
@@ -21,6 +22,6 @@ context, | ||
path: Path | ||
context: xContext | ||
context: C | ||
destination: string | ||
template: Template<C> | ||
output_directory: string | ||
template: WebpageMaker<xContext> | ||
on_file_written: OutputLogger | ||
@@ -31,13 +32,2 @@ }) { | ||
const basics = make_template_basics({ | ||
destination, | ||
template_path, | ||
output_directory, | ||
input_directory: path.directory, | ||
}) | ||
const template_function = await template(basics, context) | ||
const result_html = await template_function.render() | ||
const final_html = untab(result_html).trim() | ||
const partial = debase_path(output_directory, destination) | ||
@@ -51,2 +41,13 @@ const final_destination: Path = { | ||
const basics: TemplateBasics = { | ||
path: PathRouter.make_path_routing_function({ | ||
destination_path: final_destination.absolute, | ||
web_root_that_contains_template_module: resolve(path.directory), | ||
}), | ||
} | ||
const template_function = await template(basics, context) | ||
const result_html = await template_function.render() | ||
const final_html = untab(result_html).trim() | ||
await write_file(final_destination.relative, final_html) | ||
@@ -53,0 +54,0 @@ on_file_written(path, final_destination) |
import {dirname} from "path" | ||
import {Path} from "../../utils/path.js" | ||
@@ -7,3 +9,2 @@ import {log_error} from "../../utils/log_error.js" | ||
import {OutputLogger, TurtleScriptLogger} from "../types/loggers.js" | ||
import { dirname } from "path" | ||
@@ -10,0 +11,0 @@ export async function run_all_turtle_scripts( |
import {Path} from "../../utils/path.js" | ||
import {OutputLogger} from "./loggers.js" | ||
import {WebpageMaker} from "../../html/webpage.js" | ||
import {Template} from "../template.js" | ||
@@ -11,8 +11,8 @@ export type ScriptMeta = { | ||
on_file_written: OutputLogger | ||
write_webpage: <xContext extends {}>({}: { | ||
context: xContext | ||
write_webpage: <C>({}: { | ||
context: C | ||
destination: string | ||
template: WebpageMaker<xContext> | ||
template: Template<C> | ||
}) => Promise<void> | ||
} | ||
import {HashVersioner} from "../../utils/hash_versioner.js" | ||
import {PathRoutingFunction} from "../parts/path/path_router.js" | ||
export interface TemplateBasics { | ||
base: string | ||
v: HashVersioner | ||
path: PathRoutingFunction | ||
} | ||
import {webpage, html} from "../index.js" | ||
import {html} from "../html/html.js" | ||
import {template} from "../build/template.js" | ||
import {description, random_value} from "./data.js" | ||
export default webpage(async({v}) => html` | ||
const {url} = import.meta | ||
export default template(async({path}) => html` | ||
<!doctype html> | ||
@@ -12,3 +14,3 @@ <html> | ||
<title>@benev/turtle - alpha</title> | ||
<link rel="stylesheet" href="${v("/style.css")}"/> | ||
<link rel="stylesheet" href="${path(url).version.root('style.css')}"/> | ||
</head> | ||
@@ -21,4 +23,3 @@ <body> | ||
</html> | ||
`) | ||
import {webpage, html} from "../index.js" | ||
import {html} from "../html/html.js" | ||
import {template} from "../build/template.js" | ||
import {description, random_value} from "./data.js" | ||
import pagePartialHtml from "./page.partial.html.js" | ||
export default webpage(async({v}) => html` | ||
export default template(async basics => pagePartialHtml(basics, html` | ||
<p>${description}</p> | ||
<p>${random_value}</p> | ||
`)) | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"/> | ||
<title>@benev/turtle</title> | ||
<link rel="stylesheet" href="${v("/style.css")}"/> | ||
</head> | ||
<body> | ||
<h1>@benev/turtle</h1> | ||
<p>${description}</p> | ||
<p>${random_value}</p> | ||
</body> | ||
</html> | ||
`) | ||
import {turtle_script} from "../../build/turtle_script.js" | ||
import page from "./page.partial.html.js" | ||
import page from "./stamp.partial.html.js" | ||
@@ -6,0 +6,0 @@ // we'll stamp out a webpage for each of these values |
import {HtmlTemplate} from "./template.js" | ||
import {Html} from "./template.js" | ||
@@ -7,6 +7,6 @@ export function html( | ||
...values: any[] | ||
): HtmlTemplate { | ||
): Html { | ||
return new HtmlTemplate({strings, values}) | ||
return new Html({strings, values}) | ||
} | ||
import {HtmlTemplate} from "./template.js" | ||
import {Html} from "./template.js" | ||
export function render(template: HtmlTemplate) { | ||
export function render(template: Html) { | ||
return template.toString() | ||
} | ||
import {escape_html} from "../utils/escape_html.js" | ||
export type HtmlTemplateOptions = { | ||
export type HtmlOptions = { | ||
strings: TemplateStringsArray | string[] | ||
@@ -9,7 +9,7 @@ values: any[] | ||
export class HtmlTemplate { | ||
export class Html { | ||
#strings: string[] | ||
#values: any[] | ||
constructor({strings, values}: HtmlTemplateOptions) { | ||
constructor({strings, values}: HtmlOptions) { | ||
this.#strings = [...strings] | ||
@@ -20,3 +20,3 @@ this.#values = values | ||
#process_value(value: any): string { | ||
return value instanceof HtmlTemplate | ||
return value instanceof Html | ||
? value.toString() | ||
@@ -27,3 +27,3 @@ : escape_html(value.toString()) | ||
async #process_async_value(value: any): Promise<string> { | ||
return value instanceof HtmlTemplate | ||
return value instanceof Html | ||
? await value.render() | ||
@@ -30,0 +30,0 @@ : escape_html(value.toString()) |
import {HtmlTemplate} from "./template.js" | ||
import {Html} from "./template.js" | ||
export function unsanitized(value: string) { | ||
return new HtmlTemplate({strings: [value], values: []}) | ||
return new Html({strings: [value], values: []}) | ||
} | ||
export * from "./build/build_webpage.js" | ||
export * from "./build/build_website.js" | ||
export * from "./build/template.js" | ||
export * from "./build/turtle_script.js" | ||
export * from "./build/build_website.js" | ||
export * from "./build/build_webpage.js" | ||
@@ -10,3 +11,3 @@ export * from "./build/types/loggers.js" | ||
export * from "./errors/hash_versioner_error.js" | ||
export * from "./errors/hashing_error.js" | ||
@@ -19,8 +20,8 @@ export * from "./html/helpers.js" | ||
export * from "./html/untab.js" | ||
export * from "./html/webpage.js" | ||
export * from "./utils/hashing/apply_file_hash_to_url.js" | ||
export * from "./utils/hashing/compute_hash_for_file.js" | ||
export * from "./utils/escape_html.js" | ||
export * from "./utils/escape_regex.js" | ||
export * from "./utils/find_files.js" | ||
export * from "./utils/hash_versioner.js" | ||
export * from "./utils/indent.js" | ||
@@ -27,0 +28,0 @@ export * from "./utils/nap.js" |
@@ -8,7 +8,9 @@ | ||
import {render} from "./html/render.js" | ||
import {HtmlTemplate} from "./html/template.js" | ||
import {Html} from "./html/template.js" | ||
import {unsanitized} from "./html/unsanitized.js" | ||
import {make_hash_versioner} from "./utils/hash_versioner.js" | ||
import {PathRouter} from "./build/parts/path/path_router.js" | ||
import {apply_file_hash_to_url} from "./utils/hashing/apply_file_hash_to_url.js" | ||
export default <Suite>{ | ||
"ergonomics": { | ||
@@ -22,2 +24,3 @@ async "null and undefined injections do nothing"() { | ||
}, | ||
"async": { | ||
@@ -51,4 +54,5 @@ async "injected promises are resolved"() { | ||
}, | ||
"sanitization": async() => { | ||
const isSanitized = (t: HtmlTemplate) => !render(t).includes("<script>") | ||
const isSanitized = (t: Html) => !render(t).includes("<script>") | ||
return { | ||
@@ -78,2 +82,3 @@ async "template itself is not sanitized"() { | ||
}, | ||
"nesting": { | ||
@@ -96,2 +101,3 @@ "nested html functions must not be sanitized": async () => { | ||
}, | ||
"arrays": { | ||
@@ -104,7 +110,8 @@ async "arrays of values are joined together cleanly"() { | ||
}, | ||
"versioning": { | ||
async "adds file hash to url"() { | ||
const v = make_hash_versioner({root: "x"}) | ||
const url = "index.js" | ||
const result = await v(url) | ||
const filepath = "x/index.js" | ||
const result = await apply_file_hash_to_url({url, filepath}) | ||
assert( | ||
@@ -116,5 +123,5 @@ /(\S+)\?v=\S{8,64}/.test(result), | ||
async "adds file hash to url that already has a querystring"() { | ||
const v = make_hash_versioner({root: "x"}) | ||
const url = "index.js?lol=rofl" | ||
const result = await v(url) | ||
const filepath = "x/index.js" | ||
const result = await apply_file_hash_to_url({url, filepath}) | ||
assert( | ||
@@ -126,2 +133,3 @@ /(\S+)\?lol=rofl&v=\S{8,64}/.test(result), | ||
}, | ||
"untab": { | ||
@@ -162,2 +170,3 @@ async "handles string without any tabbing"() { | ||
}, | ||
"unsanitized": { | ||
@@ -170,3 +179,35 @@ async "unsanitized values are not sanitized"() { | ||
}, | ||
"path routing": async() => { | ||
const url = "file:///home/chase/work/@benev/turtle/x/demo/stamping/stamp.partial.html.js" | ||
const path = PathRouter.make_path_routing_function({ | ||
destination_path: "/home/chase/work/@benev/turtle/x/demo/lol/2.html", | ||
web_root_that_contains_template_module: "/home/chase/work/@benev/turtle/x/demo", | ||
}) | ||
return { | ||
async "root can traverse up one level (../)"() { | ||
expect(path(url).root("style.css")).equals("../style.css") | ||
}, | ||
async "local can find its way back to module's directory"() { | ||
const url = "file:///home/chase/work/@benev/turtle/x/demo/stamping/stamp.partial.html.js" | ||
const path = PathRouter.make_path_routing_function({ | ||
destination_path: "/home/chase/work/@benev/turtle/x/demo/lol/2.html", | ||
web_root_that_contains_template_module: "/home/chase/work/@benev/turtle/x/demo", | ||
}) | ||
expect(path(url).local("style.css")).equals("../stamping/style.css") | ||
}, | ||
async "dest just returns the same path"() { | ||
const url = "file:///home/chase/work/@benev/turtle/x/demo/stamping/stamp.partial.html.js" | ||
const path = PathRouter.make_path_routing_function({ | ||
destination_path: "/home/chase/work/@benev/turtle/x/demo/lol/2.html", | ||
web_root_that_contains_template_module: "/home/chase/work/@benev/turtle/x/demo", | ||
}) | ||
expect(path(url).dest("style.css")).equals("style.css") | ||
}, | ||
} | ||
}, | ||
} | ||
@@ -1,2 +0,2 @@ | ||
import { WebpageMaker } from "../../html/webpage.js"; | ||
export declare function load_template_function<xContext extends {}>(import_path_for_template_module: string): Promise<WebpageMaker<xContext>>; | ||
import { Template } from "../template.js"; | ||
export declare function load_template_function<C>(import_path_for_template_module: string): Promise<Template<C>>; |
@@ -0,11 +1,11 @@ | ||
import { Template } from "../template.js"; | ||
import { Path } from "../../utils/path.js"; | ||
import { OutputLogger } from "../types/loggers.js"; | ||
import { WebpageMaker } from "../../html/webpage.js"; | ||
export declare function write_webpage<xContext extends {}>({ path, context, destination, output_directory, template, on_file_written, }: { | ||
export declare function write_webpage<C>({ path, context, destination, output_directory, template, on_file_written, }: { | ||
path: Path; | ||
context: xContext; | ||
context: C; | ||
destination: string; | ||
template: Template<C>; | ||
output_directory: string; | ||
template: WebpageMaker<xContext>; | ||
on_file_written: OutputLogger; | ||
}): Promise<void>; |
import { join, resolve } from "path"; | ||
import { untab } from "../../html/untab.js"; | ||
import { debase_path } from "./debase_path.js"; | ||
import { PathRouter } from "./path/path_router.js"; | ||
import { write_file } from "../../utils/write_file.js"; | ||
import { make_template_basics } from "./make_template_basics.js"; | ||
export async function write_webpage({ path, context, destination, output_directory, template, on_file_written, }) { | ||
const template_path = path.relative; | ||
const basics = make_template_basics({ | ||
destination, | ||
template_path, | ||
output_directory, | ||
input_directory: path.directory, | ||
}); | ||
const template_function = await template(basics, context); | ||
const result_html = await template_function.render(); | ||
const final_html = untab(result_html).trim(); | ||
const partial = debase_path(output_directory, destination); | ||
@@ -24,2 +15,11 @@ const final_destination = { | ||
}; | ||
const basics = { | ||
path: PathRouter.make_path_routing_function({ | ||
destination_path: final_destination.absolute, | ||
web_root_that_contains_template_module: resolve(path.directory), | ||
}), | ||
}; | ||
const template_function = await template(basics, context); | ||
const result_html = await template_function.render(); | ||
const final_html = untab(result_html).trim(); | ||
await write_file(final_destination.relative, final_html); | ||
@@ -26,0 +26,0 @@ on_file_written(path, final_destination); |
@@ -0,4 +1,4 @@ | ||
import { dirname } from "path"; | ||
import { log_error } from "../../utils/log_error.js"; | ||
import { write_webpage } from "../parts/write_webpage.js"; | ||
import { dirname } from "path"; | ||
export async function run_all_turtle_scripts(paths, output_directory, on_file_written, on_turtle_script_executed) { | ||
@@ -5,0 +5,0 @@ const handy_write_webpage = (path) => (async ({ template, context, destination }) => { |
import { Path } from "../../utils/path.js"; | ||
import { OutputLogger } from "./loggers.js"; | ||
import { WebpageMaker } from "../../html/webpage.js"; | ||
import { Template } from "../template.js"; | ||
export type ScriptMeta = { | ||
@@ -9,7 +9,7 @@ path: Path; | ||
on_file_written: OutputLogger; | ||
write_webpage: <xContext extends {}>({}: { | ||
context: xContext; | ||
write_webpage: <C>({}: { | ||
context: C; | ||
destination: string; | ||
template: WebpageMaker<xContext>; | ||
template: Template<C>; | ||
}) => Promise<void>; | ||
}; |
@@ -1,5 +0,4 @@ | ||
import { HashVersioner } from "../../utils/hash_versioner.js"; | ||
import { PathRoutingFunction } from "../parts/path/path_router.js"; | ||
export interface TemplateBasics { | ||
base: string; | ||
v: HashVersioner; | ||
path: PathRoutingFunction; | ||
} |
@@ -1,2 +0,2 @@ | ||
declare const _default: import("../index.js").WebpageMaker<{}>; | ||
declare const _default: import("../build/template.js").Template<unknown>; | ||
export default _default; |
@@ -1,5 +0,6 @@ | ||
import { webpage, html } from "../index.js"; | ||
import { html } from "../html/html.js"; | ||
import { template } from "../build/template.js"; | ||
import { description, random_value } from "./data.js"; | ||
export default webpage(async ({ v }) => html ` | ||
const { url } = import.meta; | ||
export default template(async ({ path }) => html ` | ||
<!doctype html> | ||
@@ -10,3 +11,3 @@ <html> | ||
<title>@benev/turtle - alpha</title> | ||
<link rel="stylesheet" href="${v("/style.css")}"/> | ||
<link rel="stylesheet" href="${path(url).version.root('style.css')}"/> | ||
</head> | ||
@@ -19,4 +20,3 @@ <body> | ||
</html> | ||
`); | ||
//# sourceMappingURL=alpha.html.js.map |
@@ -1,2 +0,2 @@ | ||
declare const _default: import("../index.js").WebpageMaker<{}>; | ||
declare const _default: import("../build/template.js").Template<unknown>; | ||
export default _default; |
@@ -1,20 +0,9 @@ | ||
import { webpage, html } from "../index.js"; | ||
import { html } from "../html/html.js"; | ||
import { template } from "../build/template.js"; | ||
import { description, random_value } from "./data.js"; | ||
export default webpage(async ({ v }) => html ` | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"/> | ||
<title>@benev/turtle</title> | ||
<link rel="stylesheet" href="${v("/style.css")}"/> | ||
</head> | ||
<body> | ||
<h1>@benev/turtle</h1> | ||
<p>${description}</p> | ||
<p>${random_value}</p> | ||
</body> | ||
</html> | ||
`); | ||
import pagePartialHtml from "./page.partial.html.js"; | ||
export default template(async (basics) => pagePartialHtml(basics, html ` | ||
<p>${description}</p> | ||
<p>${random_value}</p> | ||
`)); | ||
//# sourceMappingURL=index.html.js.map |
import { turtle_script } from "../../build/turtle_script.js"; | ||
import page from "./page.partial.html.js"; | ||
import page from "./stamp.partial.html.js"; | ||
// we'll stamp out a webpage for each of these values | ||
@@ -4,0 +4,0 @@ const values = [1, 2]; |
@@ -1,3 +0,3 @@ | ||
export declare function attrMaybe(attr: string, value: string | undefined): "" | import("./template.js").HtmlTemplate; | ||
export declare function attrMaybe(attr: string, value: string | undefined): "" | import("./template.js").Html; | ||
export declare function attrBool(attr: string, value: boolean): string; | ||
export declare function maybe<V>(value: V, realize: (value: V) => any): any; |
@@ -1,2 +0,2 @@ | ||
import { HtmlTemplate } from "./template.js"; | ||
export declare function html(strings: TemplateStringsArray, ...values: any[]): HtmlTemplate; | ||
import { Html } from "./template.js"; | ||
export declare function html(strings: TemplateStringsArray, ...values: any[]): Html; |
@@ -1,5 +0,5 @@ | ||
import { HtmlTemplate } from "./template.js"; | ||
import { Html } from "./template.js"; | ||
export function html(strings, ...values) { | ||
return new HtmlTemplate({ strings, values }); | ||
return new Html({ strings, values }); | ||
} | ||
//# sourceMappingURL=html.js.map |
@@ -1,2 +0,2 @@ | ||
import { HtmlTemplate } from "./template.js"; | ||
export declare function render(template: HtmlTemplate): string; | ||
import { Html } from "./template.js"; | ||
export declare function render(template: Html): string; |
@@ -1,10 +0,10 @@ | ||
export type HtmlTemplateOptions = { | ||
export type HtmlOptions = { | ||
strings: TemplateStringsArray | string[]; | ||
values: any[]; | ||
}; | ||
export declare class HtmlTemplate { | ||
export declare class Html { | ||
#private; | ||
constructor({ strings, values }: HtmlTemplateOptions); | ||
constructor({ strings, values }: HtmlOptions); | ||
toString(): string; | ||
render(): Promise<string>; | ||
} |
@@ -12,19 +12,19 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
}; | ||
var _HtmlTemplate_instances, _HtmlTemplate_strings, _HtmlTemplate_values, _HtmlTemplate_process_value, _HtmlTemplate_process_async_value; | ||
var _Html_instances, _Html_strings, _Html_values, _Html_process_value, _Html_process_async_value; | ||
import { escape_html } from "../utils/escape_html.js"; | ||
export class HtmlTemplate { | ||
export class Html { | ||
constructor({ strings, values }) { | ||
_HtmlTemplate_instances.add(this); | ||
_HtmlTemplate_strings.set(this, void 0); | ||
_HtmlTemplate_values.set(this, void 0); | ||
__classPrivateFieldSet(this, _HtmlTemplate_strings, [...strings], "f"); | ||
__classPrivateFieldSet(this, _HtmlTemplate_values, values, "f"); | ||
_Html_instances.add(this); | ||
_Html_strings.set(this, void 0); | ||
_Html_values.set(this, void 0); | ||
__classPrivateFieldSet(this, _Html_strings, [...strings], "f"); | ||
__classPrivateFieldSet(this, _Html_values, values, "f"); | ||
} | ||
toString() { | ||
return __classPrivateFieldGet(this, _HtmlTemplate_strings, "f").reduce((previous, current, index) => { | ||
return __classPrivateFieldGet(this, _Html_strings, "f").reduce((previous, current, index) => { | ||
var _a; | ||
const value = (_a = __classPrivateFieldGet(this, _HtmlTemplate_values, "f")[index]) !== null && _a !== void 0 ? _a : ""; | ||
const value = (_a = __classPrivateFieldGet(this, _Html_values, "f")[index]) !== null && _a !== void 0 ? _a : ""; | ||
const safeValue = Array.isArray(value) | ||
? value.map(__classPrivateFieldGet(this, _HtmlTemplate_instances, "m", _HtmlTemplate_process_value)).join("") | ||
: __classPrivateFieldGet(this, _HtmlTemplate_instances, "m", _HtmlTemplate_process_value).call(this, value); | ||
? value.map(__classPrivateFieldGet(this, _Html_instances, "m", _Html_process_value)).join("") | ||
: __classPrivateFieldGet(this, _Html_instances, "m", _Html_process_value).call(this, value); | ||
return previous + current + safeValue; | ||
@@ -34,8 +34,8 @@ }, ""); | ||
async render() { | ||
const results = await Promise.all(__classPrivateFieldGet(this, _HtmlTemplate_strings, "f").map(async (string, index) => { | ||
const results = await Promise.all(__classPrivateFieldGet(this, _Html_strings, "f").map(async (string, index) => { | ||
var _a; | ||
const value = (_a = await __classPrivateFieldGet(this, _HtmlTemplate_values, "f")[index]) !== null && _a !== void 0 ? _a : ""; | ||
const value = (_a = await __classPrivateFieldGet(this, _Html_values, "f")[index]) !== null && _a !== void 0 ? _a : ""; | ||
const safeValue = Array.isArray(value) | ||
? (await Promise.all(value.map(__classPrivateFieldGet(this, _HtmlTemplate_instances, "m", _HtmlTemplate_process_async_value)))).join("") | ||
: await __classPrivateFieldGet(this, _HtmlTemplate_instances, "m", _HtmlTemplate_process_async_value).call(this, value); | ||
? (await Promise.all(value.map(__classPrivateFieldGet(this, _Html_instances, "m", _Html_process_async_value)))).join("") | ||
: await __classPrivateFieldGet(this, _Html_instances, "m", _Html_process_async_value).call(this, value); | ||
return string + safeValue; | ||
@@ -46,8 +46,8 @@ })); | ||
} | ||
_HtmlTemplate_strings = new WeakMap(), _HtmlTemplate_values = new WeakMap(), _HtmlTemplate_instances = new WeakSet(), _HtmlTemplate_process_value = function _HtmlTemplate_process_value(value) { | ||
return value instanceof HtmlTemplate | ||
_Html_strings = new WeakMap(), _Html_values = new WeakMap(), _Html_instances = new WeakSet(), _Html_process_value = function _Html_process_value(value) { | ||
return value instanceof Html | ||
? value.toString() | ||
: escape_html(value.toString()); | ||
}, _HtmlTemplate_process_async_value = async function _HtmlTemplate_process_async_value(value) { | ||
return value instanceof HtmlTemplate | ||
}, _Html_process_async_value = async function _Html_process_async_value(value) { | ||
return value instanceof Html | ||
? await value.render() | ||
@@ -54,0 +54,0 @@ : escape_html(value.toString()); |
@@ -1,2 +0,2 @@ | ||
import { HtmlTemplate } from "./template.js"; | ||
export declare function unsanitized(value: string): HtmlTemplate; | ||
import { Html } from "./template.js"; | ||
export declare function unsanitized(value: string): Html; |
@@ -1,5 +0,5 @@ | ||
import { HtmlTemplate } from "./template.js"; | ||
import { Html } from "./template.js"; | ||
export function unsanitized(value) { | ||
return new HtmlTemplate({ strings: [value], values: [] }); | ||
return new Html({ strings: [value], values: [] }); | ||
} | ||
//# sourceMappingURL=unsanitized.js.map |
@@ -0,8 +1,9 @@ | ||
export * from "./build/build_webpage.js"; | ||
export * from "./build/build_website.js"; | ||
export * from "./build/template.js"; | ||
export * from "./build/turtle_script.js"; | ||
export * from "./build/build_website.js"; | ||
export * from "./build/build_webpage.js"; | ||
export * from "./build/types/loggers.js"; | ||
export * from "./build/types/script_meta.js"; | ||
export * from "./build/types/template_basics.js"; | ||
export * from "./errors/hash_versioner_error.js"; | ||
export * from "./errors/hashing_error.js"; | ||
export * from "./html/helpers.js"; | ||
@@ -14,7 +15,7 @@ export * from "./html/template.js"; | ||
export * from "./html/untab.js"; | ||
export * from "./html/webpage.js"; | ||
export * from "./utils/hashing/apply_file_hash_to_url.js"; | ||
export * from "./utils/hashing/compute_hash_for_file.js"; | ||
export * from "./utils/escape_html.js"; | ||
export * from "./utils/escape_regex.js"; | ||
export * from "./utils/find_files.js"; | ||
export * from "./utils/hash_versioner.js"; | ||
export * from "./utils/indent.js"; | ||
@@ -21,0 +22,0 @@ export * from "./utils/nap.js"; |
@@ -0,8 +1,9 @@ | ||
export * from "./build/build_webpage.js"; | ||
export * from "./build/build_website.js"; | ||
export * from "./build/template.js"; | ||
export * from "./build/turtle_script.js"; | ||
export * from "./build/build_website.js"; | ||
export * from "./build/build_webpage.js"; | ||
export * from "./build/types/loggers.js"; | ||
export * from "./build/types/script_meta.js"; | ||
export * from "./build/types/template_basics.js"; | ||
export * from "./errors/hash_versioner_error.js"; | ||
export * from "./errors/hashing_error.js"; | ||
export * from "./html/helpers.js"; | ||
@@ -14,7 +15,7 @@ export * from "./html/template.js"; | ||
export * from "./html/untab.js"; | ||
export * from "./html/webpage.js"; | ||
export * from "./utils/hashing/apply_file_hash_to_url.js"; | ||
export * from "./utils/hashing/compute_hash_for_file.js"; | ||
export * from "./utils/escape_html.js"; | ||
export * from "./utils/escape_regex.js"; | ||
export * from "./utils/find_files.js"; | ||
export * from "./utils/hash_versioner.js"; | ||
export * from "./utils/indent.js"; | ||
@@ -21,0 +22,0 @@ export * from "./utils/nap.js"; |
@@ -7,3 +7,4 @@ import { assert, expect } from "cynic"; | ||
import { unsanitized } from "./html/unsanitized.js"; | ||
import { make_hash_versioner } from "./utils/hash_versioner.js"; | ||
import { PathRouter } from "./build/parts/path/path_router.js"; | ||
import { apply_file_hash_to_url } from "./utils/hashing/apply_file_hash_to_url.js"; | ||
export default { | ||
@@ -98,11 +99,11 @@ "ergonomics": { | ||
async "adds file hash to url"() { | ||
const v = make_hash_versioner({ root: "x" }); | ||
const url = "index.js"; | ||
const result = await v(url); | ||
const filepath = "x/index.js"; | ||
const result = await apply_file_hash_to_url({ url, filepath }); | ||
assert(/(\S+)\?v=\S{8,64}/.test(result), "url is versioned with hash"); | ||
}, | ||
async "adds file hash to url that already has a querystring"() { | ||
const v = make_hash_versioner({ root: "x" }); | ||
const url = "index.js?lol=rofl"; | ||
const result = await v(url); | ||
const filepath = "x/index.js"; | ||
const result = await apply_file_hash_to_url({ url, filepath }); | ||
assert(/(\S+)\?lol=rofl&v=\S{8,64}/.test(result), "url is versioned with hash"); | ||
@@ -149,3 +150,31 @@ }, | ||
}, | ||
"path routing": async () => { | ||
const url = "file:///home/chase/work/@benev/turtle/x/demo/stamping/stamp.partial.html.js"; | ||
const path = PathRouter.make_path_routing_function({ | ||
destination_path: "/home/chase/work/@benev/turtle/x/demo/lol/2.html", | ||
web_root_that_contains_template_module: "/home/chase/work/@benev/turtle/x/demo", | ||
}); | ||
return { | ||
async "root can traverse up one level (../)"() { | ||
expect(path(url).root("style.css")).equals("../style.css"); | ||
}, | ||
async "local can find its way back to module's directory"() { | ||
const url = "file:///home/chase/work/@benev/turtle/x/demo/stamping/stamp.partial.html.js"; | ||
const path = PathRouter.make_path_routing_function({ | ||
destination_path: "/home/chase/work/@benev/turtle/x/demo/lol/2.html", | ||
web_root_that_contains_template_module: "/home/chase/work/@benev/turtle/x/demo", | ||
}); | ||
expect(path(url).local("style.css")).equals("../stamping/style.css"); | ||
}, | ||
async "dest just returns the same path"() { | ||
const url = "file:///home/chase/work/@benev/turtle/x/demo/stamping/stamp.partial.html.js"; | ||
const path = PathRouter.make_path_routing_function({ | ||
destination_path: "/home/chase/work/@benev/turtle/x/demo/lol/2.html", | ||
web_root_that_contains_template_module: "/home/chase/work/@benev/turtle/x/demo", | ||
}); | ||
expect(path(url).dest("style.css")).equals("style.css"); | ||
}, | ||
}; | ||
}, | ||
}; | ||
//# sourceMappingURL=tests.test.js.map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
118277
193
2083
196
7