@schalkneethling/miyagi-core 4.0.2
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/LICENSE.md +21 -0
- package/README.md +43 -0
- package/api/app.js +39 -0
- package/api/index.js +236 -0
- package/bin/miyagi.js +2 -0
- package/dist/css/iframe.css +31 -0
- package/dist/css/main.css +1 -0
- package/dist/js/_iframe-links-DdifIr4P.js +1 -0
- package/dist/js/_mock-data-Dypo4Bl_.js +1 -0
- package/dist/js/_prism-By3NMwUd.js +1 -0
- package/dist/js/iframe.build.js +1 -0
- package/dist/js/iframe.js +1 -0
- package/dist/js/index-BKDKaBC6.js +1 -0
- package/dist/js/jsontree.js +1 -0
- package/dist/js/main.build.js +1 -0
- package/dist/js/main.js +1 -0
- package/frontend/assets/css/iframe/accordion-tabs.css +77 -0
- package/frontend/assets/css/iframe/jsontree.js.css +325 -0
- package/frontend/assets/css/iframe/prism.css +132 -0
- package/frontend/assets/css/iframe/styleguide/colors.css +61 -0
- package/frontend/assets/css/iframe/styleguide/fonts.css +37 -0
- package/frontend/assets/css/iframe/styleguide/index.css +109 -0
- package/frontend/assets/css/iframe/styleguide/spacings.css +21 -0
- package/frontend/assets/css/iframe.css +410 -0
- package/frontend/assets/css/main/menu/config-switcher.css +49 -0
- package/frontend/assets/css/main/menu/config-switchers.css +67 -0
- package/frontend/assets/css/main/menu/goto.css +24 -0
- package/frontend/assets/css/main/menu/nav.css +113 -0
- package/frontend/assets/css/main/menu/search.css +64 -0
- package/frontend/assets/css/main/menu/title.css +40 -0
- package/frontend/assets/css/main/menu.css +114 -0
- package/frontend/assets/css/main/reset.css +217 -0
- package/frontend/assets/css/main.css +71 -0
- package/frontend/assets/css/shared.css +34 -0
- package/frontend/assets/css/tokens.css +112 -0
- package/frontend/assets/favicon.ico +0 -0
- package/frontend/assets/js/_accordion-tabs.js +403 -0
- package/frontend/assets/js/_goto.js +63 -0
- package/frontend/assets/js/_iframe-links.js +19 -0
- package/frontend/assets/js/_is-triggered.js +15 -0
- package/frontend/assets/js/_main.js +379 -0
- package/frontend/assets/js/_mock-data.js +13 -0
- package/frontend/assets/js/_prism.js +1098 -0
- package/frontend/assets/js/_search.js +190 -0
- package/frontend/assets/js/_socket.js +9 -0
- package/frontend/assets/js/config-switcher/development-mode.js +49 -0
- package/frontend/assets/js/config-switcher/index.js +63 -0
- package/frontend/assets/js/config-switcher/text-direction.js +30 -0
- package/frontend/assets/js/config-switcher/theme.js +87 -0
- package/frontend/assets/js/iframe.build.js +43 -0
- package/frontend/assets/js/iframe.js +52 -0
- package/frontend/assets/js/jsontree.js +979 -0
- package/frontend/assets/js/main.build.js +40 -0
- package/frontend/assets/js/main.js +42 -0
- package/frontend/assets/js/styleguide/color-converter.js +741 -0
- package/frontend/assets/js/styleguide/index.js +119 -0
- package/frontend/views/component_variation.twig.miyagi +57 -0
- package/frontend/views/design-tokens/colors.twig.miyagi +43 -0
- package/frontend/views/design-tokens/sizes.twig.miyagi +35 -0
- package/frontend/views/design-tokens/typography.twig.miyagi +38 -0
- package/frontend/views/iframe_component.twig.miyagi +141 -0
- package/frontend/views/iframe_component_variation.twig.miyagi +55 -0
- package/frontend/views/iframe_index.twig.miyagi +14 -0
- package/frontend/views/layouts/iframe_default.twig.miyagi +22 -0
- package/frontend/views/main.twig.miyagi +24 -0
- package/frontend/views/menu/config-switchers.twig.miyagi +83 -0
- package/frontend/views/menu/goto.twig.miyagi +9 -0
- package/frontend/views/menu/menu.twig.miyagi +21 -0
- package/frontend/views/menu/nav.twig.miyagi +95 -0
- package/frontend/views/menu/search.twig.miyagi +13 -0
- package/frontend/views/menu/title.twig.miyagi +24 -0
- package/index.js +3 -0
- package/lib/build/index.js +1020 -0
- package/lib/cli/app.js +38 -0
- package/lib/cli/component.js +56 -0
- package/lib/cli/index.js +5 -0
- package/lib/cli/lint.js +180 -0
- package/lib/config.js +74 -0
- package/lib/default-config.js +105 -0
- package/lib/generator/component.js +199 -0
- package/lib/generator/mocks.js +201 -0
- package/lib/helpers.js +184 -0
- package/lib/i18n/en.js +91 -0
- package/lib/i18n/index.js +17 -0
- package/lib/index.js +166 -0
- package/lib/init/args.js +55 -0
- package/lib/init/config.js +330 -0
- package/lib/init/engines.js +65 -0
- package/lib/init/index.js +102 -0
- package/lib/init/rendering.js +12 -0
- package/lib/init/router.js +249 -0
- package/lib/init/static.js +133 -0
- package/lib/init/twing/cache.js +34 -0
- package/lib/init/twing/functions.js +51 -0
- package/lib/init/views.js +19 -0
- package/lib/init/watcher.js +402 -0
- package/lib/logger.js +94 -0
- package/lib/mocks/get.js +111 -0
- package/lib/mocks/index.js +9 -0
- package/lib/mocks/resolve/ref.js +484 -0
- package/lib/mocks/resolve/tpl.js +246 -0
- package/lib/mocks/resolve.js +205 -0
- package/lib/render/helpers.js +51 -0
- package/lib/render/index.js +38 -0
- package/lib/render/views/iframe/component.docs.js +77 -0
- package/lib/render/views/iframe/component.js +338 -0
- package/lib/render/views/iframe/design-tokens/colors.js +52 -0
- package/lib/render/views/iframe/design-tokens/index.js +9 -0
- package/lib/render/views/iframe/design-tokens/sizes.js +49 -0
- package/lib/render/views/iframe/design-tokens/typography.js +52 -0
- package/lib/render/views/iframe/docs.js +68 -0
- package/lib/render/views/iframe/index.js +44 -0
- package/lib/render/views/iframe/variation.js +116 -0
- package/lib/render/views/iframe/variation.standalone.js +89 -0
- package/lib/render/views/main/component.docs.js +53 -0
- package/lib/render/views/main/component.js +74 -0
- package/lib/render/views/main/design-tokens.js +53 -0
- package/lib/render/views/main/docs.js +47 -0
- package/lib/render/views/main/index.js +46 -0
- package/lib/state/components.js +132 -0
- package/lib/state/css.js +50 -0
- package/lib/state/docs.js +111 -0
- package/lib/state/file-contents.js +207 -0
- package/lib/state/helpers.js +86 -0
- package/lib/state/index.js +56 -0
- package/lib/state/menu/index.js +275 -0
- package/lib/state/menu/structure.js +146 -0
- package/lib/state/partials.js +23 -0
- package/lib/state/source-tree.js +75 -0
- package/lib/styleguide/color-names.js +150 -0
- package/lib/styleguide/colors.js +135 -0
- package/lib/styleguide/helpers.js +37 -0
- package/lib/styleguide/index.js +17 -0
- package/lib/styleguide/media-queries.js +26 -0
- package/lib/styleguide/spacings.js +35 -0
- package/lib/styleguide/typography.js +61 -0
- package/lib/validator/mocks.js +105 -0
- package/package.json +117 -0
package/lib/cli/app.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module for initializing miyagi
|
|
3
|
+
* @module init
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import express from "express";
|
|
7
|
+
|
|
8
|
+
import setEngines from "../init/engines.js";
|
|
9
|
+
import setRouter from "../init/router.js";
|
|
10
|
+
import setState from "../state/index.js";
|
|
11
|
+
import setStatic from "../init/static.js";
|
|
12
|
+
import setViews from "../init/views.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {object} mergedConfig
|
|
16
|
+
* @returns {Promise<object>}
|
|
17
|
+
*/
|
|
18
|
+
export default async function init(mergedConfig) {
|
|
19
|
+
global.app = express();
|
|
20
|
+
global.config = mergedConfig;
|
|
21
|
+
global.app.set("view cache", false);
|
|
22
|
+
global.app.set("cache", false);
|
|
23
|
+
|
|
24
|
+
await setEngines();
|
|
25
|
+
await setState({
|
|
26
|
+
sourceTree: true,
|
|
27
|
+
menu: true,
|
|
28
|
+
partials: true,
|
|
29
|
+
fileContents: true,
|
|
30
|
+
css: true,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
setStatic();
|
|
34
|
+
setRouter();
|
|
35
|
+
setViews();
|
|
36
|
+
|
|
37
|
+
return global.app;
|
|
38
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import generateComponent from "../generator/component.js";
|
|
2
|
+
import log from "../logger.js";
|
|
3
|
+
import appConfig from "../default-config.js";
|
|
4
|
+
import { t } from "../i18n/index.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {object} cliParams
|
|
8
|
+
* @returns {Promise<void>}
|
|
9
|
+
*/
|
|
10
|
+
export default async function createComponentViaCli(cliParams) {
|
|
11
|
+
const commands = cliParams._.slice(1);
|
|
12
|
+
|
|
13
|
+
if (commands.length === 0) {
|
|
14
|
+
log("error", t("generator.noComponentNameDefined"));
|
|
15
|
+
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const [component] = commands;
|
|
20
|
+
const fileTypes = getFileTypesFromCliArgs(
|
|
21
|
+
cliParams,
|
|
22
|
+
Object.values(appConfig.defaultUserConfig.files).map((file) => file.abbr),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const result = await generateComponent({ component, fileTypes });
|
|
27
|
+
log("success", result);
|
|
28
|
+
} catch (message) {
|
|
29
|
+
log("error", message);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Returns an array with file names, if necessary filtered based on args
|
|
35
|
+
* @param {object} args - the cli args
|
|
36
|
+
* @param {Array} fileTypes
|
|
37
|
+
* @returns {Array} all file paths that should be created
|
|
38
|
+
*/
|
|
39
|
+
function getFileTypesFromCliArgs(args, fileTypes) {
|
|
40
|
+
if (args) {
|
|
41
|
+
if (args.skip) {
|
|
42
|
+
const files = [];
|
|
43
|
+
for (const fileType of fileTypes) {
|
|
44
|
+
if (!args.skip.includes(fileType)) {
|
|
45
|
+
files.push(fileType);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return files;
|
|
49
|
+
}
|
|
50
|
+
if (args.only) {
|
|
51
|
+
return args.only;
|
|
52
|
+
}
|
|
53
|
+
return fileTypes;
|
|
54
|
+
}
|
|
55
|
+
return fileTypes;
|
|
56
|
+
}
|
package/lib/cli/index.js
ADDED
package/lib/cli/lint.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import init from "./app.js";
|
|
3
|
+
import getConfig from "../config.js";
|
|
4
|
+
import log from "../logger.js";
|
|
5
|
+
import { getComponentData } from "../mocks/index.js";
|
|
6
|
+
import validateMockData from "../validator/mocks.js";
|
|
7
|
+
import { t } from "../i18n/index.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {object} args
|
|
11
|
+
*/
|
|
12
|
+
export default async function lint(args) {
|
|
13
|
+
process.env.NODE_ENV = "development";
|
|
14
|
+
|
|
15
|
+
const componentArg = args._.slice(1)[0];
|
|
16
|
+
const config = await getConfig(args);
|
|
17
|
+
global.app = await init(config);
|
|
18
|
+
|
|
19
|
+
if (componentArg) {
|
|
20
|
+
const component = global.state.routes.find(
|
|
21
|
+
({ alias }) =>
|
|
22
|
+
alias === path.relative(config.components.folder, componentArg),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
if (component) {
|
|
26
|
+
await validateComponentMockData({
|
|
27
|
+
component,
|
|
28
|
+
});
|
|
29
|
+
} else {
|
|
30
|
+
log("error", `The component ${componentArg} does not seem to exist.`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
await validateAllMockData();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {boolean} exitProcess
|
|
40
|
+
*/
|
|
41
|
+
async function validateAllMockData(exitProcess = true) {
|
|
42
|
+
log("info", t("linter.all.start"));
|
|
43
|
+
|
|
44
|
+
const promises = [];
|
|
45
|
+
|
|
46
|
+
global.state.routes.forEach((route) => {
|
|
47
|
+
if (route.type === "components") {
|
|
48
|
+
promises.push(
|
|
49
|
+
new Promise((resolve, reject) => {
|
|
50
|
+
validateComponentMockData({
|
|
51
|
+
component: route,
|
|
52
|
+
silent: true,
|
|
53
|
+
exitProcess: false,
|
|
54
|
+
})
|
|
55
|
+
.then((result) => resolve(result))
|
|
56
|
+
.catch((err) => {
|
|
57
|
+
console.error(err);
|
|
58
|
+
reject();
|
|
59
|
+
});
|
|
60
|
+
}),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
Promise.all(promises)
|
|
66
|
+
.then((results) => {
|
|
67
|
+
const mockInvalidResults = results.filter(
|
|
68
|
+
(result) => result?.valid === false && result.type === "mocks",
|
|
69
|
+
);
|
|
70
|
+
const schemaInvalidResults = results.filter(
|
|
71
|
+
(result) => result?.valid === false && result.type === "schema",
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (
|
|
75
|
+
mockInvalidResults.length === 0 &&
|
|
76
|
+
schemaInvalidResults.length === 0
|
|
77
|
+
) {
|
|
78
|
+
log("success", t("linter.all.valid"));
|
|
79
|
+
if (exitProcess) {
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (schemaInvalidResults.length > 0) {
|
|
85
|
+
log(
|
|
86
|
+
"error",
|
|
87
|
+
schemaInvalidResults.length === 1
|
|
88
|
+
? t("linter.all.schema.invalid.one")
|
|
89
|
+
: t("linter.all.schema.invalid.other").replace(
|
|
90
|
+
"{{amount}}",
|
|
91
|
+
schemaInvalidResults.length,
|
|
92
|
+
),
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (mockInvalidResults.length > 0) {
|
|
97
|
+
log(
|
|
98
|
+
"error",
|
|
99
|
+
mockInvalidResults.length === 1
|
|
100
|
+
? t("linter.all.mocks.invalid.one")
|
|
101
|
+
: t("linter.all.mocks.invalid.other").replace(
|
|
102
|
+
"{{amount}}",
|
|
103
|
+
mockInvalidResults.length,
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (exitProcess) {
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
.catch((err) => {
|
|
113
|
+
console.error(err);
|
|
114
|
+
if (exitProcess) {
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {object} obj
|
|
122
|
+
* @param {object} obj.component
|
|
123
|
+
* @param {boolean} [obj.silent]
|
|
124
|
+
* @param {boolean} [obj.exitProcess]
|
|
125
|
+
* @returns {Promise<object|null>}
|
|
126
|
+
*/
|
|
127
|
+
async function validateComponentMockData({
|
|
128
|
+
component,
|
|
129
|
+
silent,
|
|
130
|
+
exitProcess = true,
|
|
131
|
+
}) {
|
|
132
|
+
if (!silent) {
|
|
133
|
+
log(
|
|
134
|
+
"info",
|
|
135
|
+
t("linter.component.start").replace(
|
|
136
|
+
"{{component}}",
|
|
137
|
+
component.paths.dir.short,
|
|
138
|
+
),
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const data = await getComponentData(component);
|
|
143
|
+
|
|
144
|
+
if (data) {
|
|
145
|
+
for (const { messages } of data) {
|
|
146
|
+
for (const { type, text, verbose } of messages) {
|
|
147
|
+
log(type, text, verbose);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const results = validateMockData(component, data);
|
|
152
|
+
|
|
153
|
+
if (!results) return null;
|
|
154
|
+
|
|
155
|
+
if (results.length === 0) {
|
|
156
|
+
if (!silent) {
|
|
157
|
+
log("success", t("linter.component.valid"));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (exitProcess) {
|
|
161
|
+
process.exit(0);
|
|
162
|
+
} else {
|
|
163
|
+
return {
|
|
164
|
+
valid: true,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
if (exitProcess) {
|
|
169
|
+
process.exit(0);
|
|
170
|
+
} else {
|
|
171
|
+
return {
|
|
172
|
+
valid: false,
|
|
173
|
+
type: results[0].type,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return null;
|
|
180
|
+
}
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import deepMerge from "deepmerge";
|
|
3
|
+
|
|
4
|
+
import getMergedConfig from "./init/config.js";
|
|
5
|
+
import log from "./logger.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {object} args
|
|
9
|
+
* @param {boolean} [isBuild]
|
|
10
|
+
* @param {boolean} [isComponentGenerator]
|
|
11
|
+
* @returns {Promise<object>}
|
|
12
|
+
*/
|
|
13
|
+
export default async function getConfig(args, isBuild, isComponentGenerator) {
|
|
14
|
+
let userFile = {};
|
|
15
|
+
let userFileName;
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
userFileName = ".miyagi.js";
|
|
19
|
+
userFile = await import(
|
|
20
|
+
path.resolve(process.cwd(), `${userFileName}?time=${Date.now()}`)
|
|
21
|
+
);
|
|
22
|
+
} catch (e) {
|
|
23
|
+
log("warn", null, e);
|
|
24
|
+
try {
|
|
25
|
+
userFileName = ".miyagi.mjs";
|
|
26
|
+
userFile = await import(
|
|
27
|
+
path.resolve(process.cwd(), `${userFileName}?time=${Date.now()}`)
|
|
28
|
+
);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
userFileName = null;
|
|
31
|
+
log("warn", null, err);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let userConfig =
|
|
36
|
+
(args ? deepMerge(userFile.default, getCliArgs(args)) : userFile.default) ??
|
|
37
|
+
{};
|
|
38
|
+
|
|
39
|
+
userConfig.userFileName = userFileName;
|
|
40
|
+
userConfig.isBuild = isBuild;
|
|
41
|
+
userConfig.isComponentGenerator = isComponentGenerator;
|
|
42
|
+
userConfig.indexPath = {
|
|
43
|
+
default: isBuild ? "component-all.html" : "/component?file=all",
|
|
44
|
+
embedded: isBuild
|
|
45
|
+
? "component-all-embedded.html"
|
|
46
|
+
: "/component?file=all&embedded=true",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
delete userConfig._;
|
|
50
|
+
|
|
51
|
+
return getMergedConfig(userConfig);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Converts and removes unnecessary cli args
|
|
56
|
+
* @param {object} args - the cli args
|
|
57
|
+
* @returns {object} configuration object based on cli args
|
|
58
|
+
*/
|
|
59
|
+
function getCliArgs(args) {
|
|
60
|
+
const cliArgs = { ...args };
|
|
61
|
+
const buildArgs = {};
|
|
62
|
+
|
|
63
|
+
delete cliArgs._;
|
|
64
|
+
delete cliArgs.$0;
|
|
65
|
+
|
|
66
|
+
if (cliArgs.folder) {
|
|
67
|
+
buildArgs.folder = cliArgs.folder;
|
|
68
|
+
delete cliArgs.folder;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
cliArgs.build = buildArgs;
|
|
72
|
+
|
|
73
|
+
return cliArgs;
|
|
74
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import AJV from "ajv";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
defaultUserConfig: {
|
|
5
|
+
assets: {
|
|
6
|
+
root: "",
|
|
7
|
+
css: [],
|
|
8
|
+
customProperties: {
|
|
9
|
+
files: [],
|
|
10
|
+
prefixes: {
|
|
11
|
+
typo: "typo",
|
|
12
|
+
color: "color",
|
|
13
|
+
spacing: "spacing",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
folder: [],
|
|
17
|
+
js: [],
|
|
18
|
+
manifest: null,
|
|
19
|
+
},
|
|
20
|
+
build: {
|
|
21
|
+
basePath: "/",
|
|
22
|
+
folder: "build",
|
|
23
|
+
},
|
|
24
|
+
docs: {
|
|
25
|
+
folder: "docs",
|
|
26
|
+
},
|
|
27
|
+
components: {
|
|
28
|
+
folder: "src",
|
|
29
|
+
ignores: [
|
|
30
|
+
"node_modules",
|
|
31
|
+
".git",
|
|
32
|
+
"package.json",
|
|
33
|
+
"package-lock.json",
|
|
34
|
+
".miyagi.js",
|
|
35
|
+
".miyagi.mjs",
|
|
36
|
+
],
|
|
37
|
+
lang: "en",
|
|
38
|
+
textDirection: "ltr",
|
|
39
|
+
},
|
|
40
|
+
engine: {
|
|
41
|
+
render: null,
|
|
42
|
+
options: {},
|
|
43
|
+
},
|
|
44
|
+
extensions: [],
|
|
45
|
+
files: {
|
|
46
|
+
css: {
|
|
47
|
+
abbr: "css",
|
|
48
|
+
name: "index",
|
|
49
|
+
extension: "css",
|
|
50
|
+
},
|
|
51
|
+
js: {
|
|
52
|
+
abbr: "js",
|
|
53
|
+
name: "index",
|
|
54
|
+
extension: "js",
|
|
55
|
+
},
|
|
56
|
+
mocks: {
|
|
57
|
+
abbr: "mocks",
|
|
58
|
+
name: "mocks",
|
|
59
|
+
extension: ["json", "js"],
|
|
60
|
+
},
|
|
61
|
+
schema: {
|
|
62
|
+
abbr: "schema",
|
|
63
|
+
name: "schema",
|
|
64
|
+
extension: "json",
|
|
65
|
+
},
|
|
66
|
+
templates: {
|
|
67
|
+
abbr: "tpl",
|
|
68
|
+
name: "index",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
namespaces: {},
|
|
72
|
+
projectName: "miyagi",
|
|
73
|
+
ui: {
|
|
74
|
+
mode: "light",
|
|
75
|
+
lang: "en",
|
|
76
|
+
reload: true,
|
|
77
|
+
reloadAfterChanges: {
|
|
78
|
+
componentAssets: false,
|
|
79
|
+
},
|
|
80
|
+
textDirection: "ltr",
|
|
81
|
+
theme: {
|
|
82
|
+
css: null,
|
|
83
|
+
favicon: null,
|
|
84
|
+
js: null,
|
|
85
|
+
logo: {
|
|
86
|
+
light: null,
|
|
87
|
+
dark: null,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
watchConfigFile: true,
|
|
91
|
+
},
|
|
92
|
+
schema: {
|
|
93
|
+
ajv: AJV,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
projectName: "miyagi",
|
|
97
|
+
defaultPort: 5000,
|
|
98
|
+
folders: {
|
|
99
|
+
assets: {
|
|
100
|
+
development: "frontend/assets",
|
|
101
|
+
production: "dist",
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
defaultVariationName: "default",
|
|
105
|
+
};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import jsonToYaml from "js-yaml";
|
|
4
|
+
import * as helpers from "../helpers.js";
|
|
5
|
+
import { t } from "../i18n/index.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Module for creating component files based on the configuration cli params
|
|
9
|
+
* @param {object} root
|
|
10
|
+
* @param {object} root.component
|
|
11
|
+
* @param {Array} root.fileTypes
|
|
12
|
+
* @returns {Promise<string>}
|
|
13
|
+
*/
|
|
14
|
+
export default async function componentGenerator({ component, fileTypes }) {
|
|
15
|
+
try {
|
|
16
|
+
await createComponentFolder(component);
|
|
17
|
+
await createComponentFiles(
|
|
18
|
+
global.config.files,
|
|
19
|
+
component,
|
|
20
|
+
fileTypes,
|
|
21
|
+
global.config.components.folder,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return Promise.resolve(
|
|
25
|
+
t("generator.component.done").replace("{{component}}", component),
|
|
26
|
+
);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
return Promise.reject(err);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns an array with file names
|
|
34
|
+
* @param {object} fileNames - an object with file names for the component
|
|
35
|
+
* @param {Array} fileTypes
|
|
36
|
+
* @returns {Array} all file paths that should be created
|
|
37
|
+
*/
|
|
38
|
+
function getFiles(fileNames, fileTypes) {
|
|
39
|
+
return fileTypes.map((fileType) => fileNames[fileType]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Returns the dummy content for a component file
|
|
44
|
+
* @param {string} fileType - the file type that should be created
|
|
45
|
+
* @param {object} filesConfig - the files object from the user congiguration object
|
|
46
|
+
* @param {string} componentPath
|
|
47
|
+
* @returns {string} dummy file content based on the given file type
|
|
48
|
+
*/
|
|
49
|
+
function getDummyFileContent(fileType, filesConfig, componentPath) {
|
|
50
|
+
let str;
|
|
51
|
+
|
|
52
|
+
switch (fileType) {
|
|
53
|
+
case "mocks":
|
|
54
|
+
{
|
|
55
|
+
const data = {
|
|
56
|
+
$variants: [
|
|
57
|
+
{
|
|
58
|
+
$name: "",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
if (["yaml", "yml"].includes(filesConfig.mocks.extension[0])) {
|
|
64
|
+
str = jsonToYaml.dump(data);
|
|
65
|
+
} else {
|
|
66
|
+
str = `${JSON.stringify(data, null, 2)}\n`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
case "schema":
|
|
71
|
+
{
|
|
72
|
+
const id = path.join("/", componentPath);
|
|
73
|
+
|
|
74
|
+
if (["yaml", "yml"].includes(filesConfig.schema.extension)) {
|
|
75
|
+
str = `$schema: "http://json-schema.org/draft-07/schema"
|
|
76
|
+
$id: "${id}"
|
|
77
|
+
additionalProperties: false
|
|
78
|
+
properties:
|
|
79
|
+
required:
|
|
80
|
+
`;
|
|
81
|
+
} else {
|
|
82
|
+
str = `${JSON.stringify(
|
|
83
|
+
{
|
|
84
|
+
$schema: "http://json-schema.org/draft-07/schema",
|
|
85
|
+
$id: id,
|
|
86
|
+
additionalProperties: false,
|
|
87
|
+
properties: {},
|
|
88
|
+
required: [],
|
|
89
|
+
},
|
|
90
|
+
null,
|
|
91
|
+
2,
|
|
92
|
+
)}\n`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
str = "";
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return str;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Creates the component files
|
|
105
|
+
* @param {object} filesConfig - the files configuration from the user configuration object
|
|
106
|
+
* @param {string} componentPath - the path of the component folder
|
|
107
|
+
* @param {Array} fileTypes
|
|
108
|
+
* @param {string} componentFolder
|
|
109
|
+
* @returns {Promise} gets resolved when all files have been created
|
|
110
|
+
*/
|
|
111
|
+
async function createComponentFiles(
|
|
112
|
+
filesConfig,
|
|
113
|
+
componentPath,
|
|
114
|
+
fileTypes,
|
|
115
|
+
componentFolder,
|
|
116
|
+
) {
|
|
117
|
+
const componentName = path.basename(componentPath);
|
|
118
|
+
const fileNames = getFileNames(filesConfig, componentName);
|
|
119
|
+
const files = getFiles(fileNames, fileTypes);
|
|
120
|
+
const entries = Object.entries(fileNames);
|
|
121
|
+
|
|
122
|
+
for (const [type, file] of entries) {
|
|
123
|
+
if (files.includes(file)) {
|
|
124
|
+
const fullFilePath = path.join(
|
|
125
|
+
process.env.INIT_CWD || process.cwd(),
|
|
126
|
+
componentPath,
|
|
127
|
+
file,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
await writeFile(
|
|
132
|
+
fullFilePath,
|
|
133
|
+
getDummyFileContent(
|
|
134
|
+
type,
|
|
135
|
+
filesConfig,
|
|
136
|
+
path.relative(componentFolder, componentPath),
|
|
137
|
+
),
|
|
138
|
+
{ flag: "wx" },
|
|
139
|
+
);
|
|
140
|
+
} catch (err) {
|
|
141
|
+
return Promise.reject(err.message);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Returns an object with the file names for a given component name
|
|
149
|
+
* @param {object} filesConfig - the files configuration from the user configuration object
|
|
150
|
+
* @param {string} componentName - the name of the component
|
|
151
|
+
* @returns {object} all file names based on the user configuration
|
|
152
|
+
*/
|
|
153
|
+
function getFileNames(filesConfig, componentName) {
|
|
154
|
+
return {
|
|
155
|
+
tpl: `${helpers.getResolvedFileName(
|
|
156
|
+
filesConfig.templates.name,
|
|
157
|
+
componentName,
|
|
158
|
+
)}.${filesConfig.templates.extension}`,
|
|
159
|
+
mocks: `${filesConfig.mocks.name}.${filesConfig.mocks.extension[0]}`,
|
|
160
|
+
docs: "README.md",
|
|
161
|
+
css: `${helpers.getResolvedFileName(filesConfig.css.name, componentName)}.${
|
|
162
|
+
filesConfig.css.extension
|
|
163
|
+
}`,
|
|
164
|
+
js: `${helpers.getResolvedFileName(filesConfig.js.name, componentName)}.${
|
|
165
|
+
filesConfig.js.extension
|
|
166
|
+
}`,
|
|
167
|
+
schema: `${filesConfig.schema.name}.${filesConfig.schema.extension}`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Creates the component folder
|
|
173
|
+
* @param {string} folder - component folder path that should be created
|
|
174
|
+
* @returns {Promise} gets resolved when the folder has been created
|
|
175
|
+
*/
|
|
176
|
+
async function createComponentFolder(folder) {
|
|
177
|
+
try {
|
|
178
|
+
await mkdir(
|
|
179
|
+
/*
|
|
180
|
+
* When using `pnpm/yarn/npm miyagi new …`, `process.env.INIT_CWD` equals
|
|
181
|
+
* the current working directory, so also subdirectories of where
|
|
182
|
+
* the package.json is located. In this case `process.cwd()` always
|
|
183
|
+
* equals the root directory though.
|
|
184
|
+
* When using node directly, `process.env.INIT_CWD` is not available,
|
|
185
|
+
* but `process.cwd()` is always the current working directory, so
|
|
186
|
+
* also subdirectories.
|
|
187
|
+
* So, if INIT_CWD is available, we know it is the directory the user
|
|
188
|
+
* cd'ed into, if it not available, then we use process.cwd(), which
|
|
189
|
+
* in that case is also the directory the user cd'ed into.
|
|
190
|
+
* It is important that we let the user create a component from their
|
|
191
|
+
* current working directory, so they can benefit from autocompletion.
|
|
192
|
+
*/
|
|
193
|
+
path.join(process.env.INIT_CWD || process.cwd(), folder),
|
|
194
|
+
{ recursive: true },
|
|
195
|
+
);
|
|
196
|
+
} catch (err) {
|
|
197
|
+
return err;
|
|
198
|
+
}
|
|
199
|
+
}
|