@shevky/core 0.0.2 → 0.0.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/engines/menuEngine.js +117 -0
- package/engines/metaEngine.js +787 -0
- package/engines/pluginEngine.js +103 -0
- package/engines/renderEngine.js +823 -0
- package/lib/contentBody.js +12 -0
- package/lib/contentFile.js +170 -0
- package/lib/contentHeader.js +295 -0
- package/lib/contentSummary.js +85 -0
- package/lib/menuItem.js +51 -0
- package/lib/page.js +103 -0
- package/lib/project.js +82 -0
- package/lib/template.js +50 -0
- package/package.json +6 -2
- package/registries/contentRegistry.js +323 -0
- package/registries/pageRegistry.js +29 -0
- package/registries/pluginRegistry.js +94 -0
- package/registries/templateRegistry.js +152 -0
- package/scripts/cli.js +2 -2
- package/scripts/main.js +1 -1
- package/types/command-line-args.d.ts +20 -0
- package/types/command-line-usage.d.ts +12 -0
- package/types/degit.d.ts +15 -0
- package/types/index.d.ts +98 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { io as _io } from "@shevky/base";
|
|
2
|
+
|
|
3
|
+
import { Template } from "../lib/template.js";
|
|
4
|
+
|
|
5
|
+
export const TYPE_PARTIAL = "partial";
|
|
6
|
+
export const TYPE_COMPONENT = "component";
|
|
7
|
+
export const TYPE_LAYOUT = "layout";
|
|
8
|
+
export const TYPE_TEMPLATE = "template";
|
|
9
|
+
|
|
10
|
+
const MUSTACHE_EXT = ".mustache";
|
|
11
|
+
|
|
12
|
+
export class TemplateRegistry {
|
|
13
|
+
/**
|
|
14
|
+
* @type {Map<string, Map<string, Template>>}
|
|
15
|
+
*/
|
|
16
|
+
#_cache = new Map();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {string} directoryPath
|
|
20
|
+
*/
|
|
21
|
+
async loadPartials(directoryPath) {
|
|
22
|
+
await this.#_loadDirectory(directoryPath, {
|
|
23
|
+
type: TYPE_PARTIAL,
|
|
24
|
+
keyPrefix: "partials/",
|
|
25
|
+
accept: (entry) => entry.startsWith("_") && entry.endsWith(MUSTACHE_EXT),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} directoryPath
|
|
31
|
+
*/
|
|
32
|
+
async loadComponents(directoryPath) {
|
|
33
|
+
await this.#_loadDirectory(directoryPath, {
|
|
34
|
+
type: TYPE_COMPONENT,
|
|
35
|
+
keyPrefix: "components/",
|
|
36
|
+
accept: (entry) => entry.endsWith(MUSTACHE_EXT),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} directoryPath
|
|
42
|
+
*/
|
|
43
|
+
async loadLayouts(directoryPath) {
|
|
44
|
+
await this.#_loadDirectory(directoryPath, {
|
|
45
|
+
type: TYPE_LAYOUT,
|
|
46
|
+
accept: (entry) => !entry.startsWith("_") && entry.endsWith(MUSTACHE_EXT),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {string} directoryPath
|
|
52
|
+
*/
|
|
53
|
+
async loadTemplates(directoryPath) {
|
|
54
|
+
await this.#_loadDirectory(directoryPath, {
|
|
55
|
+
type: TYPE_TEMPLATE,
|
|
56
|
+
accept: (entry) => entry.endsWith(MUSTACHE_EXT),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} type
|
|
62
|
+
*/
|
|
63
|
+
list(type) {
|
|
64
|
+
return Array.from(this.#_ensure(type).keys());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {string} type
|
|
69
|
+
* @param {string} key
|
|
70
|
+
*/
|
|
71
|
+
get(type, key) {
|
|
72
|
+
const template = this.#_ensure(type).get(key);
|
|
73
|
+
if (!template) {
|
|
74
|
+
throw new Error(`Template not found: ${key}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return template.content;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {string} type
|
|
82
|
+
* @param {string} key
|
|
83
|
+
*/
|
|
84
|
+
getTemplate(type, key) {
|
|
85
|
+
const template = this.#_ensure(type).get(key);
|
|
86
|
+
if (!template) {
|
|
87
|
+
throw new Error(`Template not found: ${key}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return template;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param {string} type
|
|
95
|
+
*/
|
|
96
|
+
getFiles(type) {
|
|
97
|
+
/** @type {Record<string, string>} */
|
|
98
|
+
const result = {};
|
|
99
|
+
for (const [key, template] of this.#_ensure(type).entries()) {
|
|
100
|
+
result[key] = template.content;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @param {string} type
|
|
108
|
+
*/
|
|
109
|
+
getCount(type) {
|
|
110
|
+
return this.#_ensure(type).size;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @param {string} directoryPath
|
|
115
|
+
* @param {{ type: string, keyPrefix?: string, accept: (entry: string) => boolean }} options
|
|
116
|
+
*/
|
|
117
|
+
async #_loadDirectory(directoryPath, options) {
|
|
118
|
+
const isExists = await _io.directory.exists(directoryPath);
|
|
119
|
+
if (!isExists) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const { type, keyPrefix = "", accept } = options;
|
|
124
|
+
const entries = await _io.directory.read(directoryPath);
|
|
125
|
+
for (const entry of entries) {
|
|
126
|
+
if (!accept(entry)) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const key = `${keyPrefix}${entry.replace(`${MUSTACHE_EXT}`, "")}`;
|
|
131
|
+
const path = _io.path.combine(directoryPath, entry);
|
|
132
|
+
const raw = await _io.file.read(path);
|
|
133
|
+
|
|
134
|
+
const template = new Template(key, type, path, raw);
|
|
135
|
+
this.#_ensure(type).set(key, template);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param {string} type
|
|
141
|
+
* @returns {Map<string, Template>}
|
|
142
|
+
*/
|
|
143
|
+
#_ensure(type) {
|
|
144
|
+
let bucket = this.#_cache.get(type);
|
|
145
|
+
if (!bucket) {
|
|
146
|
+
bucket = new Map();
|
|
147
|
+
this.#_cache.set(type, bucket);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return bucket;
|
|
151
|
+
}
|
|
152
|
+
}
|
package/scripts/cli.js
CHANGED
|
@@ -65,10 +65,10 @@ function help() {
|
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
header: "Project Details",
|
|
68
|
-
content: "Project Home: {underline https://
|
|
68
|
+
content: "Project Home: {underline https://shevky.github.io}",
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
|
-
content: "GitHub: {underline https://github.com/
|
|
71
|
+
content: "GitHub: {underline https://github.com/shevky}",
|
|
72
72
|
},
|
|
73
73
|
];
|
|
74
74
|
|
package/scripts/main.js
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
declare module "command-line-args" {
|
|
2
|
+
export type OptionDefinition = {
|
|
3
|
+
name: string;
|
|
4
|
+
alias?: string;
|
|
5
|
+
type?: unknown;
|
|
6
|
+
description?: string;
|
|
7
|
+
defaultValue?: unknown;
|
|
8
|
+
multiple?: boolean;
|
|
9
|
+
defaultOption?: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type CommandLineOptions = Record<string, unknown>;
|
|
13
|
+
|
|
14
|
+
function commandLineArgs(
|
|
15
|
+
options?: readonly OptionDefinition[],
|
|
16
|
+
argv?: readonly string[],
|
|
17
|
+
): CommandLineOptions;
|
|
18
|
+
|
|
19
|
+
export default commandLineArgs;
|
|
20
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare module "command-line-usage" {
|
|
2
|
+
export type Section = {
|
|
3
|
+
header?: string;
|
|
4
|
+
content?: string | string[];
|
|
5
|
+
optionList?: unknown[];
|
|
6
|
+
group?: string | string[];
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function commandLineUsage(sections: readonly Section[] | Section): string;
|
|
10
|
+
|
|
11
|
+
export default commandLineUsage;
|
|
12
|
+
}
|
package/types/degit.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare module "degit" {
|
|
2
|
+
type DegitOptions = {
|
|
3
|
+
cache?: boolean;
|
|
4
|
+
force?: boolean;
|
|
5
|
+
verbose?: boolean;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type DegitEmitter = {
|
|
9
|
+
clone: (dest: string) => Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function degit(repo: string, options?: DegitOptions): DegitEmitter;
|
|
13
|
+
|
|
14
|
+
export default degit;
|
|
15
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BasePluginContext,
|
|
3
|
+
PluginHooks,
|
|
4
|
+
PluginLoadContext as BasePluginLoadContext,
|
|
5
|
+
} from "@shevky/base";
|
|
6
|
+
|
|
7
|
+
export type ProjectPaths = {
|
|
8
|
+
root: string;
|
|
9
|
+
src: string;
|
|
10
|
+
dist: string;
|
|
11
|
+
tmp: string;
|
|
12
|
+
content: string;
|
|
13
|
+
layouts: string;
|
|
14
|
+
components: string;
|
|
15
|
+
templates: string;
|
|
16
|
+
assets: string;
|
|
17
|
+
siteConfig: string;
|
|
18
|
+
i18nConfig: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type PluginInstance = {
|
|
22
|
+
name: string;
|
|
23
|
+
version: string;
|
|
24
|
+
hooks: PluginHooks;
|
|
25
|
+
load: (ctx: PluginLoadContext) => void;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type PluginLoadContext = BasePluginLoadContext;
|
|
29
|
+
|
|
30
|
+
export type ContentHeaderLike = Record<string, any>;
|
|
31
|
+
|
|
32
|
+
export type ContentBodyLike = {
|
|
33
|
+
content?: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type ContentFileLike = {
|
|
37
|
+
header?: ContentHeaderLike;
|
|
38
|
+
body?: ContentBodyLike;
|
|
39
|
+
content?: string;
|
|
40
|
+
isValid?: boolean;
|
|
41
|
+
sourcePath?: string;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export interface PluginExecutionContext extends BasePluginContext {
|
|
45
|
+
paths: ProjectPaths;
|
|
46
|
+
contentFiles?: ContentFileLike[];
|
|
47
|
+
addContent?: (
|
|
48
|
+
input:
|
|
49
|
+
| ContentFileLike
|
|
50
|
+
| import("../lib/contentFile.js").ContentFile
|
|
51
|
+
) => void;
|
|
52
|
+
pages?: CollectionsByLang;
|
|
53
|
+
contentIndex?: Record<
|
|
54
|
+
string,
|
|
55
|
+
Record<string, { id: string; lang: string; title: string; canonical: string }>
|
|
56
|
+
>;
|
|
57
|
+
footerPolicies?: Record<string, FooterPolicy[]>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type Placeholder = {
|
|
61
|
+
token: string;
|
|
62
|
+
marker: string;
|
|
63
|
+
html: string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type FooterPolicy = {
|
|
67
|
+
key: string;
|
|
68
|
+
label: string;
|
|
69
|
+
url: string;
|
|
70
|
+
lang: string;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type ContentSummaryLike = {
|
|
74
|
+
id: string;
|
|
75
|
+
title: string;
|
|
76
|
+
slug: string;
|
|
77
|
+
lang: string;
|
|
78
|
+
canonical: string;
|
|
79
|
+
date: string | number | Date;
|
|
80
|
+
updated: string | number | Date;
|
|
81
|
+
description: string;
|
|
82
|
+
cover: string;
|
|
83
|
+
coverAlt: string;
|
|
84
|
+
coverCaption: string;
|
|
85
|
+
readingTime: number;
|
|
86
|
+
dateDisplay: string | null;
|
|
87
|
+
seriesTitle: string;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export type CollectionEntry = ContentSummaryLike & {
|
|
91
|
+
type?: string;
|
|
92
|
+
seriesTitle?: string;
|
|
93
|
+
canonical?: string;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type CollectionsByLang = Record<string, Record<string, CollectionEntry[]>>;
|
|
97
|
+
|
|
98
|
+
export type FrontMatter = Record<string, any>;
|