@mimi-ng/cli 0.4.0 → 0.5.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 +29 -7
- package/dist/init/index.js +8 -0
- package/dist/registry.js +4 -1
- package/dist/registry.json +87 -1
- package/dist/templates/blocks/login-01/login-01.ts +12 -3
- package/dist/templates/blocks/login-02/login-02.ts +12 -3
- package/dist/templates/blocks/otp-01/otp-01.ts +12 -3
- package/dist/templates/blocks/pricing-01/pricing-01.ts +1 -1
- package/dist/templates/blocks/settings-01/settings-01.ts +13 -3
- package/dist/templates/blocks/signup-01/signup-01.ts +12 -2
- package/dist/templates/blocks/table-01/index.ts +1 -0
- package/dist/templates/blocks/table-01/table-01.html +214 -0
- package/dist/templates/blocks/table-01/table-01.ts +266 -0
- package/dist/templates/components/checkbox/checkbox.ts +14 -5
- package/dist/templates/components/command/command-texts.ts +65 -0
- package/dist/templates/components/command/command.ts +553 -0
- package/dist/templates/components/command/index.ts +13 -0
- package/dist/templates/components/data-table/data-table-texts.ts +110 -0
- package/dist/templates/components/data-table/data-table.ts +1153 -0
- package/dist/templates/components/data-table/index.ts +18 -0
- package/dist/templates/components/sortable-list/index.ts +9 -0
- package/dist/templates/components/sortable-list/sortable-list-texts.ts +71 -0
- package/dist/templates/components/sortable-list/sortable-list.ts +510 -0
- package/dist/templates/components/tree/index.ts +9 -0
- package/dist/templates/components/tree/tree-texts.ts +45 -0
- package/dist/templates/components/tree/tree.ts +730 -0
- package/dist/templates/theme/provider.ts +4 -0
- package/dist/templates/theme/types.ts +84 -0
- package/dist/ui/index.js +232 -40
- package/dist/ui/schema.json +30 -6
- package/dist/utils/pages.js +138 -0
- package/dist/utils/project.js +33 -9
- package/dist/utils/tailwind.js +15 -11
- package/dist/utils/write-files.js +32 -7
- package/package.json +1 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Blocks de tipo página (B.11): `ng g mimi login-01` no copia el Block tal cual (`Login01`,
|
|
4
|
+
* `mimi-login-01`), sino que genera una página del usuario en `aliases.pages`
|
|
5
|
+
* (`src/app/pages/login/login.ts`, clase `LoginPage`) con su archivo de rutas.
|
|
6
|
+
*
|
|
7
|
+
* Solo funciones de texto, sin schematics: lo usa también el sitio para mostrar el código como
|
|
8
|
+
* lo genera la CLI.
|
|
9
|
+
*
|
|
10
|
+
* **Seguimiento por el nombre del registro (B.11-f):** los archivos de una página se identifican
|
|
11
|
+
* con claves `pages/<ítem>/…` (`pages/login-01/login-01.ts`), que son también las de sus bases
|
|
12
|
+
* (`.mimi/base/pages/login-01/`) y las del manifiesto. La carpeta y el nombre que eligió el
|
|
13
|
+
* usuario solo deciden dónde se escriben y cómo se llaman.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.isBlockLikeName = exports.pageItemOf = exports.pageKeys = exports.pageKeyOf = exports.routesKey = exports.pageSourceFiles = exports.routesConstName = exports.pageClassName = exports.defaultPageName = exports.PAGE_NAME = exports.isPageFile = exports.PAGES_PREFIX = void 0;
|
|
17
|
+
exports.pageSelector = pageSelector;
|
|
18
|
+
exports.pageTargetPath = pageTargetPath;
|
|
19
|
+
exports.renderPageFile = renderPageFile;
|
|
20
|
+
exports.routesFile = routesFile;
|
|
21
|
+
exports.routeLine = routeLine;
|
|
22
|
+
/** Prefijo de las claves de los archivos de una página. */
|
|
23
|
+
exports.PAGES_PREFIX = 'pages/';
|
|
24
|
+
/** ¿Es la clave de un archivo de una página? */
|
|
25
|
+
const isPageFile = (file) => file.startsWith(exports.PAGES_PREFIX);
|
|
26
|
+
exports.isPageFile = isPageFile;
|
|
27
|
+
/** Nombre válido para `--name`: kebab-case, empieza con una letra (`login`, `admin-login`). */
|
|
28
|
+
exports.PAGE_NAME = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
29
|
+
/** Nombre por defecto: el del registro sin el número (`login-01` → `login`). */
|
|
30
|
+
const defaultPageName = (item) => item.replace(/-\d+$/, '');
|
|
31
|
+
exports.defaultPageName = defaultPageName;
|
|
32
|
+
const pascal = (kebab) => kebab
|
|
33
|
+
.split('-')
|
|
34
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
35
|
+
.join('');
|
|
36
|
+
const endsWithPage = (name) => name === 'page' || name.endsWith('-page');
|
|
37
|
+
/** `login` → `LoginPage`; `login-page` → `LoginPage` (sin repetir «Page»). */
|
|
38
|
+
const pageClassName = (name) => endsWithPage(name) ? pascal(name) : `${pascal(name)}Page`;
|
|
39
|
+
exports.pageClassName = pageClassName;
|
|
40
|
+
/** `app` y `login` → `app-login-page`; sin prefijo, `login-page`. */
|
|
41
|
+
function pageSelector(prefix, name) {
|
|
42
|
+
const base = endsWithPage(name) ? name : `${name}-page`;
|
|
43
|
+
return prefix ? `${prefix}-${base}` : base;
|
|
44
|
+
}
|
|
45
|
+
/** `login` → `LOGIN_ROUTES`; `admin-login` → `ADMIN_LOGIN_ROUTES`. */
|
|
46
|
+
const routesConstName = (name) => `${name.replace(/-/g, '_').toUpperCase()}_ROUTES`;
|
|
47
|
+
exports.routesConstName = routesConstName;
|
|
48
|
+
const basename = (file) => file.slice(file.lastIndexOf('/') + 1);
|
|
49
|
+
/** Los archivos del Block que pasan a la página: todos menos su `index.ts`. */
|
|
50
|
+
const pageSourceFiles = (files) => files.filter((file) => basename(file) !== 'index.ts');
|
|
51
|
+
exports.pageSourceFiles = pageSourceFiles;
|
|
52
|
+
/** Clave del archivo de rutas (`pages/login-01/login-01.routes.ts`). */
|
|
53
|
+
const routesKey = (item) => `${exports.PAGES_PREFIX}${item}/${item}.routes.ts`;
|
|
54
|
+
exports.routesKey = routesKey;
|
|
55
|
+
/** Clave de un archivo del Block en la página: `blocks/login-01/login-01.html` → `pages/login-01/login-01.html`. */
|
|
56
|
+
const pageKeyOf = (item, file) => `${exports.PAGES_PREFIX}${item}/${basename(file)}`;
|
|
57
|
+
exports.pageKeyOf = pageKeyOf;
|
|
58
|
+
/** Las claves de los archivos de una página: los del Block (sin `index.ts`) y el de rutas. */
|
|
59
|
+
const pageKeys = (item, files) => [
|
|
60
|
+
...(0, exports.pageSourceFiles)(files).map((file) => (0, exports.pageKeyOf)(item, file)),
|
|
61
|
+
(0, exports.routesKey)(item),
|
|
62
|
+
];
|
|
63
|
+
exports.pageKeys = pageKeys;
|
|
64
|
+
/** El ítem de una clave de página (`pages/login-01/login-01.ts` → `login-01`). */
|
|
65
|
+
const pageItemOf = (key) => key.slice(exports.PAGES_PREFIX.length).split('/')[0];
|
|
66
|
+
exports.pageItemOf = pageItemOf;
|
|
67
|
+
/**
|
|
68
|
+
* Ruta en el workspace de un archivo de la página: `pages/login-01/login-01.ts` con
|
|
69
|
+
* `{ dir: 'src/app/pages/login', name: 'login' }` → `src/app/pages/login/login.ts`.
|
|
70
|
+
*/
|
|
71
|
+
function pageTargetPath(key, target) {
|
|
72
|
+
const file = basename(key);
|
|
73
|
+
const rest = file.startsWith(target.item) ? file.slice(target.item.length) : `.${file}`;
|
|
74
|
+
return `${target.dir}/${target.name}${rest}`;
|
|
75
|
+
}
|
|
76
|
+
const escape = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
77
|
+
/** `settings-01` → `SETTINGS_01`; `Login-Page` → `LOGIN_PAGE`. */
|
|
78
|
+
const constantCase = (kebab) => kebab.replace(/-/g, '_').toUpperCase();
|
|
79
|
+
/**
|
|
80
|
+
* ¿El nombre de página contiene el del Block (`login-01`, `login-01-x`)? La conversión no
|
|
81
|
+
* distinguiría lo viejo de lo nuevo: `ng g mimi` lo rechaza con su propio mensaje.
|
|
82
|
+
*/
|
|
83
|
+
const isBlockLikeName = (item, name) => name === item || name.startsWith(`${item}-`);
|
|
84
|
+
exports.isBlockLikeName = isBlockLikeName;
|
|
85
|
+
/**
|
|
86
|
+
* El código de un archivo del Block convertido en el de la página: el selector `mimi-login-01`
|
|
87
|
+
* (también en los `id`) pasa a `app-login-page`; la clase `Login01` y sus tipos (`Login01Value`)
|
|
88
|
+
* a `LoginPage` (`LoginPageValue`); las constantes (`SETTINGS_01_PLAN`) a `SETTINGS_PAGE_PLAN`;
|
|
89
|
+
* los archivos propios (`./login-01.html`) a `./login.html`. Lanza un error si queda algo del
|
|
90
|
+
* nombre del Block (un Block nuevo con otra forma necesita que se revise esta función; lo prueba
|
|
91
|
+
* `pages.spec.ts` con los Blocks reales). El nombre de la página no puede contener el del Block
|
|
92
|
+
* (`--name login-01`): lo rechaza antes `isBlockLikeName`.
|
|
93
|
+
*/
|
|
94
|
+
function renderPageFile(source, target) {
|
|
95
|
+
const { item, name } = target;
|
|
96
|
+
const fromClass = pascal(item);
|
|
97
|
+
const fromConstant = constantCase(item);
|
|
98
|
+
const result = source
|
|
99
|
+
.split(`mimi-${item}`)
|
|
100
|
+
.join(pageSelector(target.prefix, name))
|
|
101
|
+
.replace(new RegExp(`(['"\`])\\./${escape(item)}\\.`, 'g'), `$1./${name}.`)
|
|
102
|
+
.replace(new RegExp(`\\b${escape(fromClass)}`, 'g'), (0, exports.pageClassName)(name))
|
|
103
|
+
.replace(new RegExp(`\\b${escape(fromConstant)}(?=_|\\b)`, 'g'), constantCase((0, exports.pageClassName)(name).replace(/([a-z0-9])([A-Z])/g, '$1-$2')));
|
|
104
|
+
const left = [`mimi-${item}`, `./${item}.`].filter((text) => result.includes(text));
|
|
105
|
+
if (new RegExp(`\\b${escape(fromClass)}`).test(result))
|
|
106
|
+
left.push(fromClass);
|
|
107
|
+
if (new RegExp(`\\b${escape(fromConstant)}(?=_|\\b)`).test(result))
|
|
108
|
+
left.push(fromConstant);
|
|
109
|
+
if (left.length > 0) {
|
|
110
|
+
throw new Error(`No se pudo convertir ${item} en una página: quedan ${left.join(', ')}. Es un error de Mimi; ` +
|
|
111
|
+
'avísanos en https://github.com/nuki23/mimi-ng/issues.');
|
|
112
|
+
}
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
/** `login.routes.ts`: la página en carga diferida, lista para `loadChildren`. */
|
|
116
|
+
function routesFile(target) {
|
|
117
|
+
const className = (0, exports.pageClassName)(target.name);
|
|
118
|
+
return [
|
|
119
|
+
"import type { Routes } from '@angular/router';",
|
|
120
|
+
'',
|
|
121
|
+
'/**',
|
|
122
|
+
` * Rutas de la página ${target.name} (${target.item} de Mimi). La página se carga al entrar en`,
|
|
123
|
+
' * ella. En app.routes.ts, con loadChildren (ng g mimi te dio la línea exacta).',
|
|
124
|
+
' */',
|
|
125
|
+
`export const ${(0, exports.routesConstName)(target.name)}: Routes = [`,
|
|
126
|
+
` { path: '', loadComponent: () => import('./${target.name}').then((m) => m.${className}) },`,
|
|
127
|
+
'];',
|
|
128
|
+
'',
|
|
129
|
+
].join('\n');
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* La línea para `app.routes.ts` (que está en `appDir`): `{ path: 'login', loadChildren: () =>
|
|
133
|
+
* import('./pages/login/login.routes').then((m) => m.LOGIN_ROUTES) },`.
|
|
134
|
+
*/
|
|
135
|
+
function routeLine(target, routesImport) {
|
|
136
|
+
return (`{ path: '${target.name}', loadChildren: () => import('${routesImport}')` +
|
|
137
|
+
`.then((m) => m.${(0, exports.routesConstName)(target.name)}) },`);
|
|
138
|
+
}
|
package/dist/utils/project.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MIMI_COLLECTION = void 0;
|
|
4
4
|
exports.defaultBlocksDir = defaultBlocksDir;
|
|
5
|
+
exports.defaultPagesDir = defaultPagesDir;
|
|
5
6
|
exports.assertAliases = assertAliases;
|
|
6
7
|
exports.readJson = readJson;
|
|
7
8
|
exports.allDependencies = allDependencies;
|
|
@@ -16,6 +17,16 @@ exports.MIMI_COLLECTION = '@mimi-ng/cli';
|
|
|
16
17
|
* de la carpeta de componentes (`src/app/ui` → `src/app/blocks`).
|
|
17
18
|
*/
|
|
18
19
|
function defaultBlocksDir(componentsDir) {
|
|
20
|
+
return siblingOfComponents(componentsDir, 'blocks');
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Carpeta de las páginas si mimi.json no la dice (B.11-b), con la misma regla que la de los
|
|
24
|
+
* Blocks: `src/app/components/ui` → `src/app/pages`.
|
|
25
|
+
*/
|
|
26
|
+
function defaultPagesDir(componentsDir) {
|
|
27
|
+
return siblingOfComponents(componentsDir, 'pages');
|
|
28
|
+
}
|
|
29
|
+
function siblingOfComponents(componentsDir, folder) {
|
|
19
30
|
const parts = componentsDir.split('/').filter(Boolean);
|
|
20
31
|
if (parts.length >= 2 && parts.at(-1) === 'ui' && parts.at(-2) === 'components') {
|
|
21
32
|
parts.splice(-2, 2);
|
|
@@ -23,25 +34,38 @@ function defaultBlocksDir(componentsDir) {
|
|
|
23
34
|
else {
|
|
24
35
|
parts.pop();
|
|
25
36
|
}
|
|
26
|
-
return [...parts,
|
|
37
|
+
return [...parts, folder].join('/');
|
|
27
38
|
}
|
|
39
|
+
const ALIAS_EXAMPLES = {
|
|
40
|
+
components: 'src/app/components/ui',
|
|
41
|
+
blocks: 'src/app/blocks',
|
|
42
|
+
pages: 'src/app/pages',
|
|
43
|
+
};
|
|
28
44
|
/**
|
|
29
|
-
* M2: falla con un error claro (sin escribir nada) si `aliases.components
|
|
30
|
-
* mimi.json
|
|
45
|
+
* M2: falla con un error claro (sin escribir nada) si `aliases.components`, `aliases.blocks` o
|
|
46
|
+
* `aliases.pages` de mimi.json, o la carpeta de una página (`blocks.<ítem>.path`, B.11), es
|
|
47
|
+
* absoluto, tiene `..` o sale del proyecto.
|
|
31
48
|
*/
|
|
32
49
|
function assertAliases(config) {
|
|
33
|
-
for (const name of ['components', 'blocks']) {
|
|
50
|
+
for (const name of ['components', 'blocks', 'pages']) {
|
|
34
51
|
const value = config.aliases?.[name];
|
|
35
52
|
if (value === undefined)
|
|
36
53
|
continue;
|
|
37
|
-
|
|
38
|
-
|
|
54
|
+
assertRelative(`aliases.${name}`, value, ALIAS_EXAMPLES[name]);
|
|
55
|
+
}
|
|
56
|
+
for (const [item, entry] of Object.entries(config.blocks ?? {})) {
|
|
57
|
+
if (entry?.path === undefined)
|
|
39
58
|
continue;
|
|
40
|
-
|
|
41
|
-
throw new schematics_1.SchematicsException(`mimi.json → aliases.${name} ${reason}: ${JSON.stringify(value)}. Usa una ruta relativa a ` +
|
|
42
|
-
`la raíz del workspace y dentro de ella (por ejemplo "${example}"). No se cambió nada.`);
|
|
59
|
+
assertRelative(`blocks.${item}.path`, entry.path, `${ALIAS_EXAMPLES.pages}/login`);
|
|
43
60
|
}
|
|
44
61
|
}
|
|
62
|
+
function assertRelative(key, value, example) {
|
|
63
|
+
const reason = (0, paths_1.invalidAliasReason)(value);
|
|
64
|
+
if (!reason)
|
|
65
|
+
return;
|
|
66
|
+
throw new schematics_1.SchematicsException(`mimi.json → ${key} ${reason}: ${JSON.stringify(value)}. Usa una ruta relativa a ` +
|
|
67
|
+
`la raíz del workspace y dentro de ella (por ejemplo "${example}"). No se cambió nada.`);
|
|
68
|
+
}
|
|
45
69
|
function readJson(tree, path) {
|
|
46
70
|
if (!tree.exists(path))
|
|
47
71
|
return null;
|
package/dist/utils/tailwind.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.tailwindSupportsSourceNot = tailwindSupportsSourceNot;
|
|
4
|
-
exports.
|
|
4
|
+
exports.withFolderSource = withFolderSource;
|
|
5
5
|
exports.mimiSourceNotLine = mimiSourceNotLine;
|
|
6
6
|
exports.mimiSourceNotPath = mimiSourceNotPath;
|
|
7
7
|
exports.missingMimiExclusion = missingMimiExclusion;
|
|
@@ -37,24 +37,28 @@ function atLeast41(version) {
|
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
39
|
* Con `source(none)`, Tailwind solo escanea lo que dice un `@source`: la carpeta de los Blocks
|
|
40
|
-
*
|
|
41
|
-
* del `@source` de
|
|
42
|
-
* ya está (comillas simples o dobles).
|
|
40
|
+
* (G1) y la de las páginas (B.11) necesitan el suyo, como la de componentes. Devuelve el CSS con
|
|
41
|
+
* la línea agregada (después del último `@source` de `afterDirs` que esté, o del tema), o `null`
|
|
42
|
+
* si no hace falta: sin `source(none)`, o si ya está (comillas simples o dobles).
|
|
43
43
|
*/
|
|
44
|
-
function
|
|
44
|
+
function withFolderSource(css, cssPath, afterDirs, dir) {
|
|
45
45
|
const tailwind = (0, css_1.findTailwindImport)(css);
|
|
46
46
|
if (!tailwind?.sourceNone)
|
|
47
47
|
return null;
|
|
48
48
|
const cssDir = (0, paths_1.dirnameOf)(cssPath);
|
|
49
|
-
const path = (0, paths_1.relativePath)(cssDir,
|
|
49
|
+
const path = (0, paths_1.relativePath)(cssDir, dir);
|
|
50
50
|
if ((0, css_1.hasDirective)(css, '@source', path))
|
|
51
51
|
return null;
|
|
52
52
|
const line = `@source "${path}";`;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
String.raw
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
let end = -1;
|
|
54
|
+
for (const after of afterDirs) {
|
|
55
|
+
const match = new RegExp(String.raw `^[ \t]*@source\s+(["'])` +
|
|
56
|
+
(0, paths_1.relativePath)(cssDir, after).replace(/[.*+?^${}()|[\]\\]/g, '\\$&') +
|
|
57
|
+
String.raw `\1[^;\n]*;[^\n]*$`, 'm').exec(css);
|
|
58
|
+
if (match)
|
|
59
|
+
end = Math.max(end, match.index + match[0].length);
|
|
60
|
+
}
|
|
61
|
+
if (end >= 0) {
|
|
58
62
|
const eol = /\r\n/.test(css) ? '\r\n' : '\n';
|
|
59
63
|
return { css: css.slice(0, end) + eol + line + css.slice(end), line };
|
|
60
64
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isBlockFile = exports.hasFileChanges = exports.emptyReport = exports.MANIFEST = exports.BASE_DIR = void 0;
|
|
3
|
+
exports.isBlockFile = exports.hasFileChanges = exports.emptyReport = exports.MANIFEST = exports.BASE_DIR = exports.itemFiles = void 0;
|
|
4
4
|
exports.projectPathOf = projectPathOf;
|
|
5
5
|
exports.targetPathOf = targetPathOf;
|
|
6
6
|
exports.basePathOf = basePathOf;
|
|
@@ -10,7 +10,14 @@ exports.compareVersions = compareVersions;
|
|
|
10
10
|
exports.updatedMessages = updatedMessages;
|
|
11
11
|
const schematics_1 = require("@angular-devkit/schematics");
|
|
12
12
|
const registry_1 = require("../registry");
|
|
13
|
+
const pages_1 = require("./pages");
|
|
13
14
|
const project_1 = require("./project");
|
|
15
|
+
/**
|
|
16
|
+
* Los archivos de un ítem: los del registro o, si se genera como página, sus claves
|
|
17
|
+
* `pages/<ítem>/…` (B.11-f).
|
|
18
|
+
*/
|
|
19
|
+
const itemFiles = (item, pages = {}) => pages[item] ? (0, pages_1.pageKeys)(item, registry_1.registry.items[item].files) : registry_1.registry.items[item].files;
|
|
20
|
+
exports.itemFiles = itemFiles;
|
|
14
21
|
/** Carpeta de las copias originales, en la raíz del workspace. Debe quedar en git. */
|
|
15
22
|
exports.BASE_DIR = '.mimi/base';
|
|
16
23
|
/** Versión de Mimi con la que se escribió la base de cada archivo. */
|
|
@@ -46,7 +53,13 @@ exports.isBlockFile = isBlockFile;
|
|
|
46
53
|
* `blocks/` (`blocks/login-01/login-01.ts` → `<blocksDir>/login-01/login-01.ts`); el resto, a la
|
|
47
54
|
* de componentes (ver projectPathOf).
|
|
48
55
|
*/
|
|
49
|
-
function targetPathOf(file, componentsDir, blocksDir) {
|
|
56
|
+
function targetPathOf(file, componentsDir, blocksDir, pages = {}) {
|
|
57
|
+
if ((0, pages_1.isPageFile)(file)) {
|
|
58
|
+
const target = pages[(0, pages_1.pageItemOf)(file)];
|
|
59
|
+
if (!target)
|
|
60
|
+
throw new Error(`Falta la carpeta de la página de ${file}.`);
|
|
61
|
+
return (0, pages_1.pageTargetPath)(file, target);
|
|
62
|
+
}
|
|
50
63
|
return (0, exports.isBlockFile)(file)
|
|
51
64
|
? `${blocksDir}/${file.slice(BLOCKS_PREFIX.length)}`
|
|
52
65
|
: `${componentsDir}/${projectPathOf(file)}`;
|
|
@@ -54,7 +67,8 @@ function targetPathOf(file, componentsDir, blocksDir) {
|
|
|
54
67
|
/**
|
|
55
68
|
* Copia original en .mimi/base, con la misma estructura (`.mimi/base/button/button.ts`). Los
|
|
56
69
|
* Blocks conservan `blocks/` (`.mimi/base/blocks/login-01/login-01.ts`), y esa es también su
|
|
57
|
-
* clave en el manifiesto.
|
|
70
|
+
* clave en el manifiesto. Las páginas van por su nombre del registro, no por el de su carpeta
|
|
71
|
+
* (`.mimi/base/pages/login-01/login-01.ts`, B.11-f).
|
|
58
72
|
*/
|
|
59
73
|
function basePathOf(file) {
|
|
60
74
|
return `${exports.BASE_DIR}/${projectPathOf(file)}`;
|
|
@@ -95,6 +109,8 @@ function readManifest(tree) {
|
|
|
95
109
|
function writeTemplates(options) {
|
|
96
110
|
const items = [...new Set(options.items)];
|
|
97
111
|
const implicit = new Set(options.implicit ?? []);
|
|
112
|
+
const pages = options.pages ?? {};
|
|
113
|
+
const filesOf = (item) => (0, exports.itemFiles)(item, pages);
|
|
98
114
|
const files = new Set(items.flatMap((item) => registry_1.registry.items[item].files));
|
|
99
115
|
const contents = new Map();
|
|
100
116
|
// 1. Lee las plantillas (sin escribir nada: forEach devuelve null).
|
|
@@ -107,9 +123,18 @@ function writeTemplates(options) {
|
|
|
107
123
|
]));
|
|
108
124
|
// 2. Decide por ítem y escribe.
|
|
109
125
|
const write = (tree) => {
|
|
126
|
+
// Las páginas: su código sale del Block, con el nombre que eligió el usuario (B.11).
|
|
127
|
+
for (const [item, target] of Object.entries(pages)) {
|
|
128
|
+
for (const file of (0, pages_1.pageSourceFiles)(registry_1.registry.items[item].files)) {
|
|
129
|
+
const source = contents.get(file);
|
|
130
|
+
if (source !== undefined)
|
|
131
|
+
contents.set((0, pages_1.pageKeyOf)(item, file), (0, pages_1.renderPageFile)(source, target));
|
|
132
|
+
}
|
|
133
|
+
contents.set((0, pages_1.routesKey)(item), (0, pages_1.routesFile)(target));
|
|
134
|
+
}
|
|
110
135
|
const manifest = readManifest(tree);
|
|
111
136
|
let manifestChanged = false;
|
|
112
|
-
const targetOf = (file) => targetPathOf(file, options.componentsDir, options.blocksDir ?? (0, project_1.defaultBlocksDir)(options.componentsDir));
|
|
137
|
+
const targetOf = (file) => targetPathOf(file, options.componentsDir, options.blocksDir ?? (0, project_1.defaultBlocksDir)(options.componentsDir), pages);
|
|
113
138
|
const stateOf = (file) => {
|
|
114
139
|
const target = targetOf(file);
|
|
115
140
|
if (!tree.exists(target))
|
|
@@ -130,7 +155,7 @@ function writeTemplates(options) {
|
|
|
130
155
|
};
|
|
131
156
|
const states = new Map(items.map((item) => [
|
|
132
157
|
item,
|
|
133
|
-
|
|
158
|
+
filesOf(item)
|
|
134
159
|
.filter((file) => contents.has(file))
|
|
135
160
|
.map((file) => ({ file, ...stateOf(file) })),
|
|
136
161
|
]));
|
|
@@ -240,8 +265,8 @@ function writeTemplates(options) {
|
|
|
240
265
|
* Los avisos de los ítems que no se escribieron (`report.blocked`): qué no se actualizó, por qué
|
|
241
266
|
* y qué hacer. Nunca dicen «actualizado».
|
|
242
267
|
*/
|
|
243
|
-
function blockedMessages(report, componentsDir, version, blocksDir = (0, project_1.defaultBlocksDir)(componentsDir)) {
|
|
244
|
-
const path = (file) => targetPathOf(file, componentsDir, blocksDir);
|
|
268
|
+
function blockedMessages(report, componentsDir, version, blocksDir = (0, project_1.defaultBlocksDir)(componentsDir), pages = {}) {
|
|
269
|
+
const path = (file) => targetPathOf(file, componentsDir, blocksDir, pages);
|
|
245
270
|
return report.blocked.map(({ item, files, dependency, installed }) => {
|
|
246
271
|
if (dependency) {
|
|
247
272
|
const needs = `necesita ${dependency} ${version}, que no se actualizó (ver el aviso de ${dependency}).`;
|
package/package.json
CHANGED