@primate/markdown 0.1.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/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Markdown
2
+
3
+ This handler serves Markdown components with the `md` file extension.
4
+
5
+ ## [Documentation](https://primatejs.com/modules/markdown)
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@primate/markdown",
3
+ "version": "0.1.0",
4
+ "description": "Primate Markdown module",
5
+ "homepage": "https://primatejs.com/modules/markdown",
6
+ "bugs": "https://github.com/primatejs/primate/issues",
7
+ "license": "MIT",
8
+ "files": [
9
+ "src/**/*.js",
10
+ "src/errors.json",
11
+ "!src/**/*.spec.js"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/primatejs/primate",
16
+ "directory": "packages/markdown"
17
+ },
18
+ "dependencies": {
19
+ "marked": "^7.0.4",
20
+ "runtime-compat": "^0.25.7"
21
+ },
22
+ "peerDependencies": {
23
+ "primate": "0.22"
24
+ },
25
+ "type": "module",
26
+ "exports": "./src/exports.js"
27
+ }
package/src/compile.js ADDED
@@ -0,0 +1,39 @@
1
+ import {marked} from "marked";
2
+
3
+ const identity_heading = (text, level) => `<h${level}>${text}</h${level}>`;
4
+
5
+ export default async ({
6
+ app,
7
+ directory,
8
+ options,
9
+ }) => {
10
+ const {location} = app.config;
11
+ const monkeyed_heading = options?.renderer?.heading ?? identity_heading;
12
+ const source = app.runpath(directory);
13
+ const target = app.runpath(location.server, directory);
14
+ await target.file.create();
15
+
16
+ return async (filename, input) => {
17
+ const toc = [];
18
+ const renderer = {
19
+ ...options?.renderer ?? {},
20
+ heading(text, level) {
21
+ const name = text.toLowerCase().replaceAll(/[?{}%]/gu, "");
22
+ toc.push({level, text, name});
23
+ return monkeyed_heading(text, level);
24
+ },
25
+ };
26
+ marked.use({
27
+ ...options,
28
+ renderer,
29
+ });
30
+
31
+ const content = marked.parse(input);
32
+ const html = target.join(`${filename}.html`.replace(source, ""));
33
+ await html.directory.file.create();
34
+ await html.file.write(content);
35
+
36
+ const json = target.join(`${filename}.json`.replace(source, ""));
37
+ await json.file.write(JSON.stringify(toc));
38
+ };
39
+ };
package/src/errors.js ADDED
@@ -0,0 +1,6 @@
1
+ import {Path} from "runtime-compat/fs";
2
+ import {Logger} from "primate";
3
+
4
+ const json = await new Path(import.meta.url).up(1).join("errors.json").json();
5
+
6
+ export default Logger.err(json.errors, json.module);
@@ -0,0 +1,10 @@
1
+ {
2
+ "module": "primate/solid",
3
+ "errors": {
4
+ "MissingComponent": {
5
+ "message": "missing component {0}",
6
+ "fix": "create {1} or remove route function",
7
+ "level": "Error"
8
+ }
9
+ }
10
+ }
package/src/exports.js ADDED
@@ -0,0 +1,3 @@
1
+ export {default} from "./module.js";
2
+
3
+ export {default as compile} from "./compile.js";
package/src/module.js ADDED
@@ -0,0 +1,67 @@
1
+ import {Response, Status, MediaType} from "runtime-compat/http";
2
+ import precompile from "./compile.js";
3
+
4
+ const respond = (handler, directory) => (...[name, ...rest]) => async app => {
5
+ const base = app.runpath(app.config.location.server, directory);
6
+ const content = await base.join(`${name}.html`).text();
7
+ const toc = await base.join(`${name}.json`).json();
8
+
9
+ return handler({
10
+ content,
11
+ toc,
12
+ }, ...rest);
13
+ };
14
+
15
+ const as_html = app => async ({content}, _, {status = Status.OK} = {}) =>
16
+ new Response(await app.render({body: content}), {
17
+ status,
18
+ headers: {...await app.headers(), "Content-Type": MediaType.TEXT_HTML},
19
+ });
20
+
21
+ export default ({
22
+ directory,
23
+ extension = "md",
24
+ options,
25
+ handler,
26
+ } = {}) => {
27
+ const env = {};
28
+ const re = new RegExp(`^.*.(?:${extension})$`, "u");
29
+ let compile;
30
+
31
+ return {
32
+ name: "primate:markdown",
33
+ async init(app, next) {
34
+ env.directory = directory ?? app.config.location.components;
35
+
36
+ return next(app);
37
+ },
38
+ register(app, next) {
39
+ app.register(extension, respond(handler ?? as_html(app), env.directory));
40
+ return next(app);
41
+ },
42
+ async compile(app, next) {
43
+ const {location} = app.config;
44
+ const source = app.runpath(directory);
45
+ // copy ${env.directory} to build/${env.directory}
46
+ await app.stage(app.root.join(env.directory), env.directory, re);
47
+
48
+ const components = await source.collect(re);
49
+ const target = app.runpath(location.server, env.directory);
50
+ await target.file.create();
51
+
52
+ compile = await precompile({
53
+ app,
54
+ directory: env.directory,
55
+ options,
56
+ });
57
+
58
+ await Promise.all(components.map(async component =>
59
+ compile(component.path, await component.file.read())));
60
+
61
+ return next(app);
62
+ },
63
+ async handle(request, next) {
64
+ return next({...request, markdown: {compile}});
65
+ },
66
+ };
67
+ };