lapikit 0.6.12 → 0.7.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.
@@ -30,4 +30,5 @@ export type KitComponentScan = {
30
30
  export type ComponentInfo = {
31
31
  name: string;
32
32
  ref: string;
33
+ direct?: boolean;
33
34
  };
@@ -1,5 +1,7 @@
1
1
  export declare const lapikitImportsRef = "lapikit/components";
2
2
  export declare const lapikitImportsLabsRef = "lapikit/labs/components";
3
+ export declare const lapikitComponentPaths: Readonly<Record<string, string>>;
4
+ export declare const lapikitLabsComponentPaths: Readonly<Record<string, string>>;
3
5
  export declare const lapikitComponents: readonly string[];
4
6
  export declare const lapikitLabsComponents: readonly string[];
5
7
  export declare const lapikitPlugins: {
package/dist/constants.js CHANGED
@@ -1,41 +1,39 @@
1
1
  export const lapikitImportsRef = 'lapikit/components';
2
2
  export const lapikitImportsLabsRef = 'lapikit/labs/components';
3
- export const lapikitComponents = [
4
- 'app',
5
- 'btn',
6
- 'icon',
7
- 'avatar',
8
- 'dropdown',
9
- 'popover',
10
- 'tooltip',
11
- 'textfield',
12
- 'appbar',
13
- 'btn',
14
- 'icon',
15
- 'avatar',
16
- 'toolbar',
17
- 'btn',
18
- 'icon',
19
- 'avatar',
20
- 'list',
21
- 'list-item',
22
- 'dialog',
23
- 'modal',
24
- 'accordion',
25
- 'accordion-item',
26
- 'alert',
27
- 'aspect-ratio',
28
- 'spacer',
29
- 'separator',
30
- 'chip',
31
- 'card',
32
- 'card-title',
33
- 'card-content',
34
- 'card-media',
35
- 'card-actions',
36
- 'card-container'
37
- ];
38
- export const lapikitLabsComponents = ['sheet'];
3
+ export const lapikitComponentPaths = {
4
+ app: 'app/app.svelte',
5
+ appbar: 'appbar/appbar.svelte',
6
+ btn: 'btn/btn.svelte',
7
+ icon: 'icon/icon.svelte',
8
+ avatar: 'avatar/avatar.svelte',
9
+ dropdown: 'dropdown/dropdown.svelte',
10
+ popover: 'popover/popover.svelte',
11
+ tooltip: 'tooltip/tooltip.svelte',
12
+ textfield: 'textfield/textfield.svelte',
13
+ toolbar: 'toolbar/toolbar.svelte',
14
+ list: 'list/list.svelte',
15
+ 'list-item': 'list/modules/list-item.svelte',
16
+ dialog: 'dialog/dialog.svelte',
17
+ modal: 'modal/modal.svelte',
18
+ accordion: 'accordion/accordion.svelte',
19
+ 'accordion-item': 'accordion/modules/accordion-item.svelte',
20
+ alert: 'alert/alert.svelte',
21
+ 'aspect-ratio': 'aspect-ratio/aspect-ratio.svelte',
22
+ spacer: 'spacer/spacer.svelte',
23
+ separator: 'separator/separator.svelte',
24
+ chip: 'chip/chip.svelte',
25
+ card: 'card/card.svelte',
26
+ 'card-title': 'card/modules/card-title.svelte',
27
+ 'card-content': 'card/modules/card-content.svelte',
28
+ 'card-media': 'card/modules/card-media.svelte',
29
+ 'card-actions': 'card/modules/card-actions.svelte',
30
+ 'card-container': 'card/modules/card-container.svelte'
31
+ };
32
+ export const lapikitLabsComponentPaths = {
33
+ sheet: 'sheet/sheet.svelte'
34
+ };
35
+ export const lapikitComponents = Object.keys(lapikitComponentPaths);
36
+ export const lapikitLabsComponents = Object.keys(lapikitLabsComponentPaths);
39
37
  export const lapikitPlugins = {
40
38
  repl: {
41
39
  components: ['repl'],
@@ -1,10 +1,6 @@
1
1
  import type { LapikitPreprocessOptions } from './@types/index.js';
2
- /**
3
- * componentName generates the component name used in imports
4
- * @param shortName The short name of the component
5
- * @returns The component name with "Kit" prefix and the first letter capitalized
6
- */
7
2
  export declare function componentName(shortName: string): string;
3
+ export declare function collectDeclaredIdentifiers(content: string): Set<string>;
8
4
  export declare function liliCore(options?: LapikitPreprocessOptions): {
9
5
  markup({ content }: {
10
6
  content: string;
package/dist/framework.js CHANGED
@@ -1,67 +1,107 @@
1
1
  import { decodeSourceMap } from './escaping.js';
2
- import { lapikitImportsRef, lapikitImportsLabsRef, lapikitComponents, lapikitLabsComponents, lapikitPlugins } from './constants.js';
3
- /**
4
- * componentName generates the component name used in imports
5
- * @param shortName The short name of the component
6
- * @returns The component name with "Kit" prefix and the first letter capitalized
7
- */
2
+ import { lapikitImportsRef, lapikitImportsLabsRef, lapikitComponentPaths, lapikitLabsComponentPaths, lapikitPlugins } from './constants.js';
8
3
  export function componentName(shortName) {
9
4
  const pascal = shortName.replace(/(^|-)([a-z])/g, (_, __, letter) => letter.toUpperCase());
10
5
  return 'Kit' + pascal;
11
6
  }
7
+ export function collectDeclaredIdentifiers(content) {
8
+ const declared = new Set();
9
+ const scriptRegex = /<script\b[^>]*>([\s\S]*?)<\/script>/g;
10
+ for (const [, rawScript] of content.matchAll(scriptRegex)) {
11
+ const script = rawScript.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|[^:])\/\/.*$/gm, '$1');
12
+ const importRegex = /\bimport\s+(?:type\s+)?([^'";]*?)\s+from\s*['"]/g;
13
+ for (const [, clause] of script.matchAll(importRegex)) {
14
+ const braces = clause.match(/\{([^}]*)\}/);
15
+ if (braces) {
16
+ for (const specifier of braces[1].split(',')) {
17
+ const local = specifier
18
+ .trim()
19
+ .replace(/^type\s+/, '')
20
+ .split(/\s+as\s+/)
21
+ .pop();
22
+ if (local)
23
+ declared.add(local.trim());
24
+ }
25
+ }
26
+ const outside = clause.replace(/\{[^}]*\}/, '');
27
+ const namespace = outside.match(/\*\s*as\s+([\w$]+)/);
28
+ if (namespace)
29
+ declared.add(namespace[1]);
30
+ const defaultImport = outside.match(/^\s*([\w$]+)/);
31
+ if (defaultImport)
32
+ declared.add(defaultImport[1]);
33
+ }
34
+ const declarationRegex = /\b(?:const|let|var|function|class)\s+([\w$]+)/g;
35
+ for (const [, name] of script.matchAll(declarationRegex)) {
36
+ declared.add(name);
37
+ }
38
+ }
39
+ return declared;
40
+ }
12
41
  export function liliCore(options) {
13
42
  return {
14
43
  markup({ content }) {
15
- const allComponents = [...lapikitComponents, ...lapikitLabsComponents];
16
- const componentToRef = new Map();
17
- lapikitComponents.forEach((comp) => {
18
- componentToRef.set(comp, lapikitImportsRef);
19
- });
20
- lapikitLabsComponents.forEach((comp) => {
21
- componentToRef.set(comp, lapikitImportsLabsRef);
22
- });
44
+ if (!content.includes('<kit:'))
45
+ return;
46
+ const componentInfo = new Map();
47
+ for (const [shortName, path] of Object.entries(lapikitComponentPaths)) {
48
+ componentInfo.set(shortName, {
49
+ name: componentName(shortName),
50
+ ref: `${lapikitImportsRef}/${path}`,
51
+ direct: true
52
+ });
53
+ }
54
+ for (const [shortName, path] of Object.entries(lapikitLabsComponentPaths)) {
55
+ componentInfo.set(shortName, {
56
+ name: componentName(shortName),
57
+ ref: `${lapikitImportsLabsRef}/${path}`,
58
+ direct: true
59
+ });
60
+ }
23
61
  // plugins
24
62
  if (options?.plugins) {
25
63
  options.plugins.forEach((pluginKey) => {
26
64
  const plugin = lapikitPlugins[pluginKey];
27
65
  if (plugin) {
28
66
  plugin.components.forEach((comp) => {
29
- if (!allComponents.includes(comp)) {
30
- allComponents.push(comp);
31
- }
32
- componentToRef.set(comp, plugin.ref);
67
+ componentInfo.set(comp, { name: componentName(comp), ref: plugin.ref });
33
68
  });
34
69
  }
35
70
  });
36
71
  }
37
- if (!content.includes('<kit:'))
38
- return;
39
- const componentInfo = new Map();
40
- for (const shortName of allComponents) {
41
- componentInfo.set(shortName, {
42
- name: componentName(shortName),
43
- ref: componentToRef.get(shortName) || lapikitImportsRef
44
- });
45
- }
46
72
  const scanResult = decodeSourceMap(content, componentInfo);
47
73
  if (!scanResult.changed)
48
74
  return;
49
75
  let processedContent = scanResult.code;
50
76
  const importedComponents = scanResult.importedComponents;
77
+ // components already declared by the user (manual import, alias...) are not imported again
78
+ const declared = collectDeclaredIdentifiers(content);
79
+ declared.forEach((name) => importedComponents.delete(name));
51
80
  if (importedComponents.size > 0) {
81
+ const directNames = new Set();
82
+ componentInfo.forEach((info) => {
83
+ if (info.direct)
84
+ directNames.add(info.name);
85
+ });
86
+ const directImports = [];
52
87
  const importsByRef = new Map();
53
88
  importedComponents.forEach((ref, component) => {
89
+ if (directNames.has(component)) {
90
+ directImports.push(`\n\timport ${component} from '${ref}';`);
91
+ return;
92
+ }
54
93
  if (!importsByRef.has(ref)) {
55
94
  importsByRef.set(ref, []);
56
95
  }
57
96
  importsByRef.get(ref).push(component);
58
97
  });
59
- const importLines = Array.from(importsByRef.entries())
60
- .map(([ref, components]) => {
61
- const imports = components.join(', ');
62
- return `\n\timport { ${imports} } from '${ref}';`;
63
- })
64
- .join('');
98
+ const importLines = directImports.join('') +
99
+ Array.from(importsByRef.entries())
100
+ .map(([ref, components]) => {
101
+ const imports = components.join(', ');
102
+ return `\n\timport { ${imports} } from '${ref}';`;
103
+ })
104
+ .join('');
65
105
  const scriptRegex = /<script(?![^>]*\bmodule\b)([^>]*)>/;
66
106
  const scriptMatch = processedContent.match(scriptRegex);
67
107
  if (scriptMatch && scriptMatch.index !== undefined) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lapikit",
3
- "version": "0.6.12",
3
+ "version": "0.7.0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -60,11 +60,21 @@
60
60
  "svelte": "./dist/components/index.js",
61
61
  "default": "./dist/components/index.js"
62
62
  },
63
+ "./components/*": {
64
+ "types": "./dist/components/*.d.ts",
65
+ "svelte": "./dist/components/*",
66
+ "default": "./dist/components/*"
67
+ },
63
68
  "./labs/components": {
64
69
  "types": "./dist/labs/index.d.ts",
65
70
  "svelte": "./dist/labs/index.js",
66
71
  "default": "./dist/labs/index.js"
67
72
  },
73
+ "./labs/components/*": {
74
+ "types": "./dist/labs/*.d.ts",
75
+ "svelte": "./dist/labs/*",
76
+ "default": "./dist/labs/*"
77
+ },
68
78
  "./actions": {
69
79
  "default": "./dist/hooks/actions.js"
70
80
  }