Page MenuHomeSealhub

jdd.ts
No OneTemporary

import { tempstream } from "tempstream";
import { JDDContext } from "./jdd-context.js";
import { Registry } from "./registry.js";
import { EarlyAsset, JDDHeading } from "./component.js";
import { hasField } from "@sealcode/ts-predicates";
import {
JDDocumentContainer,
RawJDDocument,
documentContainerFromParsed,
documentContainerFromStorage,
} from "./document.js";
import { documentToParsed } from "./document.js";
export class JDD {
constructor(
public registry: Registry,
public jdd_context: JDDContext,
public parsed: JDDocumentContainer<"parsed">
) {}
static async fromStorage(
registry: Registry,
jdd_context: JDDContext,
document: RawJDDocument
) {
const parsed = await documentToParsed(
registry,
jdd_context,
documentContainerFromStorage(document)
);
return new JDD(registry, jdd_context, parsed);
}
static fromParsed(
registry: Registry,
jdd_context: JDDContext,
parsed: RawJDDocument
) {
return new JDD(
registry,
jdd_context,
documentContainerFromParsed(parsed)
);
}
render(
make_component_classes = (index: number) => [
"jdd-component",
`component-number-${index}`,
]
) {
return tempstream`${this.parsed.value.map(
({ component_name, args }, index) => {
const component = this.registry.get(component_name);
if (!component) {
console.warn(
"Component not found in the registry: " + component_name
);
return "";
}
for (const arg_name in component?.getArguments()) {
if (!Object.prototype.hasOwnProperty.call(args, arg_name)) {
args[arg_name] = component
?.getArguments()
[arg_name]?.getEmptyValue(this.jdd_context);
}
}
return component.toHTML({
args,
classes: make_component_classes(index),
jdd_context: this.jdd_context,
index,
});
}
)}`;
}
renderEarlyScript(asset: EarlyAsset): string {
if (hasField("url", asset)) {
return /* HTML */ `<script
async
src="${asset.url}"
onLoad="document.dispatchEvent(new Event('loaded-${asset.identity}'))"
${(asset.integrity &&
`integrity="${asset.integrity}" crossorigin="anonymous"`) ||
""}
></script>`;
} else {
return /* HTML */ `<script><${asset.content}/script>`;
}
}
renderEarlyStyle(asset: EarlyAsset): string {
if (hasField("url", asset)) {
const integrity =
(asset.integrity &&
`integrity="${asset.integrity}" crossorigin="anonymous"`) ||
"";
// see https://web.dev/articles/defer-non-critical-css
return /* HTML */ `<link
rel="preload"
href="${asset.url}"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
${integrity}
/>
<noscript
><link rel="stylesheet" href="${asset.url}" ${integrity}
/></noscript>`;
} else {
return /* HTML */ `<style>
${asset.content}
</style>`;
}
}
async renderEarlyAssets() {
const early_assets = (
await Promise.all(
this.parsed.value.map(async ({ component_name, args }) => {
const component = this.registry.get(component_name);
if (!component) {
console.warn(
"Component not found in the registry: " +
component_name
);
return [];
}
for (const arg_name in component?.getArguments()) {
if (
!Object.prototype.hasOwnProperty.call(
args,
arg_name
)
) {
args[arg_name] = component
?.getArguments()
[arg_name]?.getEmptyValue(this.jdd_context);
}
}
return await component.getEarlyAssets(
args,
this.jdd_context
);
})
)
).flat();
const deduplicated_assets: Record<string, EarlyAsset> = {};
for (const asset of early_assets) {
deduplicated_assets[asset.identity] = asset;
}
return Object.values(deduplicated_assets)
.map((asset) => {
if (asset.type == "script") {
return this.renderEarlyScript(asset);
} else if (asset.type == "style") {
this.renderEarlyStyle(asset);
}
})
.join(" ");
}
countWords(registry: Registry): number {
return this.parsed.value.reduce((acc, { component_name, args }) => {
const component = registry.get(component_name);
if (!component) {
console.warn(
"Component not found in the registry: " + component_name
);
return acc + 0;
}
return acc + component.countWords(args);
}, 0);
}
getHeadings(): JDDHeading[] {
return this.parsed.value
.map(({ component_name, args }) => {
const component = this.registry.get(component_name);
if (!component) {
return [];
}
return component.getHeadings(this.jdd_context, args);
})
.flat();
}
static async renderFromStorage(
registry: Registry,
document: RawJDDocument,
jdd_context: JDDContext
) {
const jdd = await JDD.fromStorage(registry, jdd_context, document);
return jdd.render();
}
static async renderEarlyAssetsFromStorage(
registry: Registry,
document: RawJDDocument,
jdd_context: JDDContext
) {
const jdd = await JDD.fromStorage(registry, jdd_context, document);
return jdd.renderEarlyAssets();
}
static async render(
registry: Registry,
parsed: JDDocumentContainer<"parsed">,
jdd_context: JDDContext
) {
const jdd = new JDD(registry, jdd_context, parsed);
return jdd.render();
}
}

File Metadata

Mime Type
text/html
Expires
Sat, Sep 20, 14:26 (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
949272
Default Alt Text
jdd.ts (5 KB)

Event Timeline