Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F996384
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/package.json b/package.json
index 027bd5d..efee29e 100644
--- a/package.json
+++ b/package.json
@@ -1,60 +1,60 @@
{
"name": "@sealcode/jdd",
- "version": "0.6.0-alpha2",
+ "version": "0.6.0-alpha3",
"description": "JSON-Driven Documents",
"main": "lib/index.js",
"type": "module",
"scripts": {
"pretest": "npm run build",
"test": "node test.cjs",
"prebuild": "npm run lint",
"build": "tsc",
"typecheck": "tsc --noemit",
"prepare": "npm run build",
"lint": "eslint src",
"preinstrument": "npm run build && rm -fr .xunit coverage lib-instrumented",
"instrument": "npx nyc instrument --exclude \"\" lib lib-instrumented",
"pretest-reports": "npm run instrument",
"test-reports": "npx nyc --exclude \"\" ./node_modules/.bin/mocha --recursive --timeout=10000 --require source-map-support/register --reporter xunit --reporter-option output=.xunit 'lib-instrumented/**/*.test.js' && nyc report --reporter clover --exclude \"\"",
"precover-html": "rm -rf coverate/lcov-report",
"cover-html": "npm run test-reports && nyc report --reporter lcov --exclude \"\" && xdg-open coverage/lcov-report/index.html"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@types/mocha": "^10.0.1",
"@types/prettier": "^2.7.0",
"@types/slug": "^5.0.9",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^5.58.0",
"@typescript-eslint/parser": "^5.58.0",
"assert": "^2.0.0",
"eslint": "^8.38.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-with-tsc-error": "^0.0.8",
"mocha": "^10.2.0",
"nyc": "^15.1.0",
"source-map-support": "^0.5.21",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
},
"types": "./@types/index.d.ts",
"dependencies": {
"@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.5.3",
"escape-goat": "^4.0.0",
"hyphenopoly": "^5.3.0",
"koa-responsive-image-router": "^0.2.29",
"locreq": "^3.0.0",
"marked": "^12.0.0",
"mri": "^1.2.0",
"prettier": "^2.7.1",
"slug": "^9.1.0",
"tempstream": "^0.4.1",
"uuid": "^9.0.1"
},
"peerDependencies": {
"sealious": "^0.19.18"
}
}
diff --git a/src/jdd.ts b/src/jdd.ts
index af60e15..16300a3 100644
--- a/src/jdd.ts
+++ b/src/jdd.ts
@@ -1,207 +1,216 @@
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
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Dec 24, 14:02 (10 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
557226
Default Alt Text
(7 KB)
Attached To
Mode
R130 jdd
Attached
Detach File
Event Timeline
Log In to Comment