nodoku-core 0.1.1 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{dist/esm → esm}/bin/mustache/component-resolver.ts.hbs +2 -2
- package/{dist/esm → esm}/content/nd-content.js +2 -2
- package/{dist/esm → esm}/core/dummy-comp.jsx +2 -2
- package/esm/core/rendering-page-props.js +35 -0
- package/{dist/esm → esm}/core/rendering-page.jsx +18 -35
- package/{dist/esm → esm}/index.js +2 -2
- package/{dist/esm → esm}/providers/content/content-markdown-provider.js +20 -20
- package/{dist/esm → esm}/providers/skin/skin-yaml-provider.js +4 -1
- package/package.json +9 -15
- package/schemas/md-content-block-delimiter.json +26 -0
- package/{dist/types → types}/content/nd-content.d.ts +17 -17
- package/{dist/types → types}/core/providers.d.ts +3 -3
- package/{dist/types → types}/core/rendering-page-props.d.ts +4 -4
- package/{dist/types → types}/index.d.ts +2 -2
- package/LICENSE +0 -21
- package/README.MD +0 -46
- package/dist/esm/core/rendering-page-props.js +0 -23
- /package/{dist/esm → esm}/bin/generate-component-default-theme.js +0 -0
- /package/{dist/esm → esm}/bin/generate-component-resolver.js +0 -0
- /package/{dist/esm → esm}/bin/generate-content-schema.js +0 -0
- /package/{dist/esm → esm}/bin/generate-skin-schema.js +0 -0
- /package/{dist/esm → esm}/bin/import-load-hooks.js +0 -0
- /package/{dist/esm → esm}/bin/manifest-loader.js +0 -0
- /package/{dist/esm → esm}/bin/manifest.js +0 -0
- /package/{dist/esm → esm}/bin/mustache/content-schema.json.hbs +0 -0
- /package/{dist/esm → esm}/bin/mustache/visual-schema.json.hbs +0 -0
- /package/{dist/esm → esm}/core/providers.js +0 -0
- /package/{dist/esm → esm}/skin/nd-skin.js +0 -0
- /package/{dist/esm → esm}/theme-utils/extended-theme-style.js +0 -0
- /package/{dist/esm → esm}/theme-utils/theme-merger.js +0 -0
- /package/{dist/esm → esm}/theme-utils/theme-style.js +0 -0
- /package/{dist/schemas → schemas}/content-common-schema.json +0 -0
- /package/{dist/schemas → schemas}/manifest-schema.json +0 -0
- /package/{dist/schemas → schemas}/skin-common-schema.json +0 -0
- /package/{dist/types → types}/bin/generate-component-default-theme.d.ts +0 -0
- /package/{dist/types → types}/bin/generate-component-resolver.d.ts +0 -0
- /package/{dist/types → types}/bin/generate-content-schema.d.ts +0 -0
- /package/{dist/types → types}/bin/generate-skin-schema.d.ts +0 -0
- /package/{dist/types → types}/bin/import-load-hooks.d.ts +0 -0
- /package/{dist/types → types}/bin/manifest-loader.d.ts +0 -0
- /package/{dist/types → types}/bin/manifest.d.ts +0 -0
- /package/{dist/types → types}/core/dummy-comp.d.ts +0 -0
- /package/{dist/types → types}/core/rendering-page.d.ts +0 -0
- /package/{dist/types → types}/providers/content/content-markdown-provider.d.ts +0 -0
- /package/{dist/types → types}/providers/skin/skin-yaml-provider.d.ts +0 -0
- /package/{dist/types → types}/skin/nd-skin.d.ts +0 -0
- /package/{dist/types → types}/theme-utils/extended-theme-style.d.ts +0 -0
- /package/{dist/types → types}/theme-utils/theme-merger.d.ts +0 -0
- /package/{dist/types → types}/theme-utils/theme-style.d.ts +0 -0
|
@@ -10,7 +10,7 @@ const components: Map<string, {compo: AsyncFunctionComponent, compoDef: NdCompon
|
|
|
10
10
|
components.set("{{{name}}}", {compo: {{impl}}, compoDef: new NdComponentDefinition({{{numBlocks}}}, "{{{defaultThemeFile}}}")});
|
|
11
11
|
{{/comps}}
|
|
12
12
|
|
|
13
|
-
export function
|
|
13
|
+
export async function nodokuComponentResolver(componentName: string): Promise<{compo: AsyncFunctionComponent, compoDef: NdComponentDefinition}> {
|
|
14
14
|
const f: {compo: AsyncFunctionComponent, compoDef: NdComponentDefinition} | undefined = components.get(componentName);
|
|
15
|
-
return
|
|
15
|
+
return f ? f : {compo: DummyComp, compoDef: new NdComponentDefinition(1)};
|
|
16
16
|
}
|
|
@@ -3,7 +3,7 @@ export class NdContentImage {
|
|
|
3
3
|
title;
|
|
4
4
|
alt;
|
|
5
5
|
}
|
|
6
|
-
export class
|
|
6
|
+
export class NdTranslatableText {
|
|
7
7
|
key = "";
|
|
8
8
|
ns = "";
|
|
9
9
|
text = "";
|
|
@@ -75,7 +75,7 @@ export class NdContentBlock {
|
|
|
75
75
|
}
|
|
76
76
|
function getPropertyFromObjectRecursively(obj, path) {
|
|
77
77
|
// console.log(`getting path from obj >>${path}<<`, obj)
|
|
78
|
-
if (obj instanceof
|
|
78
|
+
if (obj instanceof NdTranslatableText) {
|
|
79
79
|
return obj.text;
|
|
80
80
|
}
|
|
81
81
|
if (path.length == 0) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NdCode,
|
|
1
|
+
import { NdCode, NdTranslatableText } from "../content/nd-content";
|
|
2
2
|
// import {CodeComp} from "./code-comp";
|
|
3
3
|
export async function DummyComp(props) {
|
|
4
4
|
// console.log("content dummy comp", props.theme)
|
|
@@ -33,7 +33,7 @@ async function render(rowIndex, componentIndex, block, t) {
|
|
|
33
33
|
|
|
34
34
|
paragraphs:
|
|
35
35
|
{await Promise.all(block.paragraphs.map(async (p, ip) => {
|
|
36
|
-
if (p instanceof
|
|
36
|
+
if (p instanceof NdTranslatableText) {
|
|
37
37
|
return (<div>
|
|
38
38
|
{p && p.key}
|
|
39
39
|
<p key={ip} className={"mb-3 font-normal text-gray-700 dark:text-gray-400"}>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export var RenderingPriority;
|
|
2
|
+
(function (RenderingPriority) {
|
|
3
|
+
/*
|
|
4
|
+
* the content is rendered as it appears in the markdown file, sequentially, block by block, from top to bottom
|
|
5
|
+
* if a visual component is configured in the skin Yaml file, this visual component is used for rendering the content block.
|
|
6
|
+
* Otherwise a default visual component is used
|
|
7
|
+
*/
|
|
8
|
+
RenderingPriority[RenderingPriority["content_first"] = 0] = "content_first";
|
|
9
|
+
/*
|
|
10
|
+
* the rendering is fully prescribed by the skin Yaml file
|
|
11
|
+
* The components are rendered in the order they appear in the Yaml file
|
|
12
|
+
* If a content block is not matched by any of the visual components in the skin Yaml file, it is not rendered at all
|
|
13
|
+
* If a content block matches more than one visual component, each visual component is rendered,
|
|
14
|
+
* and the same content block will appear several times on the page
|
|
15
|
+
*/
|
|
16
|
+
RenderingPriority[RenderingPriority["skin_first"] = 1] = "skin_first";
|
|
17
|
+
})(RenderingPriority || (RenderingPriority = {}));
|
|
18
|
+
export class RenderingPageProps {
|
|
19
|
+
lng;
|
|
20
|
+
content;
|
|
21
|
+
skin = undefined;
|
|
22
|
+
renderingPriority = RenderingPriority.content_first;
|
|
23
|
+
componentResolver = undefined;
|
|
24
|
+
imageUrlProvider = undefined;
|
|
25
|
+
i18nextProvider = undefined;
|
|
26
|
+
constructor(lng, content, componentResolver, skin = undefined, renderingPriority = RenderingPriority.content_first, imageUrlProvider = undefined, i18nextProvider = undefined) {
|
|
27
|
+
this.lng = lng;
|
|
28
|
+
this.renderingPriority = renderingPriority;
|
|
29
|
+
this.content = content;
|
|
30
|
+
this.componentResolver = componentResolver;
|
|
31
|
+
this.skin = skin;
|
|
32
|
+
this.imageUrlProvider = imageUrlProvider;
|
|
33
|
+
this.i18nextProvider = i18nextProvider;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -5,7 +5,7 @@ import { DummyComp } from "./dummy-comp";
|
|
|
5
5
|
import yaml from "js-yaml";
|
|
6
6
|
import fs from "node:fs";
|
|
7
7
|
import { mergeTheme } from "../theme-utils/theme-merger";
|
|
8
|
-
async function
|
|
8
|
+
async function defaultComponentResolver() {
|
|
9
9
|
const compoDef = new NdComponentDefinition("unlimited", undefined, {});
|
|
10
10
|
return { compo: DummyComp, compoDef: compoDef };
|
|
11
11
|
}
|
|
@@ -13,11 +13,8 @@ async function defaultImageUrlProvider(imageUrl) {
|
|
|
13
13
|
return imageUrl;
|
|
14
14
|
}
|
|
15
15
|
async function RenderingPage(props) {
|
|
16
|
-
const { lng, renderingPriority, content,
|
|
17
|
-
const
|
|
18
|
-
// if (!componentProvider) {
|
|
19
|
-
// componentProvider = defaultComponentProvider;
|
|
20
|
-
// }
|
|
16
|
+
const { lng, renderingPriority, content, componentResolver, skin, imageUrlProvider, i18nextProvider } = props;
|
|
17
|
+
const actualComponentResolver = componentResolver ? componentResolver : defaultComponentResolver;
|
|
21
18
|
let l;
|
|
22
19
|
if (skin) {
|
|
23
20
|
let blockSkin = skin;
|
|
@@ -26,15 +23,11 @@ async function RenderingPage(props) {
|
|
|
26
23
|
}
|
|
27
24
|
// console.log(" >>> this is my content <<< ", content)
|
|
28
25
|
// console.log(" >>> this is my skin <<< ", JSON.stringify(blockSkin))
|
|
29
|
-
l = await Promise.all(blockSkin.rows.map(async (row, iRow) => await createRow(row, iRow, content, lng, imageUrlProvider, i18nextProvider,
|
|
30
|
-
// await createSubRows(row, iRow, content, lng, imageUrlProvider, i18nextProvider, actualComponentProvider)
|
|
31
|
-
));
|
|
26
|
+
l = await Promise.all(blockSkin.rows.map(async (row, iRow) => await createRow(row, iRow, content, lng, imageUrlProvider, i18nextProvider, actualComponentResolver)));
|
|
32
27
|
}
|
|
33
28
|
else {
|
|
34
|
-
l = [await createRow(undefined, 0, content, lng, imageUrlProvider, i18nextProvider,
|
|
35
|
-
// l = [await createSubRows(undefined, 0, content, lng, imageUrlProvider, i18nextProvider, actualComponentProvider)];
|
|
29
|
+
l = [await createRow(undefined, 0, content, lng, imageUrlProvider, i18nextProvider, actualComponentResolver)];
|
|
36
30
|
}
|
|
37
|
-
// const rows: JSX.Element[] = l.flatMap((a: JSX.Element[]) => a);
|
|
38
31
|
return <div className={`${skin?.renderingPage?.base} ${skin?.renderingPage?.decoration}`}>{l}</div>;
|
|
39
32
|
}
|
|
40
33
|
function generateSkinByContentBlocks(blocks, skin) {
|
|
@@ -69,15 +62,18 @@ function generateSkinByContentBlocks(blocks, skin) {
|
|
|
69
62
|
// console.log("generated skin", JSON.stringify(res))
|
|
70
63
|
return res;
|
|
71
64
|
}
|
|
72
|
-
async function createRow(row, iRow, blocks, lng, imageUrlProvider, i18nProvider,
|
|
65
|
+
async function createRow(row, iRow, blocks, lng, imageUrlProvider, i18nProvider, componentResolver) {
|
|
73
66
|
let l;
|
|
74
67
|
if (row) {
|
|
75
|
-
l = await Promise.all(row.components.map(async (visualSection, iComp) => await createRowComponents(iRow, iComp, visualSection, blocks, lng, imageUrlProvider, i18nProvider,
|
|
68
|
+
l = await Promise.all(row.components.map(async (visualSection, iComp) => await createRowComponents(iRow, iComp, visualSection, blocks, lng, imageUrlProvider, i18nProvider, componentResolver)));
|
|
76
69
|
}
|
|
77
70
|
else {
|
|
78
|
-
l = await Promise.all(blocks.map(async (block, iComp) => await createRowComponents(iRow, iComp, undefined, [block], lng, imageUrlProvider, i18nProvider,
|
|
71
|
+
l = await Promise.all(blocks.map(async (block, iComp) => await createRowComponents(iRow, iComp, undefined, [block], lng, imageUrlProvider, i18nProvider, componentResolver)));
|
|
79
72
|
}
|
|
80
73
|
const rowComponents = l.flatMap((p) => p);
|
|
74
|
+
if (rowComponents.length == 0) {
|
|
75
|
+
return <></>;
|
|
76
|
+
}
|
|
81
77
|
const numComponents = rowComponents.length;
|
|
82
78
|
const rowEffectiveTheme = mergeTheme(row?.theme, NdRow.defaultRowTheme);
|
|
83
79
|
const maxCols = row?.maxCols ? row.maxCols : 3;
|
|
@@ -111,9 +107,6 @@ async function createRow(row, iRow, blocks, lng, imageUrlProvider, i18nProvider,
|
|
|
111
107
|
case 9:
|
|
112
108
|
gridCols = "lg:grid-cols-9";
|
|
113
109
|
break;
|
|
114
|
-
case 9:
|
|
115
|
-
gridCols = "lg:grid-cols-9";
|
|
116
|
-
break;
|
|
117
110
|
case 10:
|
|
118
111
|
gridCols = "lg:grid-cols-10";
|
|
119
112
|
break;
|
|
@@ -124,28 +117,18 @@ async function createRow(row, iRow, blocks, lng, imageUrlProvider, i18nProvider,
|
|
|
124
117
|
gridCols = "lg:grid-cols-12";
|
|
125
118
|
break;
|
|
126
119
|
}
|
|
127
|
-
// if (numComponents == 1) {
|
|
128
|
-
// return [<div key={`row-${iRow}`} className={`${rowEffectiveTheme?.base} ${rowEffectiveTheme?.decoration} class-row-${iRow}`}>{rowComponents[0]}</div>];
|
|
129
|
-
// } else {
|
|
130
|
-
// const subRows: JSX.Element[] = [];
|
|
131
|
-
// for (var i = 0; i < numComponents / numCols; i++) {
|
|
132
|
-
// subRows.push(
|
|
133
|
-
// <div key={`row-${iRow}`} className={`grid ${gridCols} ${rowEffectiveTheme?.base} ${rowEffectiveTheme?.decoration} class-row-${iRow}`}>
|
|
134
|
-
// {rowComponents.slice(numCols * i, Math.min((i + 1) * numCols, numComponents))}
|
|
135
|
-
// </div>
|
|
136
|
-
// )
|
|
137
|
-
//
|
|
138
|
-
// }
|
|
139
120
|
return (<div key={`row-${iRow}`} className={`grid ${gridCols} ${rowEffectiveTheme?.base} ${rowEffectiveTheme?.decoration} class-row-${iRow}`}>
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
// }
|
|
121
|
+
{rowComponents}
|
|
122
|
+
</div>);
|
|
143
123
|
}
|
|
144
|
-
async function createRowComponents(rowIndex, blockIndex, skinComponent, pageContent, lng, imageUrlProvide, i18nProvider,
|
|
124
|
+
async function createRowComponents(rowIndex, blockIndex, skinComponent, pageContent, lng, imageUrlProvide, i18nProvider, componentResolver) {
|
|
145
125
|
// console.log("before component", skinComponent)
|
|
146
126
|
const filteredBlocks = skinComponent ? skinComponent.selector.filterBlocks(pageContent) : pageContent;
|
|
127
|
+
if (filteredBlocks.length == 0) {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
147
130
|
// console.log("retrieving comp", rowIndex, blockIndex, filteredBlocks.map(fb => JSON.stringify(fb.attributes)).join(", "));
|
|
148
|
-
const { compo, compoDef } = await
|
|
131
|
+
const { compo, compoDef } = await componentResolver(skinComponent ? skinComponent.componentName : "default");
|
|
149
132
|
// console.log("start rendering comp", rowIndex, blockIndex, skinComponent);
|
|
150
133
|
if (!compoDef.defaultTheme && compoDef.defaultThemeYaml) {
|
|
151
134
|
compoDef.defaultTheme = yaml.load(fs.readFileSync(compoDef.defaultThemeYaml).toString());
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { NdContentImage,
|
|
1
|
+
import { NdContentImage, NdTranslatableText, NdList, NdCode, NdContentBlock } from "./content/nd-content";
|
|
2
2
|
import { NdSkinComponent, NdRow, NdPageSkin, NdSkinComponentProps, NdContentSelector, NdComponentDefinition, NdThemeHierarchy } from "./skin/nd-skin";
|
|
3
3
|
import { RenderingPageProps, RenderingPriority } from "./core/rendering-page-props";
|
|
4
4
|
import { RenderingPage } from "./core/rendering-page";
|
|
5
5
|
import { mergeTheme } from "./theme-utils/theme-merger";
|
|
6
6
|
import { ThemeStyle } from "./theme-utils/theme-style";
|
|
7
7
|
import { ExtendedThemeStyle } from "./theme-utils/extended-theme-style";
|
|
8
|
-
export { NdContentImage,
|
|
8
|
+
export { NdContentImage, NdTranslatableText, NdList, NdCode, NdContentBlock, NdSkinComponent, NdRow, NdPageSkin, NdSkinComponentProps, NdContentSelector, NdComponentDefinition, NdThemeHierarchy };
|
|
9
9
|
export { RenderingPageProps, RenderingPriority, RenderingPage };
|
|
10
10
|
export { mergeTheme, ThemeStyle, ExtendedThemeStyle };
|
|
11
11
|
export { DummyComp } from "./core/dummy-comp";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NdTranslatableText, NdList, NdContentBlock, NdContentImage, NdCode } from "nodoku-core";
|
|
2
2
|
import { Marked } from '@ts-stack/markdown';
|
|
3
3
|
import { parse } from 'node-html-parser';
|
|
4
4
|
import yaml from "js-yaml";
|
|
@@ -171,27 +171,27 @@ class BlockHolder {
|
|
|
171
171
|
this.blockContent.htmlStream.forEach((htmlElem, i) => {
|
|
172
172
|
let text = undefined;
|
|
173
173
|
if (i === this.blockContent.titleIndex) {
|
|
174
|
-
newBlock.title = new
|
|
174
|
+
newBlock.title = new NdTranslatableText(this.ns, `${blockId}.title`, htmlElem.innerHTML);
|
|
175
175
|
text = newBlock.title;
|
|
176
176
|
}
|
|
177
177
|
else if (i === this.blockContent.subTitleIndex) {
|
|
178
|
-
newBlock.subTitle = new
|
|
178
|
+
newBlock.subTitle = new NdTranslatableText(this.ns, `${blockId}.subTitle`, htmlElem.innerHTML);
|
|
179
179
|
text = newBlock.subTitle;
|
|
180
180
|
}
|
|
181
181
|
else if (i === this.blockContent.h3Index) {
|
|
182
|
-
newBlock.h3 = new
|
|
182
|
+
newBlock.h3 = new NdTranslatableText(this.ns, `${blockId}.h3`, htmlElem.innerHTML);
|
|
183
183
|
text = newBlock.h3;
|
|
184
184
|
}
|
|
185
185
|
else if (i === this.blockContent.h4Index) {
|
|
186
|
-
newBlock.h4 = new
|
|
186
|
+
newBlock.h4 = new NdTranslatableText(this.ns, `${blockId}.h4`, htmlElem.innerHTML);
|
|
187
187
|
text = newBlock.h4;
|
|
188
188
|
}
|
|
189
189
|
else if (i === this.blockContent.h5Index) {
|
|
190
|
-
newBlock.h5 = new
|
|
190
|
+
newBlock.h5 = new NdTranslatableText(this.ns, `${blockId}.h5`, htmlElem.innerHTML);
|
|
191
191
|
text = newBlock.h5;
|
|
192
192
|
}
|
|
193
193
|
else if (i === this.blockContent.h6Index) {
|
|
194
|
-
newBlock.h6 = new
|
|
194
|
+
newBlock.h6 = new NdTranslatableText(this.ns, `${blockId}.h6`, htmlElem.innerHTML);
|
|
195
195
|
text = newBlock.h6;
|
|
196
196
|
}
|
|
197
197
|
else if (this.blockContent.paragraphsIndex.indexOf(i) >= 0) {
|
|
@@ -213,16 +213,16 @@ class BlockHolder {
|
|
|
213
213
|
const imgHtmlElem = cn;
|
|
214
214
|
if (imgHtmlElem.rawTagName == "img") {
|
|
215
215
|
img = new NdContentImage();
|
|
216
|
-
img.url = new
|
|
217
|
-
img.alt = new
|
|
218
|
-
img.title = new
|
|
216
|
+
img.url = new NdTranslatableText(this.ns, `${blockId}.images.${imi}.url`, imgHtmlElem.attributes["src"], true);
|
|
217
|
+
img.alt = new NdTranslatableText(this.ns, `${blockId}.images.${imi}.alt`, imgHtmlElem.attributes["alt"]);
|
|
218
|
+
img.title = new NdTranslatableText(this.ns, `${blockId}.images.${imi}.title`, imgHtmlElem.attributes["title"]);
|
|
219
219
|
}
|
|
220
220
|
});
|
|
221
221
|
if (img) {
|
|
222
222
|
htmlElem.childNodes
|
|
223
223
|
.forEach((cn) => {
|
|
224
224
|
if (cn.rawTagName == "figcaption") {
|
|
225
|
-
img.title = new
|
|
225
|
+
img.title = new NdTranslatableText(this.ns, `${blockId}.images.${imi}.title`, cn.innerHTML);
|
|
226
226
|
}
|
|
227
227
|
});
|
|
228
228
|
}
|
|
@@ -232,9 +232,9 @@ class BlockHolder {
|
|
|
232
232
|
* extract image from <img>
|
|
233
233
|
*/
|
|
234
234
|
img = new NdContentImage();
|
|
235
|
-
img.url = new
|
|
236
|
-
img.alt = new
|
|
237
|
-
img.title = new
|
|
235
|
+
img.url = new NdTranslatableText(this.ns, `${blockId}.images.${imi}.url`, htmlElem.attributes["src"], true);
|
|
236
|
+
img.alt = new NdTranslatableText(this.ns, `${blockId}.images.${imi}.alt`, htmlElem.attributes["alt"]);
|
|
237
|
+
img.title = new NdTranslatableText(this.ns, `${blockId}.images.${imi}.title`, htmlElem.attributes["title"]);
|
|
238
238
|
}
|
|
239
239
|
if (img) {
|
|
240
240
|
newBlock.images.push(img);
|
|
@@ -243,22 +243,22 @@ class BlockHolder {
|
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
else {
|
|
246
|
-
text = new
|
|
246
|
+
text = new NdTranslatableText(this.ns, `${blockId}.htmlElements.${newBlock.htmlElements.length}`, "");
|
|
247
247
|
}
|
|
248
248
|
newBlock.htmlElements.push({ htmlElem: htmlElem, translatedText: text });
|
|
249
249
|
});
|
|
250
250
|
if (this.blockContent.footer && this.blockContent.footer.trim().length > 0) {
|
|
251
|
-
newBlock.footer = new
|
|
251
|
+
newBlock.footer = new NdTranslatableText(this.ns, `${blockId}.footer`, this.blockContent.footer);
|
|
252
252
|
}
|
|
253
253
|
if (this.blockContent.bgImage && this.blockContent.bgImage.getAttribute("src")) {
|
|
254
|
-
newBlock.bgImageUrl = new
|
|
254
|
+
newBlock.bgImageUrl = new NdTranslatableText(this.ns, `${blockId}.bgImageUrl`, this.blockContent.bgImage.getAttribute("src"), true);
|
|
255
255
|
}
|
|
256
256
|
// console.log("added block", newBlock)
|
|
257
257
|
return newBlock;
|
|
258
258
|
}
|
|
259
259
|
parseParagraph(blockId, p, pi) {
|
|
260
260
|
if (p.rawTagName === "p" || p.rawTagName === "blockquote") {
|
|
261
|
-
return new
|
|
261
|
+
return new NdTranslatableText(this.ns, `${blockId}.paragraphs.${pi}`, p.innerHTML);
|
|
262
262
|
}
|
|
263
263
|
else if (p.rawTagName === "pre") {
|
|
264
264
|
const codeHtml = p.childNodes[0];
|
|
@@ -276,7 +276,7 @@ class BlockHolder {
|
|
|
276
276
|
.filter(lin => lin.innerText && lin.innerText.trim().length > 0)
|
|
277
277
|
.map((lin, k) => {
|
|
278
278
|
const li = lin;
|
|
279
|
-
return new
|
|
279
|
+
return new NdTranslatableText(this.ns, `${blockId}.paragraphs.${pi}.items.${k}`, li.innerHTML);
|
|
280
280
|
}));
|
|
281
281
|
}
|
|
282
282
|
else if (p.rawTagName === "ul") {
|
|
@@ -284,7 +284,7 @@ class BlockHolder {
|
|
|
284
284
|
.filter(lin => lin.innerText && lin.innerText.trim().length > 0)
|
|
285
285
|
.map((lin, k) => {
|
|
286
286
|
const li = lin;
|
|
287
|
-
return new
|
|
287
|
+
return new NdTranslatableText(this.ns, `${blockId}.paragraphs.${pi}.items.${k}`, li.innerHTML);
|
|
288
288
|
}));
|
|
289
289
|
}
|
|
290
290
|
console.log("couldn't parse paragraph: ", p);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import yaml from "js-yaml";
|
|
2
|
-
import { NdContentSelector, NdRow, NdSkinComponent, NdThemeHierarchy } from "../../skin/nd-skin";
|
|
2
|
+
import { NdContentSelector, NdPageSkin, NdRow, NdSkinComponent, NdThemeHierarchy } from "../../skin/nd-skin";
|
|
3
3
|
export async function skinYamlProvider(yamlFileUrl) {
|
|
4
4
|
return await fetch(yamlFileUrl)
|
|
5
5
|
.then(response => response.text())
|
|
@@ -7,6 +7,9 @@ export async function skinYamlProvider(yamlFileUrl) {
|
|
|
7
7
|
}
|
|
8
8
|
export function parseYamlContentAsSkin(fileContents) {
|
|
9
9
|
const data = yaml.load(fileContents);
|
|
10
|
+
if (!data) {
|
|
11
|
+
return new NdPageSkin();
|
|
12
|
+
}
|
|
10
13
|
let defaultThemeName = "light";
|
|
11
14
|
let globalTheme = {};
|
|
12
15
|
let globalThemes = [];
|
package/package.json
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodoku-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "basic foundation for nodoku static site generator",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
|
-
"types": "./
|
|
8
|
-
"import": "./
|
|
7
|
+
"types": "./types/index.d.ts",
|
|
8
|
+
"import": "./esm/index.js"
|
|
9
9
|
},
|
|
10
10
|
"./package.json": "./package.json"
|
|
11
11
|
},
|
|
12
|
-
"module": "
|
|
13
|
-
"types": "
|
|
14
|
-
"files": [
|
|
15
|
-
"dist"
|
|
16
|
-
],
|
|
12
|
+
"module": "esm/index.js",
|
|
13
|
+
"types": "types/index.d.ts",
|
|
17
14
|
"type": "module",
|
|
18
15
|
"bin": {
|
|
19
|
-
"nodoku-gen-component-resolver": "./
|
|
20
|
-
"nodoku-gen-content-schema": "./
|
|
21
|
-
"nodoku-gen-skin-schema": "./
|
|
22
|
-
"nodoku-gen-component-default-theme": "./
|
|
16
|
+
"nodoku-gen-component-resolver": "./esm/bin/generate-component-resolver.js",
|
|
17
|
+
"nodoku-gen-content-schema": "./esm/bin/generate-content-schema.js",
|
|
18
|
+
"nodoku-gen-skin-schema": "./esm/bin/generate-skin-schema.js",
|
|
19
|
+
"nodoku-gen-component-default-theme": "./esm/bin/generate-component-default-theme.js"
|
|
23
20
|
},
|
|
24
21
|
"dependencies": {
|
|
25
22
|
},
|
|
@@ -47,8 +44,5 @@
|
|
|
47
44
|
"react-dom": "^18.3.1",
|
|
48
45
|
"typescript": "^5.5.3",
|
|
49
46
|
"shx": "^0.3.4"
|
|
50
|
-
},
|
|
51
|
-
"scripts": {
|
|
52
|
-
"dist": "shx rm -rf dist && tsc && shx cp -r src/bin/mustache dist/esm/bin/ && shx cp -r schemas dist"
|
|
53
47
|
}
|
|
54
48
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"id": {
|
|
6
|
+
"type": "string"
|
|
7
|
+
},
|
|
8
|
+
"namespace": {
|
|
9
|
+
"type": "string"
|
|
10
|
+
},
|
|
11
|
+
"tags": {
|
|
12
|
+
"type": "array",
|
|
13
|
+
"items": {
|
|
14
|
+
"type": "string"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"attributes": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"additionalProperties": {
|
|
20
|
+
"type": "string"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"additionalProperties": false,
|
|
25
|
+
"additionalItems": false
|
|
26
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import HTMLElement from "node-html-parser/dist/nodes/html";
|
|
2
2
|
export declare class NdContentImage {
|
|
3
|
-
url:
|
|
4
|
-
title?:
|
|
5
|
-
alt?:
|
|
3
|
+
url: NdTranslatableText;
|
|
4
|
+
title?: NdTranslatableText;
|
|
5
|
+
alt?: NdTranslatableText;
|
|
6
6
|
}
|
|
7
|
-
export declare class
|
|
7
|
+
export declare class NdTranslatableText {
|
|
8
8
|
key: string;
|
|
9
9
|
ns: string;
|
|
10
10
|
text: string;
|
|
@@ -12,11 +12,11 @@ export declare class NdTranslatedText {
|
|
|
12
12
|
constructor(ns: string, key?: string, text?: string, excludeFromTranslation?: boolean);
|
|
13
13
|
}
|
|
14
14
|
export declare class NdList {
|
|
15
|
-
items:
|
|
15
|
+
items: NdTranslatableText[];
|
|
16
16
|
ordered: boolean;
|
|
17
17
|
private constructor();
|
|
18
|
-
static createOrdered(items:
|
|
19
|
-
static createUnOrdered(items:
|
|
18
|
+
static createOrdered(items: NdTranslatableText[]): NdList;
|
|
19
|
+
static createUnOrdered(items: NdTranslatableText[]): NdList;
|
|
20
20
|
}
|
|
21
21
|
export declare class NdCode {
|
|
22
22
|
lang: string;
|
|
@@ -32,19 +32,19 @@ export declare class NdContentBlock {
|
|
|
32
32
|
}[];
|
|
33
33
|
tags: string[];
|
|
34
34
|
namespace: string;
|
|
35
|
-
title?:
|
|
36
|
-
subTitle?:
|
|
37
|
-
h3?:
|
|
38
|
-
h4?:
|
|
39
|
-
h5?:
|
|
40
|
-
h6?:
|
|
41
|
-
footer?:
|
|
42
|
-
paragraphs: (
|
|
43
|
-
bgImageUrl?:
|
|
35
|
+
title?: NdTranslatableText;
|
|
36
|
+
subTitle?: NdTranslatableText;
|
|
37
|
+
h3?: NdTranslatableText;
|
|
38
|
+
h4?: NdTranslatableText;
|
|
39
|
+
h5?: NdTranslatableText;
|
|
40
|
+
h6?: NdTranslatableText;
|
|
41
|
+
footer?: NdTranslatableText;
|
|
42
|
+
paragraphs: (NdTranslatableText | NdList | NdCode)[];
|
|
43
|
+
bgImageUrl?: NdTranslatableText;
|
|
44
44
|
images: NdContentImage[];
|
|
45
45
|
htmlElements: {
|
|
46
46
|
htmlElem: HTMLElement;
|
|
47
|
-
translatedText: (
|
|
47
|
+
translatedText: (NdTranslatableText | NdContentImage | NdList | NdCode);
|
|
48
48
|
}[];
|
|
49
49
|
constructor(id: string, ns: string, lng: string);
|
|
50
50
|
getByKey(key: string, ns: string): string | undefined;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { JSX } from "react";
|
|
2
2
|
import { NdComponentDefinition, NdSkinComponentProps } from "../skin/nd-skin";
|
|
3
|
-
import {
|
|
3
|
+
import { NdTranslatableText } from "../content/nd-content";
|
|
4
4
|
export type AsyncFunctionComponent = (props: NdSkinComponentProps) => Promise<JSX.Element>;
|
|
5
|
-
export type
|
|
5
|
+
export type ComponentResolver = (componentName: string) => Promise<{
|
|
6
6
|
compo: AsyncFunctionComponent;
|
|
7
7
|
compoDef: NdComponentDefinition;
|
|
8
8
|
}>;
|
|
9
9
|
export type I18nextProvider = (lng: string) => Promise<{
|
|
10
|
-
t: (text:
|
|
10
|
+
t: (text: NdTranslatableText) => string;
|
|
11
11
|
}>;
|
|
12
12
|
export type ImageUrlProvider = (imageUrl: string) => Promise<string>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ComponentResolver, I18nextProvider, ImageUrlProvider } from "./providers";
|
|
2
2
|
import { NdContentBlock } from "../content/nd-content";
|
|
3
3
|
import { NdPageSkin } from "../skin/nd-skin";
|
|
4
4
|
export declare enum RenderingPriority {
|
|
@@ -7,11 +7,11 @@ export declare enum RenderingPriority {
|
|
|
7
7
|
}
|
|
8
8
|
export declare class RenderingPageProps {
|
|
9
9
|
lng: string;
|
|
10
|
-
renderingPriority: RenderingPriority;
|
|
11
10
|
content: NdContentBlock[];
|
|
12
|
-
componentProvider: ComponentProvider | undefined;
|
|
13
11
|
skin: NdPageSkin | undefined;
|
|
12
|
+
renderingPriority: RenderingPriority;
|
|
13
|
+
componentResolver: ComponentResolver | undefined;
|
|
14
14
|
imageUrlProvider: ImageUrlProvider | undefined;
|
|
15
15
|
i18nextProvider: I18nextProvider | undefined;
|
|
16
|
-
constructor(lng: string,
|
|
16
|
+
constructor(lng: string, content: NdContentBlock[], componentResolver: ComponentResolver | undefined, skin?: NdPageSkin | undefined, renderingPriority?: RenderingPriority, imageUrlProvider?: ImageUrlProvider | undefined, i18nextProvider?: I18nextProvider | undefined);
|
|
17
17
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NdContentImage,
|
|
1
|
+
import { NdContentImage, NdTranslatableText, NdList, NdCode, NdContentBlock } from "./content/nd-content";
|
|
2
2
|
import { NdSkinComponent, NdRow, NdPageSkin, NdSkinComponentProps, NdContentSelector, NdComponentDefinition, NdThemeHierarchy, NdDefaultThemeName } from "./skin/nd-skin";
|
|
3
3
|
import { RenderingPageProps, RenderingPriority } from "./core/rendering-page-props";
|
|
4
4
|
import { RenderingPage } from "./core/rendering-page";
|
|
@@ -6,7 +6,7 @@ import { I18nextProvider, AsyncFunctionComponent, ImageUrlProvider } from "./cor
|
|
|
6
6
|
import { mergeTheme } from "./theme-utils/theme-merger";
|
|
7
7
|
import { ThemeStyle } from "./theme-utils/theme-style";
|
|
8
8
|
import { ExtendedThemeStyle } from "./theme-utils/extended-theme-style";
|
|
9
|
-
export { NdContentImage,
|
|
9
|
+
export { NdContentImage, NdTranslatableText, NdList, NdCode, NdContentBlock, NdSkinComponent, NdRow, NdPageSkin, NdSkinComponentProps, NdContentSelector, NdComponentDefinition, NdThemeHierarchy, type NdDefaultThemeName };
|
|
10
10
|
export { RenderingPageProps, RenderingPriority, RenderingPage };
|
|
11
11
|
export { mergeTheme, ThemeStyle, ExtendedThemeStyle };
|
|
12
12
|
export type { I18nextProvider, AsyncFunctionComponent, ImageUrlProvider };
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 nodoku
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.MD
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
nodoku-core is a foundation library for the nodoku static site generator,
|
|
2
|
-
a Node JS - React based framework for fast page prototyping using yaml files as content and page config
|
|
3
|
-
The site in Nodoku is composed of two yaml files - visual and content.
|
|
4
|
-
|
|
5
|
-
# getting started
|
|
6
|
-
|
|
7
|
-
in order to use nodoku one needs to install the nodoku-core library (this one)
|
|
8
|
-
and at least one component library for nodoku (for example, nodoku-flowbite)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
```shell
|
|
12
|
-
npm install nodoku-core nodoku-flowbite
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Then the rendering component would be as follows:
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
<RenderingPage
|
|
19
|
-
pageName={"main"}
|
|
20
|
-
lng={lng}
|
|
21
|
-
contentYamlProvider={contentYamlProvider}
|
|
22
|
-
visualYamlProvider={visualYamlProvider}
|
|
23
|
-
i18nextProvider={i18nextProvider}
|
|
24
|
-
componentProvider={defaultComponentProvider}
|
|
25
|
-
/>
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
where:
|
|
29
|
-
- **_pageName_**: the name of the page to be rendered. This name is given to the visualYamlProvider funtion to fetch the required page layout yaml file
|
|
30
|
-
|
|
31
|
-
- **_lng_**: the page language for localization. This parameter is given further to the contentYamlProvider to fetch the content on the given language
|
|
32
|
-
|
|
33
|
-
- **_contentYamlProvider_**: function providing the textual content for the page. This function is expected to fetch the content yaml file and return its content as text for the further processing. the function signature is the following: ```(lng: string, ns: string) => Promise<string>```
|
|
34
|
-
|
|
35
|
-
- **_visualYamlProvider_**: function providing the content of a yaml file that is used to render the page - the page structure yaml file. This function is expected to fetch the content yaml file and return its content as text for the further processing. the function signature is the following: ```(pageName: string) => Promise<string>```
|
|
36
|
-
|
|
37
|
-
- **_i18nextProvider_**: the page localization provider. The signature is the following: ```(lng: string) => Promise<{t: (key: string, ns: string) => string}>```. For a given language the localization provider is supposed to return a function, that would provide the value for a given key and namespace
|
|
38
|
-
|
|
39
|
-
- **_componentProvider_**: the function returning an actual implementation of the component, given its name, as specified in the page structure - visual yaml file. The signature is as follows: ```(componentName: string) => Promise<AsyncFunctionComponent>```, where AsyncFunctionComponent is the following function: ```(props: LbComponentProps) => Promise<JSX.Element>```
|
|
40
|
-
|
|
41
|
-
# generation scripts
|
|
42
|
-
to simplify the development, the nodoku-core provides the following scripts, that are used to generate component resolver, content schema and visual schema, by scanning the **node_modules** folder of the project
|
|
43
|
-
- **nodoku-gen-component-resolver**: generates the component resolver by scanning node_modules and searching for nodoku component libraries - the libraries providing the nodoku.manifest.json file
|
|
44
|
-
- **nodoku-gen-content-schema**: generates the json schema file that can be used to validate the **content** yaml file
|
|
45
|
-
- **nodoku-gen-visual-schema**: generates the json schema file thate can be used to validate the **visual** page yaml file
|
|
46
|
-
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export var RenderingPriority;
|
|
2
|
-
(function (RenderingPriority) {
|
|
3
|
-
RenderingPriority[RenderingPriority["content_first"] = 0] = "content_first";
|
|
4
|
-
RenderingPriority[RenderingPriority["skin_first"] = 1] = "skin_first";
|
|
5
|
-
})(RenderingPriority || (RenderingPriority = {}));
|
|
6
|
-
export class RenderingPageProps {
|
|
7
|
-
lng;
|
|
8
|
-
renderingPriority;
|
|
9
|
-
content;
|
|
10
|
-
componentProvider;
|
|
11
|
-
skin;
|
|
12
|
-
imageUrlProvider = undefined;
|
|
13
|
-
i18nextProvider = undefined;
|
|
14
|
-
constructor(lng, renderingPriority = RenderingPriority.content_first, content, componentProvider, skin, imageUrlProvider, i18nextProvider) {
|
|
15
|
-
this.lng = lng;
|
|
16
|
-
this.renderingPriority = renderingPriority;
|
|
17
|
-
this.content = content;
|
|
18
|
-
this.componentProvider = componentProvider;
|
|
19
|
-
this.skin = skin;
|
|
20
|
-
this.imageUrlProvider = imageUrlProvider;
|
|
21
|
-
this.i18nextProvider = i18nextProvider;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|