@ojiepermana/angular 0.1.1 → 21.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.
Files changed (133) hide show
  1. package/README.md +41 -249
  2. package/collection.json +25 -0
  3. package/fesm2022/ojiepermana-angular-chart.mjs +3714 -0
  4. package/fesm2022/ojiepermana-angular-chart.mjs.map +1 -0
  5. package/fesm2022/ojiepermana-angular-component.mjs +3463 -0
  6. package/fesm2022/ojiepermana-angular-component.mjs.map +1 -0
  7. package/fesm2022/ojiepermana-angular-generator-api.mjs +67 -0
  8. package/fesm2022/ojiepermana-angular-generator-api.mjs.map +1 -0
  9. package/fesm2022/ojiepermana-angular-layout.mjs +296 -408
  10. package/fesm2022/ojiepermana-angular-layout.mjs.map +1 -1
  11. package/fesm2022/ojiepermana-angular-navigation.mjs +2198 -404
  12. package/fesm2022/ojiepermana-angular-navigation.mjs.map +1 -1
  13. package/fesm2022/ojiepermana-angular-theme.mjs +381 -1
  14. package/fesm2022/ojiepermana-angular-theme.mjs.map +1 -1
  15. package/fesm2022/ojiepermana-angular.mjs +16 -1
  16. package/fesm2022/ojiepermana-angular.mjs.map +1 -1
  17. package/generator/api/README.md +183 -0
  18. package/generator/api/bin/schematics/init/index.js +88 -0
  19. package/generator/api/bin/schematics/sdk/index.js +58 -0
  20. package/generator/api/bin/src/config/loader.js +41 -0
  21. package/generator/api/bin/src/config/schema.js +56 -0
  22. package/generator/api/bin/src/emit/client.js +246 -0
  23. package/generator/api/bin/src/emit/metadata.js +295 -0
  24. package/generator/api/bin/src/emit/models.js +106 -0
  25. package/generator/api/bin/src/emit/navigation.js +56 -0
  26. package/generator/api/bin/src/emit/operations.js +122 -0
  27. package/generator/api/bin/src/emit/public-api.js +54 -0
  28. package/generator/api/bin/src/emit/services.js +87 -0
  29. package/generator/api/bin/src/engine.js +65 -0
  30. package/generator/api/bin/src/layout/per-domain.js +346 -0
  31. package/generator/api/bin/src/parser/bundle.js +25 -0
  32. package/generator/api/bin/src/parser/ir.js +320 -0
  33. package/generator/api/bin/src/parser/types.js +7 -0
  34. package/generator/api/bin/src/render/template.js +58 -0
  35. package/generator/api/bin/src/writer/index.js +69 -0
  36. package/generator/api/schematics/init/schema.json +19 -0
  37. package/generator/api/schematics/sdk/schema.json +19 -0
  38. package/generator/api/sdk.config.example.json +22 -0
  39. package/generator/guide/README.md +84 -0
  40. package/generator/guide/bin/schematics/build/index.js +35 -0
  41. package/generator/guide/bin/schematics/init/index.js +70 -0
  42. package/generator/guide/bin/src/config/loader.js +50 -0
  43. package/generator/guide/bin/src/config/schema.js +12 -0
  44. package/generator/guide/bin/src/engine/component.js +73 -0
  45. package/generator/guide/bin/src/engine/frontmatter.js +42 -0
  46. package/generator/guide/bin/src/engine/index.js +42 -0
  47. package/generator/guide/bin/src/engine/naming.js +39 -0
  48. package/generator/guide/bin/src/engine/render.js +18 -0
  49. package/generator/guide/bin/src/engine/routes.js +106 -0
  50. package/generator/guide/bin/src/engine/walk.js +35 -0
  51. package/generator/guide/guide.config.example.json +9 -0
  52. package/generator/guide/schematics/build/schema.json +14 -0
  53. package/generator/guide/schematics/init/schema.json +19 -0
  54. package/package.json +58 -38
  55. package/theme/styles/etos.css +38 -0
  56. package/theme/styles/index.css +32 -8
  57. package/theme/styles/themes/brand/etos/color.css +21 -0
  58. package/theme/styles/themes/brand/etos/style.css +50 -0
  59. package/theme/styles/themes/library/_components.css +63 -0
  60. package/theme/styles/themes/library/_layers.css +15 -0
  61. package/theme/styles/themes/library/_material-overrides.css +254 -0
  62. package/theme/styles/themes/library/_tokens.css +54 -0
  63. package/theme/styles/themes/library/color/amber.css +18 -0
  64. package/theme/styles/themes/library/color/blue.css +23 -0
  65. package/theme/styles/themes/library/color/green.css +18 -0
  66. package/theme/styles/themes/library/color/index.css +9 -0
  67. package/theme/styles/themes/library/color/purple.css +18 -0
  68. package/theme/styles/themes/library/color/red.css +18 -0
  69. package/theme/styles/themes/library/style/brutal.css +47 -0
  70. package/theme/styles/themes/library/style/default.css +51 -0
  71. package/theme/styles/themes/library/style/index.css +8 -0
  72. package/theme/styles/themes/library/style/sharp.css +47 -0
  73. package/theme/styles/themes/library/style/soft.css +47 -0
  74. package/theme/styles/themes/mode/dark.css +20 -0
  75. package/theme/styles/themes/mode/index.css +6 -0
  76. package/theme/styles/themes/mode/light.css +24 -0
  77. package/theme/styles/themes/taildwind.css +109 -0
  78. package/types/ojiepermana-angular-chart.d.ts +1094 -0
  79. package/types/ojiepermana-angular-component.d.ts +1174 -0
  80. package/types/ojiepermana-angular-generator-api.d.ts +85 -0
  81. package/types/ojiepermana-angular-layout.d.ts +125 -76
  82. package/types/ojiepermana-angular-navigation.d.ts +256 -116
  83. package/types/ojiepermana-angular-theme.d.ts +170 -1
  84. package/types/ojiepermana-angular.d.ts +2 -1
  85. package/fesm2022/ojiepermana-angular-internal.mjs +0 -489
  86. package/fesm2022/ojiepermana-angular-internal.mjs.map +0 -1
  87. package/fesm2022/ojiepermana-angular-navigation-horizontal.mjs +0 -721
  88. package/fesm2022/ojiepermana-angular-navigation-horizontal.mjs.map +0 -1
  89. package/fesm2022/ojiepermana-angular-navigation-vertical.mjs +0 -1647
  90. package/fesm2022/ojiepermana-angular-navigation-vertical.mjs.map +0 -1
  91. package/fesm2022/ojiepermana-angular-shell.mjs +0 -19
  92. package/fesm2022/ojiepermana-angular-shell.mjs.map +0 -1
  93. package/fesm2022/ojiepermana-angular-theme-component.mjs +0 -235
  94. package/fesm2022/ojiepermana-angular-theme-component.mjs.map +0 -1
  95. package/fesm2022/ojiepermana-angular-theme-directive.mjs +0 -29
  96. package/fesm2022/ojiepermana-angular-theme-directive.mjs.map +0 -1
  97. package/fesm2022/ojiepermana-angular-theme-service.mjs +0 -241
  98. package/fesm2022/ojiepermana-angular-theme-service.mjs.map +0 -1
  99. package/layout/README.md +0 -144
  100. package/layout/src/component/horizontal/horizontal.css +0 -130
  101. package/layout/src/component/vertical/vertical.css +0 -75
  102. package/layout/src/layout.css +0 -16
  103. package/navigation/README.md +0 -301
  104. package/navigation/horizontal/README.md +0 -49
  105. package/shell/README.md +0 -41
  106. package/styles/index.css +0 -2
  107. package/styles/resets.css +0 -22
  108. package/theme/README.md +0 -379
  109. package/theme/styles/adapters/material-ui/index.css +0 -205
  110. package/theme/styles/modes/dark.css +0 -84
  111. package/theme/styles/presets/colors/blue.css +0 -45
  112. package/theme/styles/presets/colors/brand.css +0 -52
  113. package/theme/styles/presets/colors/cyan.css +0 -45
  114. package/theme/styles/presets/colors/green.css +0 -45
  115. package/theme/styles/presets/colors/index.css +0 -7
  116. package/theme/styles/presets/colors/orange.css +0 -45
  117. package/theme/styles/presets/colors/purple.css +0 -45
  118. package/theme/styles/presets/colors/red.css +0 -45
  119. package/theme/styles/presets/styles/flat.css +0 -61
  120. package/theme/styles/presets/styles/glass.css +0 -28
  121. package/theme/styles/presets/styles/index.css +0 -2
  122. package/theme/styles/roles/index.css +0 -67
  123. package/theme/styles/tokens/foundation.css +0 -136
  124. package/theme/styles/tokens/semantic.css +0 -87
  125. package/theme/styles/utilities/index.css +0 -88
  126. package/types/ojiepermana-angular-internal.d.ts +0 -90
  127. package/types/ojiepermana-angular-navigation-horizontal.d.ts +0 -81
  128. package/types/ojiepermana-angular-navigation-vertical.d.ts +0 -262
  129. package/types/ojiepermana-angular-shell.d.ts +0 -14
  130. package/types/ojiepermana-angular-theme-component.d.ts +0 -46
  131. package/types/ojiepermana-angular-theme-directive.d.ts +0 -10
  132. package/types/ojiepermana-angular-theme-service.d.ts +0 -68
  133. /package/{navigation/vertical → chart}/README.md +0 -0
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.init = init;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const FALLBACK_TEMPLATE = {
7
+ $schema: './node_modules/@ojiepermana/angular/generator/guide/schematics/build/schema.json',
8
+ sourceDir: './docs',
9
+ outputDir: './projects/demo/library/src/app/docs',
10
+ routeFile: 'doc.routes.ts',
11
+ componentPrefix: 'Doc',
12
+ componentStyle: 'none',
13
+ routeExportName: 'DOC_ROUTES',
14
+ };
15
+ function init(options = {}) {
16
+ return (tree, context) => {
17
+ const workspaceRoot = process.cwd();
18
+ const destRelative = options.path ?? 'config/guide.config.json';
19
+ const treePath = destRelative.startsWith('/') ? destRelative : `/${destRelative}`;
20
+ if (tree.exists(treePath) && !options.force) {
21
+ throw new Error(`${destRelative} already exists. Re-run with --force to overwrite.`);
22
+ }
23
+ const content = loadTemplate(workspaceRoot, destRelative);
24
+ const buffer = Buffer.from(content, 'utf8');
25
+ if (tree.exists(treePath)) {
26
+ tree.overwrite(treePath, buffer);
27
+ context.logger.info(`[guide:init] overwrote ${destRelative}`);
28
+ }
29
+ else {
30
+ tree.create(treePath, buffer);
31
+ context.logger.info(`[guide:init] created ${destRelative}`);
32
+ }
33
+ context.logger.info(`[guide:init] edit sourceDir / outputDir, then run \`${getNextCommand(workspaceRoot)}\`.`);
34
+ };
35
+ }
36
+ function loadTemplate(workspaceRoot, destRelative) {
37
+ const candidates = [
38
+ (0, node_path_1.resolve)(workspaceRoot, 'guide.config.example.json'),
39
+ (0, node_path_1.resolve)(__dirname, '../../../guide.config.example.json'),
40
+ (0, node_path_1.resolve)(workspaceRoot, 'projects/angular/generator/guide/guide.config.example.json'),
41
+ ];
42
+ for (const candidate of candidates) {
43
+ try {
44
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(candidate, 'utf8'));
45
+ parsed.$schema = resolveSchemaPath(workspaceRoot, destRelative);
46
+ return `${JSON.stringify(parsed, null, 2)}\n`;
47
+ }
48
+ catch {
49
+ // try next
50
+ }
51
+ }
52
+ return `${JSON.stringify({ ...FALLBACK_TEMPLATE, $schema: resolveSchemaPath(workspaceRoot, destRelative) }, null, 2)}\n`;
53
+ }
54
+ function resolveSchemaPath(workspaceRoot, destRelative) {
55
+ const prefix = relativePrefix(destRelative);
56
+ if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(workspaceRoot, 'projects/angular/generator/guide/schematics/build/schema.json'))) {
57
+ return `${prefix}projects/angular/generator/guide/schematics/build/schema.json`;
58
+ }
59
+ return `${prefix}node_modules/@ojiepermana/angular/generator/guide/schematics/build/schema.json`;
60
+ }
61
+ function relativePrefix(destRelative) {
62
+ const depth = destRelative.replace(/^\/+/, '').split('/').length - 1;
63
+ return depth <= 0 ? './' : '../'.repeat(depth);
64
+ }
65
+ function getNextCommand(workspaceRoot) {
66
+ if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(workspaceRoot, 'projects/angular/collection.json'))) {
67
+ return 'bun run gen:guide';
68
+ }
69
+ return 'ng generate @ojiepermana/angular:guide';
70
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadConfig = loadConfig;
4
+ exports.resolveConfig = resolveConfig;
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ const VALID_STYLES = ['none', 'css', 'scss'];
8
+ function loadConfig(configPath, workspaceRoot) {
9
+ const absolute = (0, node_path_1.isAbsolute)(configPath) ? configPath : (0, node_path_1.resolve)(workspaceRoot, configPath);
10
+ let raw;
11
+ try {
12
+ raw = (0, node_fs_1.readFileSync)(absolute, 'utf8');
13
+ }
14
+ catch (error) {
15
+ throw new Error(`[guide] Unable to read config at ${absolute}. Run \`bun run gen:guide:init\` to scaffold one. (${error.message})`);
16
+ }
17
+ let parsed;
18
+ try {
19
+ parsed = JSON.parse(raw);
20
+ }
21
+ catch (error) {
22
+ throw new Error(`[guide] Invalid JSON in ${absolute}: ${error.message}`);
23
+ }
24
+ return resolveConfig(parsed, absolute);
25
+ }
26
+ function resolveConfig(input, configPath) {
27
+ if (!input || typeof input !== 'object') {
28
+ throw new Error(`[guide] Config at ${configPath} must be a JSON object.`);
29
+ }
30
+ if (!input.sourceDir || typeof input.sourceDir !== 'string') {
31
+ throw new Error(`[guide] "sourceDir" is required in ${configPath}.`);
32
+ }
33
+ if (!input.outputDir || typeof input.outputDir !== 'string') {
34
+ throw new Error(`[guide] "outputDir" is required in ${configPath}.`);
35
+ }
36
+ const style = input.componentStyle ?? 'none';
37
+ if (!VALID_STYLES.includes(style)) {
38
+ throw new Error(`[guide] Invalid componentStyle "${style}". Expected one of ${VALID_STYLES.join(', ')}.`);
39
+ }
40
+ return {
41
+ sourceDir: input.sourceDir,
42
+ outputDir: input.outputDir,
43
+ routeFile: input.routeFile && input.routeFile.trim() ? input.routeFile : 'doc.routes.ts',
44
+ componentPrefix: input.componentPrefix && input.componentPrefix.trim() ? input.componentPrefix : 'Doc',
45
+ componentStyle: style,
46
+ routeExportName: input.routeExportName && /^[A-Za-z_][A-Za-z0-9_]*$/.test(input.routeExportName)
47
+ ? input.routeExportName
48
+ : 'DOC_ROUTES',
49
+ };
50
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ /**
3
+ * Public configuration shape for the `guide` schematic.
4
+ *
5
+ * The schematic reads `guide.config.json` at the workspace root and produces
6
+ * standalone Angular components plus a nested `Routes` file under `outputDir`.
7
+ *
8
+ * Node / Angular CLI utilities stay in the schematic package itself. This file
9
+ * is the only surface re-exported by the secondary entry point and therefore
10
+ * MUST stay free of Node-specific imports.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildComponent = buildComponent;
4
+ const naming_1 = require("./naming");
5
+ const render_1 = require("./render");
6
+ function buildComponent(segments, frontmatter, body, config) {
7
+ const html = (0, render_1.renderMarkdown)(body);
8
+ const escaped = (0, render_1.escapeForTemplateLiteral)(html);
9
+ const className = (0, naming_1.componentClassName)(config.componentPrefix, segments);
10
+ const selector = (0, naming_1.componentSelector)(config.componentPrefix, segments);
11
+ const fileBase = (0, naming_1.componentFileBase)(segments);
12
+ const folderPath = segments.slice(0, -1).map(naming_1.toSlug).join('/');
13
+ const tsPath = joinPath(folderPath, `${fileBase}.component.ts`);
14
+ const { stylePath, styleRef, styleContent } = styleAssets(config.componentStyle, folderPath, fileBase);
15
+ const title = typeof frontmatter.title === 'string' && frontmatter.title.trim()
16
+ ? frontmatter.title.trim()
17
+ : humanizeTitle(segments);
18
+ const order = typeof frontmatter.order === 'number' ? frontmatter.order : null;
19
+ const pathOverride = typeof frontmatter.path === 'string' && frontmatter.path.trim() ? frontmatter.path.trim() : null;
20
+ const tsContent = renderComponentTs({
21
+ className,
22
+ selector,
23
+ html: escaped,
24
+ styleRef,
25
+ });
26
+ return {
27
+ className,
28
+ selector,
29
+ tsContent,
30
+ styleContent,
31
+ tsPath,
32
+ stylePath,
33
+ segments,
34
+ title,
35
+ order,
36
+ pathOverride,
37
+ };
38
+ }
39
+ function styleAssets(style, folder, fileBase) {
40
+ if (style === 'none') {
41
+ return { stylePath: null, styleRef: null, styleContent: null };
42
+ }
43
+ const ext = style === 'scss' ? 'scss' : 'css';
44
+ const stylePath = joinPath(folder, `${fileBase}.component.${ext}`);
45
+ return {
46
+ stylePath,
47
+ styleRef: `./${fileBase}.component.${ext}`,
48
+ styleContent: `:host { display: block; }\n`,
49
+ };
50
+ }
51
+ function renderComponentTs(opts) {
52
+ const styleLine = opts.styleRef ? ` styleUrl: '${opts.styleRef}',\n` : '';
53
+ return (`// Auto-generated by @ojiepermana/angular/generator/guide. Do not edit by hand.\n` +
54
+ `import { ChangeDetectionStrategy, Component } from '@angular/core';\n\n` +
55
+ `@Component({\n` +
56
+ ` selector: '${opts.selector}',\n` +
57
+ ` changeDetection: ChangeDetectionStrategy.OnPush,\n` +
58
+ styleLine +
59
+ ` template: \`${opts.html}\`,\n` +
60
+ `})\n` +
61
+ `export class ${opts.className} {}\n`);
62
+ }
63
+ function humanizeTitle(segments) {
64
+ const last = segments[segments.length - 1] ?? 'Untitled';
65
+ return last
66
+ .replace(/[-_]+/g, ' ')
67
+ .replace(/\s+/g, ' ')
68
+ .trim()
69
+ .replace(/(^|\s)\S/g, (c) => c.toUpperCase());
70
+ }
71
+ function joinPath(folder, file) {
72
+ return folder ? `${folder}/${file}` : file;
73
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseMarkdown = parseMarkdown;
4
+ const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
5
+ function parseMarkdown(source) {
6
+ const match = source.match(FRONTMATTER_RE);
7
+ if (!match) {
8
+ return { frontmatter: {}, body: source };
9
+ }
10
+ const frontmatter = parseSimpleYaml(match[1]);
11
+ const body = source.slice(match[0].length);
12
+ return { frontmatter, body };
13
+ }
14
+ function parseSimpleYaml(yaml) {
15
+ const out = {};
16
+ for (const rawLine of yaml.split(/\r?\n/)) {
17
+ const line = rawLine.trim();
18
+ if (!line || line.startsWith('#'))
19
+ continue;
20
+ const idx = line.indexOf(':');
21
+ if (idx === -1)
22
+ continue;
23
+ const key = line.slice(0, idx).trim();
24
+ let value = line.slice(idx + 1).trim();
25
+ if (!key)
26
+ continue;
27
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
28
+ value = value.slice(1, -1);
29
+ }
30
+ if (value === 'true')
31
+ out[key] = true;
32
+ else if (value === 'false')
33
+ out[key] = false;
34
+ else if (value !== '' && !Number.isNaN(Number(value)) && /^-?\d+(\.\d+)?$/.test(value)) {
35
+ out[key] = Number(value);
36
+ }
37
+ else {
38
+ out[key] = value;
39
+ }
40
+ }
41
+ return out;
42
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generate = generate;
4
+ const node_path_1 = require("node:path");
5
+ const component_1 = require("./component");
6
+ const frontmatter_1 = require("./frontmatter");
7
+ const routes_1 = require("./routes");
8
+ const walk_1 = require("./walk");
9
+ function generate(config, workspaceRoot) {
10
+ const sourceAbs = resolveUnderRoot(config.sourceDir, workspaceRoot);
11
+ const outputAbs = resolveUnderRoot(config.outputDir, workspaceRoot);
12
+ const sources = (0, walk_1.collectMarkdown)(sourceAbs);
13
+ const components = sources.map((src) => {
14
+ const { frontmatter, body } = (0, frontmatter_1.parseMarkdown)(src.content);
15
+ return (0, component_1.buildComponent)(src.segments, frontmatter, body, config);
16
+ });
17
+ const files = [];
18
+ for (const comp of components) {
19
+ files.push({ path: joinWorkspace(workspaceRoot, outputAbs, comp.tsPath), content: comp.tsContent });
20
+ if (comp.stylePath && comp.styleContent !== null) {
21
+ files.push({ path: joinWorkspace(workspaceRoot, outputAbs, comp.stylePath), content: comp.styleContent });
22
+ }
23
+ }
24
+ files.push({
25
+ path: joinWorkspace(workspaceRoot, outputAbs, config.routeFile),
26
+ content: (0, routes_1.renderRoutes)(components, config),
27
+ });
28
+ return {
29
+ config,
30
+ outputDir: outputAbs,
31
+ files,
32
+ stats: { markdown: sources.length, components: components.length, files: files.length },
33
+ };
34
+ }
35
+ function resolveUnderRoot(p, workspaceRoot) {
36
+ return (0, node_path_1.isAbsolute)(p) ? p : (0, node_path_1.resolve)(workspaceRoot, p);
37
+ }
38
+ function joinWorkspace(workspaceRoot, outputAbs, rel) {
39
+ const abs = (0, node_path_1.resolve)(outputAbs, rel);
40
+ const normalized = abs.startsWith(workspaceRoot) ? abs.slice(workspaceRoot.length + 1) : abs;
41
+ return normalized.split(/[\\/]+/).join('/');
42
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toSlug = toSlug;
4
+ exports.toPascal = toPascal;
5
+ exports.componentClassName = componentClassName;
6
+ exports.componentFileBase = componentFileBase;
7
+ exports.componentSelector = componentSelector;
8
+ function toSlug(segment) {
9
+ return segment
10
+ .toLowerCase()
11
+ .trim()
12
+ .replace(/[^a-z0-9]+/g, '-')
13
+ .replace(/^-+|-+$/g, '');
14
+ }
15
+ function toPascal(segment) {
16
+ return segment
17
+ .replace(/[^A-Za-z0-9]+/g, ' ')
18
+ .trim()
19
+ .split(/\s+/)
20
+ .map((w) => (w.length === 0 ? w : w[0].toUpperCase() + w.slice(1).toLowerCase()))
21
+ .join('');
22
+ }
23
+ function componentClassName(prefix, segments) {
24
+ const base = segments.map(toPascal).join('');
25
+ return `${prefix}${base}Component`;
26
+ }
27
+ function componentFileBase(segments) {
28
+ const last = segments[segments.length - 1] ?? 'index';
29
+ return toSlug(last) || 'index';
30
+ }
31
+ function componentSelector(prefix, segments) {
32
+ const kebabPrefix = prefix
33
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
34
+ .replace(/[^A-Za-z0-9]+/g, '-')
35
+ .replace(/^-+|-+$/g, '')
36
+ .toLowerCase() || 'doc';
37
+ const rest = segments.map(toSlug).filter(Boolean).join('-') || 'index';
38
+ return `${kebabPrefix}-${rest}`;
39
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderMarkdown = renderMarkdown;
4
+ exports.escapeForTemplateLiteral = escapeForTemplateLiteral;
5
+ const marked_1 = require("marked");
6
+ /** Render Markdown (GFM) to HTML synchronously. */
7
+ function renderMarkdown(body) {
8
+ marked_1.marked.setOptions({ gfm: true, breaks: false });
9
+ const html = marked_1.marked.parse(body, { async: false });
10
+ if (typeof html !== 'string') {
11
+ throw new Error('[guide] marked returned a non-string result; expected synchronous parse.');
12
+ }
13
+ return html.trim();
14
+ }
15
+ /** Escape backticks and `${` so HTML can be safely embedded in a TS template literal. */
16
+ function escapeForTemplateLiteral(html) {
17
+ return html.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
18
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderRoutes = renderRoutes;
4
+ const naming_1 = require("./naming");
5
+ function renderRoutes(components, config) {
6
+ const root = { segment: '', children: new Map() };
7
+ for (const comp of components) {
8
+ insert(root, comp);
9
+ }
10
+ const body = serializeChildren(root, ' ');
11
+ const exportName = config.routeExportName;
12
+ return (`// Auto-generated by @ojiepermana/angular/generator/guide. Do not edit by hand.\n` +
13
+ `import type { Routes } from '@angular/router';\n\n` +
14
+ `export const ${exportName}: Routes = [\n` +
15
+ body +
16
+ `];\n`);
17
+ }
18
+ function insert(root, comp) {
19
+ const segments = routeSegments(comp);
20
+ let node = root;
21
+ for (let i = 0; i < segments.length - 1; i++) {
22
+ const seg = segments[i];
23
+ let next = node.children.get(seg);
24
+ if (!next) {
25
+ next = { segment: seg, children: new Map() };
26
+ node.children.set(seg, next);
27
+ }
28
+ node = next;
29
+ }
30
+ const leafSeg = segments[segments.length - 1];
31
+ let leaf = node.children.get(leafSeg);
32
+ if (!leaf) {
33
+ leaf = { segment: leafSeg, children: new Map() };
34
+ node.children.set(leafSeg, leaf);
35
+ }
36
+ if (leaf.leaf) {
37
+ throw new Error(`[guide] Route conflict: two markdown files resolve to the same path "${segments.join('/') || '<root>'}".`);
38
+ }
39
+ leaf.leaf = comp;
40
+ }
41
+ function routeSegments(comp) {
42
+ // file segments without extension; handle index.md as empty path at parent level
43
+ const segs = comp.segments.slice();
44
+ const last = segs[segs.length - 1] ?? 'index';
45
+ if (comp.pathOverride !== null) {
46
+ // Override replaces the leaf segment path (keeps parent folders).
47
+ segs[segs.length - 1] = comp.pathOverride === '' ? '' : comp.pathOverride;
48
+ }
49
+ else if (/^index$/i.test(last)) {
50
+ segs[segs.length - 1] = '';
51
+ }
52
+ else {
53
+ segs[segs.length - 1] = (0, naming_1.toSlug)(last);
54
+ }
55
+ // slugify folder segments
56
+ for (let i = 0; i < segs.length - 1; i++) {
57
+ segs[i] = (0, naming_1.toSlug)(segs[i]);
58
+ }
59
+ return segs;
60
+ }
61
+ function serializeChildren(node, indent) {
62
+ const children = [...node.children.values()].sort(compareNodes);
63
+ return children.map((c) => serializeNode(c, indent)).join('');
64
+ }
65
+ function compareNodes(a, b) {
66
+ const orderA = a.leaf?.order ?? Number.POSITIVE_INFINITY;
67
+ const orderB = b.leaf?.order ?? Number.POSITIVE_INFINITY;
68
+ if (orderA !== orderB)
69
+ return orderA - orderB;
70
+ return a.segment.localeCompare(b.segment);
71
+ }
72
+ function serializeNode(node, indent) {
73
+ const next = indent + ' ';
74
+ const lines = [];
75
+ lines.push(`${indent}{`);
76
+ lines.push(`${next}path: ${JSON.stringify(node.segment)},`);
77
+ if (node.leaf) {
78
+ const comp = node.leaf;
79
+ const importPath = importSpecifier(comp.tsPath);
80
+ lines.push(`${next}loadComponent: () => import(${JSON.stringify(importPath)}).then((m) => m.${comp.className}),`);
81
+ const data = routeData(comp);
82
+ if (data)
83
+ lines.push(`${next}data: ${data},`);
84
+ }
85
+ if (node.children.size > 0) {
86
+ lines.push(`${next}children: [`);
87
+ lines.push(serializeChildren(node, next + ' ').replace(/\n+$/, ''));
88
+ lines.push(`${next}],`);
89
+ }
90
+ lines.push(`${indent}},`);
91
+ return lines.join('\n') + '\n';
92
+ }
93
+ function routeData(comp) {
94
+ const parts = [];
95
+ if (comp.title)
96
+ parts.push(`title: ${JSON.stringify(comp.title)}`);
97
+ if (comp.order !== null)
98
+ parts.push(`order: ${comp.order}`);
99
+ if (parts.length === 0)
100
+ return null;
101
+ return `{ ${parts.join(', ')} }`;
102
+ }
103
+ function importSpecifier(tsPath) {
104
+ const noExt = tsPath.replace(/\.ts$/i, '');
105
+ return `./${noExt}`;
106
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectMarkdown = collectMarkdown;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ function collectMarkdown(sourceDir) {
7
+ const out = [];
8
+ walk(sourceDir, sourceDir, out);
9
+ return out.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
10
+ }
11
+ function walk(root, dir, out) {
12
+ const entries = (0, node_fs_1.readdirSync)(dir, { withFileTypes: true });
13
+ for (const entry of entries) {
14
+ const abs = (0, node_path_1.join)(dir, entry.name);
15
+ if (entry.isDirectory()) {
16
+ walk(root, abs, out);
17
+ continue;
18
+ }
19
+ if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.md'))
20
+ continue;
21
+ const st = (0, node_fs_1.statSync)(abs);
22
+ if (!st.isFile())
23
+ continue;
24
+ const rel = (0, node_path_1.relative)(root, abs)
25
+ .split(/[\\/]+/)
26
+ .join('/');
27
+ const segments = rel.replace(/\.md$/i, '').split('/');
28
+ out.push({
29
+ absolutePath: abs,
30
+ relativePath: rel,
31
+ segments,
32
+ content: (0, node_fs_1.readFileSync)(abs, 'utf8'),
33
+ });
34
+ }
35
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "./node_modules/@ojiepermana/angular/generator/guide/schematics/build/schema.json",
3
+ "sourceDir": "./docs",
4
+ "outputDir": "./projects/demo/library/src/app/docs",
5
+ "routeFile": "doc.routes.ts",
6
+ "componentPrefix": "Doc",
7
+ "componentStyle": "none",
8
+ "routeExportName": "DOC_ROUTES"
9
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "GuideBuildSchema",
4
+ "title": "Guide · build",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "config": {
9
+ "type": "string",
10
+ "description": "Path to the guide config file, relative to the workspace root.",
11
+ "default": "config/guide.config.json"
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "GuideInitSchema",
4
+ "title": "Guide · init",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "path": {
9
+ "type": "string",
10
+ "description": "Destination path for the generated guide.config.json, relative to the workspace root.",
11
+ "default": "config/guide.config.json"
12
+ },
13
+ "force": {
14
+ "type": "boolean",
15
+ "description": "Overwrite an existing guide.config.json.",
16
+ "default": false
17
+ }
18
+ }
19
+ }
package/package.json CHANGED
@@ -1,24 +1,58 @@
1
1
  {
2
2
  "name": "@ojiepermana/angular",
3
- "version": "0.1.1",
4
- "publishConfig": {
5
- "access": "public"
3
+ "version": "21.0.2",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/ojiepermana/angular.git"
7
+ },
8
+ "homepage": "https://github.com/ojiepermana/angular#readme",
9
+ "bugs": {
10
+ "url": "https://github.com/ojiepermana/angular/issues"
6
11
  },
7
12
  "peerDependencies": {
8
13
  "@angular/common": "^21.2.0",
9
14
  "@angular/core": "^21.2.0",
10
- "@angular/material": "^21.0.0",
11
- "@angular/cdk": "^21.0.0",
12
- "@lucide/angular": ">=1.0.0",
13
- "tailwindcss": ">=4.0.0"
15
+ "@angular/forms": "^21.2.0",
16
+ "@angular/router": "^21.2.0",
17
+ "@angular/cdk": "^21.2.7",
18
+ "@angular/material": "^21.2.7",
19
+ "rxjs": "~7.8.0"
20
+ },
21
+ "peerDependenciesMeta": {
22
+ "@angular/forms": {
23
+ "optional": true
24
+ },
25
+ "@angular/router": {
26
+ "optional": true
27
+ },
28
+ "@angular/cdk": {
29
+ "optional": true
30
+ },
31
+ "@angular/material": {
32
+ "optional": true
33
+ }
14
34
  },
15
35
  "dependencies": {
16
- "tslib": "^2.8.1"
36
+ "class-variance-authority": "^0.7.1",
37
+ "clsx": "^2.1.1",
38
+ "d3-array": "^3.2.4",
39
+ "d3-scale": "^4.0.2",
40
+ "d3-shape": "^3.2.0",
41
+ "marked": "^16.0.0",
42
+ "tailwind-merge": "^3.5.0",
43
+ "tslib": "^2.8.1",
44
+ "yaml": "^2.8.3"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public",
48
+ "registry": "https://registry.npmjs.org/"
17
49
  },
18
50
  "sideEffects": false,
19
- "module": "fesm2022/ojiepermana-angular.mjs",
20
- "typings": "types/ojiepermana-angular.d.ts",
51
+ "schematics": "./collection.json",
21
52
  "exports": {
53
+ "./theme/styles": "./theme/styles/index.css",
54
+ "./theme/styles/*": "./theme/styles/*",
55
+ "./theme/tailwind/theme.css": "./theme/styles/themes/taildwind.css",
22
56
  "./package.json": {
23
57
  "default": "./package.json"
24
58
  },
@@ -26,9 +60,17 @@
26
60
  "types": "./types/ojiepermana-angular.d.ts",
27
61
  "default": "./fesm2022/ojiepermana-angular.mjs"
28
62
  },
29
- "./internal": {
30
- "types": "./types/ojiepermana-angular-internal.d.ts",
31
- "default": "./fesm2022/ojiepermana-angular-internal.mjs"
63
+ "./chart": {
64
+ "types": "./types/ojiepermana-angular-chart.d.ts",
65
+ "default": "./fesm2022/ojiepermana-angular-chart.mjs"
66
+ },
67
+ "./component": {
68
+ "types": "./types/ojiepermana-angular-component.d.ts",
69
+ "default": "./fesm2022/ojiepermana-angular-component.mjs"
70
+ },
71
+ "./generator/api": {
72
+ "types": "./types/ojiepermana-angular-generator-api.d.ts",
73
+ "default": "./fesm2022/ojiepermana-angular-generator-api.mjs"
32
74
  },
33
75
  "./layout": {
34
76
  "types": "./types/ojiepermana-angular-layout.d.ts",
@@ -38,34 +80,12 @@
38
80
  "types": "./types/ojiepermana-angular-navigation.d.ts",
39
81
  "default": "./fesm2022/ojiepermana-angular-navigation.mjs"
40
82
  },
41
- "./navigation/horizontal": {
42
- "types": "./types/ojiepermana-angular-navigation-horizontal.d.ts",
43
- "default": "./fesm2022/ojiepermana-angular-navigation-horizontal.mjs"
44
- },
45
- "./navigation/vertical": {
46
- "types": "./types/ojiepermana-angular-navigation-vertical.d.ts",
47
- "default": "./fesm2022/ojiepermana-angular-navigation-vertical.mjs"
48
- },
49
- "./shell": {
50
- "types": "./types/ojiepermana-angular-shell.d.ts",
51
- "default": "./fesm2022/ojiepermana-angular-shell.mjs"
52
- },
53
83
  "./theme": {
54
84
  "types": "./types/ojiepermana-angular-theme.d.ts",
55
85
  "default": "./fesm2022/ojiepermana-angular-theme.mjs"
56
- },
57
- "./theme/component": {
58
- "types": "./types/ojiepermana-angular-theme-component.d.ts",
59
- "default": "./fesm2022/ojiepermana-angular-theme-component.mjs"
60
- },
61
- "./theme/directive": {
62
- "types": "./types/ojiepermana-angular-theme-directive.d.ts",
63
- "default": "./fesm2022/ojiepermana-angular-theme-directive.mjs"
64
- },
65
- "./theme/service": {
66
- "types": "./types/ojiepermana-angular-theme-service.d.ts",
67
- "default": "./fesm2022/ojiepermana-angular-theme-service.mjs"
68
86
  }
69
87
  },
88
+ "module": "fesm2022/ojiepermana-angular.mjs",
89
+ "typings": "types/ojiepermana-angular.d.ts",
70
90
  "type": "module"
71
- }
91
+ }