@griddo/cx 11.11.8-rc.1 → 11.12.0
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/build/commands/end-render.js +5 -5
- package/build/commands/end-render.js.map +4 -4
- package/build/commands/prepare-assets-directory.js +3 -3
- package/build/commands/prepare-assets-directory.js.map +4 -4
- package/build/commands/prepare-domains-render.js +9 -9
- package/build/commands/prepare-domains-render.js.map +4 -4
- package/build/commands/reset-render.js +8 -8
- package/build/commands/reset-render.js.map +4 -4
- package/build/commands/start-render.js +35 -33
- package/build/commands/start-render.js.map +4 -4
- package/build/commands/upload-search-content.js +6 -6
- package/build/commands/upload-search-content.js.map +4 -4
- package/build/core/paths.d.ts +2 -0
- package/build/index.js +25 -23
- package/build/services/generate-md.d.ts +8 -0
- package/build/services/llms.d.ts +2 -2
- package/build/shared/brush.d.ts +6 -0
- package/build/shared/context.d.ts +1 -0
- package/build/shared/envs.d.ts +2 -1
- package/build/shared/load-config.d.ts +16 -0
- package/build/ssg-adapters/gatsby/actions/index.d.ts +2 -0
- package/build/ssg-adapters/gatsby/actions/llms.d.ts +2 -0
- package/build/ssg-adapters/gatsby/shared/extract-assets.d.ts +4 -1
- package/cli.mjs +8 -0
- package/exporter/build.sh +4 -5
- package/exporter/core/GriddoLog.ts +1 -1
- package/exporter/core/check-env-health.ts +1 -1
- package/exporter/core/errors.ts +1 -1
- package/exporter/core/life-cycle.ts +1 -1
- package/exporter/core/paths.ts +3 -0
- package/exporter/core/print-logos.ts +1 -1
- package/exporter/services/api.ts +1 -1
- package/exporter/services/generate-md.ts +151 -0
- package/exporter/services/llms.ts +16 -12
- package/exporter/services/render.ts +1 -1
- package/exporter/services/store.ts +1 -1
- package/exporter/shared/brush.ts +30 -0
- package/exporter/shared/context.ts +1 -0
- package/exporter/shared/envs.ts +2 -0
- package/exporter/shared/load-config.ts +164 -0
- package/exporter/shared/npm-modules/README.md +0 -1
- package/exporter/ssg-adapters/gatsby/actions/index.ts +2 -0
- package/exporter/ssg-adapters/gatsby/actions/llms.ts +11 -0
- package/exporter/ssg-adapters/gatsby/actions/meta.ts +0 -2
- package/exporter/ssg-adapters/gatsby/actions/relocation.ts +5 -3
- package/exporter/ssg-adapters/gatsby/actions/sync.ts +5 -3
- package/exporter/ssg-adapters/gatsby/index.ts +2 -3
- package/exporter/ssg-adapters/gatsby/shared/extract-assets.ts +16 -21
- package/exporter/ssg-adapters/gatsby/shared/sync-render.ts +37 -10
- package/package.json +6 -4
- package/tsconfig.exporter.json +2 -2
- package/build/shared/npm-modules/brush.d.ts +0 -18
- package/exporter/commands/generate-md.noop +0 -109
- package/exporter/shared/npm-modules/brush.ts +0 -39
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { RenderContext } from "@shared/context";
|
|
2
2
|
|
|
3
|
-
import { generateLLMs } from "@services/llms";
|
|
4
3
|
import { generateRobots } from "@services/robots";
|
|
5
4
|
import { generateSitemaps } from "@services/sitemaps";
|
|
6
5
|
|
|
@@ -9,5 +8,4 @@ export async function metaAction(context: RenderContext) {
|
|
|
9
8
|
|
|
10
9
|
await generateSitemaps(domain);
|
|
11
10
|
await generateRobots(domain);
|
|
12
|
-
await generateLLMs(domain);
|
|
13
11
|
}
|
|
@@ -8,8 +8,10 @@ export async function relocationAction(context: RenderContext) {
|
|
|
8
8
|
pathsHydratedWithDomain: { __root, __ssg },
|
|
9
9
|
} = context;
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
const
|
|
11
|
+
const gatsbyWorkingDir = path.join(__ssg, "public");
|
|
12
|
+
const workingDistDir = path.join(__root, "current-dist");
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
context.workingDistDir = workingDistDir;
|
|
15
|
+
|
|
16
|
+
await fsp.rename(gatsbyWorkingDir, workingDistDir);
|
|
15
17
|
}
|
|
@@ -25,8 +25,10 @@ export async function syncAction(context: RenderContext<SSG>) {
|
|
|
25
25
|
const previousDist = path.join(__exports, "dist");
|
|
26
26
|
|
|
27
27
|
// caching...
|
|
28
|
-
await
|
|
29
|
-
|
|
28
|
+
await Promise.all([
|
|
29
|
+
mvDirs(__root, __cache, renderArtifacts.cacheables, { override: true }),
|
|
30
|
+
mvDirs(__ssg, __cache, ssgArtifacts.cacheables, { override: true }),
|
|
31
|
+
]);
|
|
30
32
|
|
|
31
33
|
if (renderMode === RENDER_MODE.FROM_SCRATCH) {
|
|
32
34
|
await deleteDisposableSiteDirs(currentDist);
|
|
@@ -57,7 +59,7 @@ export async function syncAction(context: RenderContext<SSG>) {
|
|
|
57
59
|
|
|
58
60
|
if (needsAssetPrefix) {
|
|
59
61
|
// TODO: Mejorar performance
|
|
60
|
-
await extractAssetsFromDist(domain);
|
|
62
|
+
await extractAssetsFromDist(domain, { root: __root, exports: __exports });
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
// rsync assets
|
|
@@ -109,10 +109,9 @@ export async function gatsbyRenderDomain(domain: string) {
|
|
|
109
109
|
|
|
110
110
|
await doLifeCycle("Data", async () => actions.data(context));
|
|
111
111
|
await doLifeCycle("SSG", async () => actions.ssg(context), { skip: isDryRender });
|
|
112
|
-
await doLifeCycle("Relocation", async () => actions.relocation(context), {
|
|
113
|
-
skip: isDryRender,
|
|
114
|
-
});
|
|
112
|
+
await doLifeCycle("Relocation", async () => actions.relocation(context), { skip: isDryRender });
|
|
115
113
|
await doLifeCycle("Meta", async () => actions.meta(context), { skip: isDryRender });
|
|
114
|
+
await doLifeCycle("LLMS", async () => actions.llms(context), { skip: isDryRender });
|
|
116
115
|
await doLifeCycle("Report", async () => actions.report(context));
|
|
117
116
|
await doLifeCycle("DryRunSync", async () => actions.dryRenderSync(context), {
|
|
118
117
|
skip: isWetRender,
|
|
@@ -2,18 +2,17 @@ import fsp from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
4
|
import { pathExists } from "../../../core/fs";
|
|
5
|
-
import { getRenderPathsHydratedWithDomainFromDB } from "../../../services/render";
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Update the Griddo's `/dist` dir with the contents from `public` dir only
|
|
9
8
|
* with files of type: js, json and css.
|
|
10
9
|
* TODO: Explicar que el static se copia a assets porque el js va en el subdominio de assets.
|
|
11
10
|
*/
|
|
12
|
-
async function extractAssetsFromDist(domain: string) {
|
|
13
|
-
const {
|
|
11
|
+
async function extractAssetsFromDist(domain: string, dirs: { root: string; exports: string }) {
|
|
12
|
+
const { exports, root } = dirs;
|
|
14
13
|
|
|
15
14
|
// Archivos (no carpetas) válidos de public
|
|
16
|
-
const filesFromDist = (await fsp.readdir(path.join(
|
|
15
|
+
const filesFromDist = (await fsp.readdir(path.join(exports, "dist"))).filter(
|
|
17
16
|
(file) =>
|
|
18
17
|
path.extname(file) === ".js" ||
|
|
19
18
|
path.extname(file) === ".json" ||
|
|
@@ -21,35 +20,31 @@ async function extractAssetsFromDist(domain: string) {
|
|
|
21
20
|
);
|
|
22
21
|
|
|
23
22
|
// Creamos assets si es necesario (needsAssetPrefix)
|
|
24
|
-
await fsp.mkdir(path.join(
|
|
23
|
+
await fsp.mkdir(path.join(root, "assets"), { recursive: true });
|
|
25
24
|
// page-data folder
|
|
26
|
-
await fsp.cp(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
preserveTimestamps: true,
|
|
31
|
-
recursive: true,
|
|
32
|
-
},
|
|
33
|
-
);
|
|
25
|
+
await fsp.cp(path.join(exports, "dist", "page-data"), path.join(root, "assets", "page-data"), {
|
|
26
|
+
preserveTimestamps: true,
|
|
27
|
+
recursive: true,
|
|
28
|
+
});
|
|
34
29
|
// static folder si existe
|
|
35
|
-
if (await pathExists(path.join(
|
|
36
|
-
await fsp.cp(path.join(
|
|
30
|
+
if (await pathExists(path.join(root, "static"))) {
|
|
31
|
+
await fsp.cp(path.join(root, "static"), path.join(root, "assets"), {
|
|
37
32
|
force: false,
|
|
38
33
|
preserveTimestamps: true,
|
|
39
34
|
recursive: true,
|
|
40
35
|
});
|
|
41
36
|
}
|
|
42
37
|
// dist/static -> assets/static
|
|
43
|
-
if (await pathExists(path.join(
|
|
44
|
-
await fsp.cp(path.join(
|
|
38
|
+
if (await pathExists(path.join(exports, "dist", "static"))) {
|
|
39
|
+
await fsp.cp(path.join(exports, "dist", "static"), path.join(root, "assets", "static"), {
|
|
45
40
|
force: false,
|
|
46
41
|
preserveTimestamps: true,
|
|
47
42
|
recursive: true,
|
|
48
43
|
});
|
|
49
44
|
}
|
|
50
45
|
// otro static...
|
|
51
|
-
if (await pathExists(path.join(
|
|
52
|
-
await fsp.cp(path.join(
|
|
46
|
+
if (await pathExists(path.join(root, "static"))) {
|
|
47
|
+
await fsp.cp(path.join(root, "static"), path.join(exports, "dist", domain), {
|
|
53
48
|
preserveTimestamps: true,
|
|
54
49
|
recursive: true,
|
|
55
50
|
force: false,
|
|
@@ -64,8 +59,8 @@ async function extractAssetsFromDist(domain: string) {
|
|
|
64
59
|
// }
|
|
65
60
|
|
|
66
61
|
const arraysOfPromises: Promise<void>[] = filesFromDist.map((file) => {
|
|
67
|
-
const fileSrc = path.join(
|
|
68
|
-
const fileDest = path.join(
|
|
62
|
+
const fileSrc = path.join(exports, "dist", file);
|
|
63
|
+
const fileDest = path.join(root, "assets", file);
|
|
69
64
|
return fsp.cp(fileSrc, fileDest, { preserveTimestamps: true, recursive: true });
|
|
70
65
|
});
|
|
71
66
|
|
|
@@ -3,9 +3,10 @@ import path from "node:path";
|
|
|
3
3
|
|
|
4
4
|
import pLimit from "p-limit";
|
|
5
5
|
|
|
6
|
-
import { findFilesBySuffix } from "../../../core/fs";
|
|
6
|
+
import { findFilesBySuffix, pathExists } from "../../../core/fs";
|
|
7
7
|
import { GriddoLog } from "../../../core/GriddoLog";
|
|
8
8
|
import { addLogToBuffer } from "../../../core/logger";
|
|
9
|
+
import { removeTrailingSlash } from "../../../core/paths";
|
|
9
10
|
import { GRIDDO_SSG_BUNDLE_ANALYZER } from "../../../shared/envs";
|
|
10
11
|
import { getAssetsDiffBetweenRenders, patchHtmlFile } from "./diff-assets";
|
|
11
12
|
|
|
@@ -21,16 +22,19 @@ interface CopyFilePath {
|
|
|
21
22
|
to: string;
|
|
22
23
|
}
|
|
23
24
|
interface SyncState {
|
|
25
|
+
mdToAdd: CopyFilePath[];
|
|
24
26
|
htmlToAdd: CopyFilePath[];
|
|
25
27
|
jsonToAdd: CopyFilePath[];
|
|
26
28
|
htmlToDelete: string[];
|
|
27
29
|
jsonToDelete: string[];
|
|
30
|
+
mdToDelete: string[];
|
|
28
31
|
}
|
|
29
32
|
interface PageInfo {
|
|
30
33
|
id: number;
|
|
31
34
|
composePath: string; // p.ej. '/about-us' o '/'
|
|
32
35
|
htmlPath: string; // p.ej. '/path/to/public/about-us/index.html'
|
|
33
36
|
jsonPath: string; // p.ej. '/path/to/public/page-data/about-us/page-data.json'
|
|
37
|
+
mdPath: string; // p.ej. '/path/to/public/about-us.md'
|
|
34
38
|
}
|
|
35
39
|
interface GatsbyPageData {
|
|
36
40
|
result: {
|
|
@@ -56,10 +60,12 @@ class SyncRender {
|
|
|
56
60
|
private assetArtifacts: string[];
|
|
57
61
|
|
|
58
62
|
private state: SyncState = {
|
|
63
|
+
mdToAdd: [],
|
|
59
64
|
htmlToAdd: [],
|
|
60
65
|
jsonToAdd: [],
|
|
61
66
|
htmlToDelete: [],
|
|
62
67
|
jsonToDelete: [],
|
|
68
|
+
mdToDelete: [],
|
|
63
69
|
};
|
|
64
70
|
|
|
65
71
|
constructor(config: SyncRenderConfig) {
|
|
@@ -91,17 +97,18 @@ class SyncRender {
|
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
private async setPagesToDelete() {
|
|
100
|
+
// -------------------------------------------------------
|
|
94
101
|
// INCLUIMOS LAS PÁGINAS A CREAR EN LAS CANDIDATAS A BORRAR
|
|
95
|
-
//
|
|
102
|
+
// -------------------------------------------------------
|
|
96
103
|
// El set de ids incluye tanto las páginas a borrar como las que se van
|
|
97
104
|
// a crear para manejar correctamente los cambios de slug.
|
|
98
105
|
//
|
|
99
|
-
// Ejemplo: Si la página `id=3` tiene slug
|
|
100
|
-
// `slug=about-us`, necesitamos borrar la página `id=3` del render
|
|
101
|
-
// y volver a crearla con la nueva ruta.
|
|
106
|
+
// Ejemplo: Si la página `id=3` tiene `slug=about` y después viene con
|
|
107
|
+
// `slug=about-us`, necesitamos borrar la página `id=3` del render
|
|
108
|
+
// previo y volver a crearla con la nueva ruta.
|
|
102
109
|
//
|
|
103
|
-
// ¿Por qué? Porque el slug determina dónde se guarda la página:
|
|
104
|
-
//
|
|
110
|
+
// ¿Por qué? Porque el slug determina dónde se guarda la página: -
|
|
111
|
+
// /about/index.html -> /about-us/index.html
|
|
105
112
|
//
|
|
106
113
|
// Si no la borrásemos previamente, tendríamos ambas páginas:
|
|
107
114
|
// `/about/index.html` y `/about-us/index.html`
|
|
@@ -112,10 +119,12 @@ class SyncRender {
|
|
|
112
119
|
if (candidateIdsToDelete.has(page.id)) {
|
|
113
120
|
this.state.htmlToDelete.push(page.htmlPath);
|
|
114
121
|
this.state.jsonToDelete.push(page.jsonPath);
|
|
122
|
+
this.state.mdToDelete.push(page.mdPath);
|
|
115
123
|
}
|
|
116
124
|
}
|
|
117
125
|
|
|
118
126
|
GriddoLog.verbose(`${this.state.htmlToDelete.length} pages HTML to delete`);
|
|
127
|
+
GriddoLog.verbose(`${this.state.mdToDelete.length} pages Markdown to delete`);
|
|
119
128
|
GriddoLog.verbose(`${this.state.jsonToDelete.length} pages JSON to delete`);
|
|
120
129
|
}
|
|
121
130
|
|
|
@@ -126,11 +135,23 @@ class SyncRender {
|
|
|
126
135
|
for (const page of newPages) {
|
|
127
136
|
if (candidateIdsToCreate.has(page.id)) {
|
|
128
137
|
const htmlTo = path.join(this.bundleDir, page.composePath, "index.html");
|
|
138
|
+
const mdTo = path.join(this.bundleDir, `${page.composePath}.md`);
|
|
139
|
+
|
|
140
|
+
// El page-data.json del índice principal tiene como slug solo
|
|
141
|
+
// la barra (`/`) por eso gatsby lo guarda en el directorio
|
|
142
|
+
// `index` de forma "reservada".
|
|
143
|
+
// Ejemplos
|
|
144
|
+
// ../page-data/about-us/page-data.json // página con slug
|
|
145
|
+
// ../page-data/programs/page-data.json // página con slug
|
|
146
|
+
// ../page-data/index/page-data.json // <---- ¡página root index!
|
|
129
147
|
const normalizedCompose = page.composePath === "/" ? "index" : page.composePath;
|
|
130
148
|
const jsonTo = path.join(this.bundleDir, "page-data", normalizedCompose, "page-data.json");
|
|
131
149
|
|
|
132
150
|
this.state.htmlToAdd.push({ from: page.htmlPath, to: htmlTo });
|
|
133
151
|
this.state.jsonToAdd.push({ from: page.jsonPath, to: jsonTo });
|
|
152
|
+
if (await pathExists(page.mdPath)) {
|
|
153
|
+
this.state.mdToAdd.push({ from: page.mdPath, to: mdTo });
|
|
154
|
+
}
|
|
134
155
|
}
|
|
135
156
|
}
|
|
136
157
|
|
|
@@ -140,7 +161,11 @@ class SyncRender {
|
|
|
140
161
|
|
|
141
162
|
private async sync() {
|
|
142
163
|
// Delete...
|
|
143
|
-
const allFilesToDelete = [
|
|
164
|
+
const allFilesToDelete = [
|
|
165
|
+
...this.state.htmlToDelete,
|
|
166
|
+
...this.state.jsonToDelete,
|
|
167
|
+
...this.state.mdToDelete,
|
|
168
|
+
];
|
|
144
169
|
for (const file of allFilesToDelete) {
|
|
145
170
|
try {
|
|
146
171
|
// Usar `force: true` para no fallar si el archivo ya no existe.
|
|
@@ -155,7 +180,7 @@ class SyncRender {
|
|
|
155
180
|
await this.restoreWebpackCompilationHash();
|
|
156
181
|
|
|
157
182
|
// Copy...
|
|
158
|
-
const allFilesToAdd = [...this.state.htmlToAdd, ...this.state.jsonToAdd];
|
|
183
|
+
const allFilesToAdd = [...this.state.htmlToAdd, ...this.state.jsonToAdd, ...this.state.mdToAdd];
|
|
159
184
|
for (const file of allFilesToAdd) {
|
|
160
185
|
try {
|
|
161
186
|
await fsp.mkdir(path.dirname(file.to), { recursive: true });
|
|
@@ -267,6 +292,7 @@ class SyncRender {
|
|
|
267
292
|
path.join(dir, "page-data"),
|
|
268
293
|
"page-data.json",
|
|
269
294
|
);
|
|
295
|
+
|
|
270
296
|
const processingPromises: Promise<PageInfo | null>[] = [];
|
|
271
297
|
for await (const file of gatsbyPageDataGenerator) {
|
|
272
298
|
processingPromises.push(
|
|
@@ -276,12 +302,13 @@ class SyncRender {
|
|
|
276
302
|
const content = JSON.parse(fileContent) as GatsbyPageData;
|
|
277
303
|
|
|
278
304
|
const id = content.result.pageContext.id;
|
|
279
|
-
const composePath = content.result.pageContext.fullPath.compose;
|
|
305
|
+
const composePath = removeTrailingSlash(content.result.pageContext.fullPath.compose);
|
|
280
306
|
|
|
281
307
|
return {
|
|
282
308
|
id,
|
|
283
309
|
composePath,
|
|
284
310
|
htmlPath: path.join(dir, composePath, "index.html"),
|
|
311
|
+
mdPath: path.join(dir, `${composePath}.md`),
|
|
285
312
|
jsonPath: file,
|
|
286
313
|
};
|
|
287
314
|
} catch (e) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/cx",
|
|
3
3
|
"description": "Griddo SSG based on Gatsby",
|
|
4
|
-
"version": "11.
|
|
4
|
+
"version": "11.12.0",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Hisco <francis.vega@griddo.io>"
|
|
7
7
|
],
|
|
@@ -56,12 +56,14 @@
|
|
|
56
56
|
"watch:ts-lint": "tsc --noEmit --watch"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
+
"@kreuzberg/html-to-markdown": "2.24.5",
|
|
59
60
|
"gatsby": "5.15.0",
|
|
60
|
-
"html-react-parser": "5.2.11"
|
|
61
|
+
"html-react-parser": "5.2.11",
|
|
62
|
+
"jiti": "^2.6.1"
|
|
61
63
|
},
|
|
62
64
|
"devDependencies": {
|
|
63
65
|
"@biomejs/biome": "2.3.4",
|
|
64
|
-
"@griddo/core": "11.
|
|
66
|
+
"@griddo/core": "11.12.0",
|
|
65
67
|
"@types/node": "20.19.4",
|
|
66
68
|
"@typescript/native-preview": "7.0.0-dev.20260108.1",
|
|
67
69
|
"cheerio": "1.1.2",
|
|
@@ -94,5 +96,5 @@
|
|
|
94
96
|
"publishConfig": {
|
|
95
97
|
"access": "public"
|
|
96
98
|
},
|
|
97
|
-
"gitHead": "
|
|
99
|
+
"gitHead": "47dd37fe46a7bb09187b0c475c4ece29a6abc289"
|
|
98
100
|
}
|
package/tsconfig.exporter.json
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"target": "es2022",
|
|
4
4
|
"lib": ["dom", "esnext"],
|
|
5
5
|
"jsx": "react-jsx",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"moduleResolution": "NodeNext",
|
|
7
|
+
"module": "NodeNext",
|
|
8
8
|
"esModuleInterop": true,
|
|
9
9
|
"forceConsistentCasingInFileNames": true,
|
|
10
10
|
"strict": true,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
declare const CODES: {
|
|
2
|
-
readonly black: "\u001B[30m";
|
|
3
|
-
readonly red: "\u001B[31m";
|
|
4
|
-
readonly green: "\u001B[32m";
|
|
5
|
-
readonly yellow: "\u001B[33m";
|
|
6
|
-
readonly blue: "\u001B[34m";
|
|
7
|
-
readonly magenta: "\u001B[35m";
|
|
8
|
-
readonly cyan: "\u001B[36m";
|
|
9
|
-
readonly white: "\u001B[37m";
|
|
10
|
-
readonly gray: "\u001B[90m";
|
|
11
|
-
readonly bold: "\u001B[1m";
|
|
12
|
-
readonly dim: "\u001B[2m";
|
|
13
|
-
};
|
|
14
|
-
type ColorFunction = (text: string | number) => string;
|
|
15
|
-
type ColorName = keyof typeof CODES;
|
|
16
|
-
type Brush = Record<ColorName, ColorFunction>;
|
|
17
|
-
declare const brush: Brush;
|
|
18
|
-
export { brush };
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import fsp from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
import TurndownService from "turndown";
|
|
5
|
-
|
|
6
|
-
// import { gfm } from "turndown-plugin-gfm";
|
|
7
|
-
|
|
8
|
-
import { throwError, withErrorHandler } from "../core/errors";
|
|
9
|
-
import { GriddoLog } from "../core/GriddoLog";
|
|
10
|
-
import { getRenderPathsHydratedWithDomainFromDB } from "../services/render";
|
|
11
|
-
import { ReadFromStoreError } from "../shared/errors";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Converts HTML to Markdown.
|
|
15
|
-
* @param html - The HTML content to convert.
|
|
16
|
-
* @returns The Markdown content.
|
|
17
|
-
*/
|
|
18
|
-
function htmlToMarkdown(html: string): string {
|
|
19
|
-
const turndown = new TurndownService({
|
|
20
|
-
headingStyle: "atx",
|
|
21
|
-
codeBlockStyle: "fenced",
|
|
22
|
-
bulletListMarker: "-",
|
|
23
|
-
emDelimiter: "*",
|
|
24
|
-
strongDelimiter: "**",
|
|
25
|
-
linkStyle: "inlined", // evita ruido
|
|
26
|
-
hr: "---",
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// añade soporte GitHub-like
|
|
30
|
-
// turndown.use(gfm);
|
|
31
|
-
|
|
32
|
-
// elimina tags que hacen ruido para LLMs
|
|
33
|
-
turndown.remove([
|
|
34
|
-
"style",
|
|
35
|
-
"script",
|
|
36
|
-
"noscript",
|
|
37
|
-
"iframe",
|
|
38
|
-
"form",
|
|
39
|
-
"input",
|
|
40
|
-
"button",
|
|
41
|
-
"nav",
|
|
42
|
-
"footer",
|
|
43
|
-
"object",
|
|
44
|
-
]);
|
|
45
|
-
|
|
46
|
-
let md = turndown.turndown(html);
|
|
47
|
-
|
|
48
|
-
md = md
|
|
49
|
-
.replace(/ /g, " ")
|
|
50
|
-
.replace(/&/g, "&")
|
|
51
|
-
.replace(/\n{3,}/g, "\n\n") // compacta saltos
|
|
52
|
-
.trim();
|
|
53
|
-
|
|
54
|
-
return md;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Walk recursively in a basePath and return an array of pages with json
|
|
59
|
-
* extension with the full absolute path and the path includes "page-data".
|
|
60
|
-
*
|
|
61
|
-
* @param basePath The path to walk recursively.
|
|
62
|
-
* @returns An array of pages with json extension with the full absolute path
|
|
63
|
-
* and the path includes "page-data".
|
|
64
|
-
*/
|
|
65
|
-
async function* walkRecursively(basePath: string): AsyncGenerator<string> {
|
|
66
|
-
const filesHandle = await fsp.opendir(basePath);
|
|
67
|
-
|
|
68
|
-
for await (const fileDirent of filesHandle) {
|
|
69
|
-
if (fileDirent.isDirectory()) {
|
|
70
|
-
yield* walkRecursively(path.join(basePath, fileDirent.name));
|
|
71
|
-
} else if (fileDirent.isFile() && path.extname(fileDirent.name) === ".html") {
|
|
72
|
-
yield path.join(basePath, fileDirent.name);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function* getPageDataPagesFromExports(
|
|
78
|
-
basePath: string,
|
|
79
|
-
): AsyncGenerator<{ path: string; content: string }> {
|
|
80
|
-
const jsonFiles = walkRecursively(basePath);
|
|
81
|
-
|
|
82
|
-
for await (const filePath of jsonFiles) {
|
|
83
|
-
try {
|
|
84
|
-
const fileContent = await fsp.readFile(filePath, "utf8");
|
|
85
|
-
const content = htmlToMarkdown(fileContent);
|
|
86
|
-
yield { path: filePath, content };
|
|
87
|
-
} catch (error) {
|
|
88
|
-
throwError(ReadFromStoreError, error);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async function generateMD() {
|
|
94
|
-
const [domain] = process.argv.slice(2);
|
|
95
|
-
const { __exports } = await getRenderPathsHydratedWithDomainFromDB({ domain });
|
|
96
|
-
|
|
97
|
-
const pages = getPageDataPagesFromExports(path.join(__exports, "dist"));
|
|
98
|
-
|
|
99
|
-
for await (const page of pages) {
|
|
100
|
-
await fsp.writeFile(path.join(page.path.replace(".html", ".md")), page.content);
|
|
101
|
-
GriddoLog.info(`Generating MD for a ${page.path}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async function main() {
|
|
106
|
-
await generateMD();
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
withErrorHandler(main);
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Brush adds color to a string|number, it does not print it!
|
|
3
|
-
// Its simple, no log, no chains, just color in a string|number
|
|
4
|
-
// usage:
|
|
5
|
-
// console.log(brush.green("sucess!"))
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
// This is a global variable to check if the code is running in a CI environment
|
|
9
|
-
// TODO: Temporarily set to true to avoid color in CI environment
|
|
10
|
-
const NO_COLORS = process.env.NO_COLORS;
|
|
11
|
-
|
|
12
|
-
const RESET = "\x1b[0m";
|
|
13
|
-
const CODES = {
|
|
14
|
-
black: "\x1b[30m",
|
|
15
|
-
red: "\x1b[31m",
|
|
16
|
-
green: "\x1b[32m",
|
|
17
|
-
yellow: "\x1b[33m",
|
|
18
|
-
blue: "\x1b[34m",
|
|
19
|
-
magenta: "\x1b[35m",
|
|
20
|
-
cyan: "\x1b[36m",
|
|
21
|
-
white: "\x1b[37m",
|
|
22
|
-
gray: "\x1b[90m",
|
|
23
|
-
bold: "\x1b[1m",
|
|
24
|
-
dim: "\x1b[2m",
|
|
25
|
-
} as const;
|
|
26
|
-
|
|
27
|
-
type ColorFunction = (text: string | number) => string;
|
|
28
|
-
type ColorName = keyof typeof CODES;
|
|
29
|
-
type Brush = Record<ColorName, ColorFunction>;
|
|
30
|
-
|
|
31
|
-
const brush = {} as Brush;
|
|
32
|
-
|
|
33
|
-
for (const color in CODES) {
|
|
34
|
-
const key = color as ColorName;
|
|
35
|
-
brush[key] = (text: string | number) =>
|
|
36
|
-
NO_COLORS ? (text as string).toString() : `${CODES[key]}${text}${RESET}`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export { brush };
|