vueless 0.0.680 → 0.0.681

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.
@@ -0,0 +1,94 @@
1
+ /* eslint-disable no-console */
2
+
3
+ import { existsSync } from "node:fs";
4
+ import path from "node:path";
5
+ import { cwd } from "node:process";
6
+ import { cp, readFile, writeFile, rename } from "node:fs/promises";
7
+ import { styleText } from "node:util";
8
+
9
+ import { getDirFiles } from "../../utils/node/helper.js";
10
+ import { replaceRelativeImports } from "../utils/formatUtil.js";
11
+ import { getStorybookId, getStoryMetaKeyIndex } from "../utils/dataUtils.js";
12
+
13
+ import { SRC_COMPONENTS_PATH, COMPONENTS_PATH } from "../constants.js";
14
+ import { COMPONENTS, VUELESS_DIR, VUELESS_LOCAL_DIR } from "../../constants.js";
15
+
16
+ function getSourcePath(componentName) {
17
+ return path.join(cwd(), VUELESS_DIR, COMPONENTS[componentName]);
18
+ }
19
+
20
+ export async function copyVuelessComponent(options) {
21
+ const [componentName, newComponentName] = options;
22
+
23
+ if (!componentName) {
24
+ throw new Error("Component name is required.");
25
+ }
26
+
27
+ if (!(componentName in COMPONENTS)) {
28
+ throw new Error("There is no such component.");
29
+ }
30
+
31
+ const sourceComponentPath = getSourcePath(componentName);
32
+
33
+ const isSrcDir = existsSync(path.join(cwd(), VUELESS_LOCAL_DIR));
34
+ const destPath = isSrcDir
35
+ ? path.join(cwd(), SRC_COMPONENTS_PATH, newComponentName)
36
+ : path.join(cwd(), COMPONENTS_PATH, newComponentName);
37
+
38
+ const isComponentExists = newComponentName in COMPONENTS || existsSync(destPath);
39
+
40
+ if (isComponentExists) {
41
+ throw new Error(`Component with name ${newComponentName} alrady exists.`);
42
+ }
43
+
44
+ await cp(sourceComponentPath, destPath, { recursive: true });
45
+ await modifyCreatedComponent(destPath, componentName, newComponentName);
46
+
47
+ const successMessage = styleText(
48
+ "green",
49
+ `Success: ${componentName} was copied into ${destPath} directory.`,
50
+ );
51
+
52
+ console.log(successMessage);
53
+ }
54
+
55
+ async function modifyCreatedComponent(destPath, componentName, newComponentName) {
56
+ const destFiles = await getDirFiles(destPath, "");
57
+ const storybookId = await getStorybookId();
58
+
59
+ for await (const filePath of destFiles) {
60
+ const fileContent = await readFile(filePath, "utf-8");
61
+
62
+ let updatedContent = replaceRelativeImports(newComponentName, filePath, fileContent);
63
+ let targetPath = filePath;
64
+
65
+ if (filePath.endsWith("constants.ts")) {
66
+ updatedContent = updatedContent.replace(componentName, newComponentName);
67
+ }
68
+
69
+ if (filePath.endsWith("stories.ts")) {
70
+ const storyLines = updatedContent.split("\n");
71
+
72
+ const storyComponentImportIndex = storyLines.findIndex(
73
+ (line) => line.includes(componentName) && line.includes("import"),
74
+ );
75
+ const storyIdIndex = getStoryMetaKeyIndex(fileContent, "id");
76
+ const storyTitleIndex = getStoryMetaKeyIndex(fileContent, "title");
77
+
78
+ storyLines[storyIdIndex] = ` id: "${storybookId}",`;
79
+ storyLines[storyTitleIndex] = ` title: "Custom / ${newComponentName}",`;
80
+ storyLines[storyComponentImportIndex] =
81
+ `import ${newComponentName} from "../${newComponentName}.vue"`;
82
+
83
+ updatedContent = storyLines.join("\n").replaceAll(componentName, newComponentName);
84
+ }
85
+
86
+ if (targetPath.endsWith(`${componentName}.vue`)) {
87
+ targetPath = targetPath.replace(componentName, newComponentName);
88
+
89
+ await rename(filePath, targetPath);
90
+ }
91
+
92
+ await writeFile(targetPath, updatedContent);
93
+ }
94
+ }
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable no-console */
2
+
2
3
  import { existsSync } from "node:fs";
3
4
  import path from "node:path";
4
5
  import { cwd } from "node:process";
@@ -7,7 +8,7 @@ import { styleText } from "node:util";
7
8
 
8
9
  import { getDirFiles } from "../../utils/node/helper.js";
9
10
  import { replaceRelativeImports } from "../utils/formatUtil.js";
10
- import { getLastStorybookId } from "../utils/dataUtils.js";
11
+ import { getStorybookId } from "../utils/dataUtils.js";
11
12
 
12
13
  import { SRC_COMPONENTS_PATH, COMPONENTS_PATH } from "../constants.js";
13
14
 
@@ -20,7 +21,7 @@ export async function createVuelessComponent(options) {
20
21
  const [componentName] = options;
21
22
 
22
23
  if (!componentName) {
23
- throw new Error("Component name is required");
24
+ throw new Error("Component name is required.");
24
25
  }
25
26
 
26
27
  const isSrcDir = existsSync(path.join(cwd(), VUELESS_LOCAL_DIR));
@@ -31,7 +32,7 @@ export async function createVuelessComponent(options) {
31
32
  const isComponentExists = componentName in COMPONENTS || existsSync(destPath);
32
33
 
33
34
  if (isComponentExists) {
34
- throw new Error(`Component with name ${componentName} alrady exists`);
35
+ throw new Error(`Component with name ${componentName} alrady exists.`);
35
36
  }
36
37
 
37
38
  await cp(boilerplatePath, destPath, { recursive: true });
@@ -40,7 +41,7 @@ export async function createVuelessComponent(options) {
40
41
 
41
42
  const successMessage = styleText(
42
43
  "green",
43
- `Success: ${componentName} was created in ${destPath} directory`,
44
+ `Success: ${componentName} was created in ${destPath} directory.`,
44
45
  );
45
46
 
46
47
  console.log(successMessage);
@@ -48,7 +49,7 @@ export async function createVuelessComponent(options) {
48
49
 
49
50
  async function modifyCreatedComponent(destPath, componentName) {
50
51
  const destFiles = await getDirFiles(destPath, "");
51
- const lastStorybookId = await getLastStorybookId();
52
+ const storybookId = await getStorybookId();
52
53
 
53
54
  for await (const filePath of destFiles) {
54
55
  const fileContent = await readFile(filePath, "utf-8");
@@ -63,7 +64,7 @@ async function modifyCreatedComponent(destPath, componentName) {
63
64
  if (filePath.endsWith("stories.ts")) {
64
65
  updatedContent = updatedContent
65
66
  .replaceAll(boilerplateName, componentName)
66
- .replace("{{component_id}}", String(lastStorybookId + 10));
67
+ .replace("{{component_id}}", String(storybookId));
67
68
  }
68
69
 
69
70
  if (targetPath.endsWith(`${boilerplateName}.vue`)) {
@@ -1,7 +1,9 @@
1
1
  import { vuelssInit } from "./init.js";
2
2
  import { createVuelessComponent } from "./create.js";
3
+ import { copyVuelessComponent } from "./copy.js";
3
4
 
4
5
  export const commands = {
5
6
  init: vuelssInit,
6
7
  create: createVuelessComponent,
8
+ copy: copyVuelessComponent,
7
9
  };
@@ -16,7 +16,7 @@ export async function vuelssInit(options) {
16
16
  const isValidOptions = options.every((option) => vuelessInitOptions.includes(option));
17
17
 
18
18
  if (options.length && !isValidOptions) {
19
- throw new Error("Ivalid options were provided");
19
+ throw new Error("Ivalid options were provided.");
20
20
  }
21
21
 
22
22
  const fileExt = options.includes("--ts") ? TYPESCRIPT_EXT : JAVASCRIPT_EXT;
@@ -28,7 +28,7 @@ export async function vuelssInit(options) {
28
28
 
29
29
  const successMessage = styleText(
30
30
  "green",
31
- `Success: ${formattedDestPath.split(path.sep).at(-1)} was created in ${cwd()} directory`,
31
+ `Success: ${formattedDestPath.split(path.sep).at(-1)} was created in ${cwd()} directory.`,
32
32
  );
33
33
 
34
34
  console.log(successMessage);
@@ -10,7 +10,7 @@ import { VUELESS_DIR } from "../../constants.js";
10
10
 
11
11
  const storiesName = "stories.ts";
12
12
 
13
- export async function getLastStorybookId() {
13
+ export async function getStorybookId() {
14
14
  const srcComponentsDir = path.join(cwd(), SRC_COMPONENTS_PATH);
15
15
  const componentsDir = path.join(cwd(), COMPONENTS_PATH);
16
16
  const vuelessPackagePath = path.join(cwd(), VUELESS_DIR);
@@ -36,9 +36,8 @@ export async function getLastStorybookId() {
36
36
  for await (const storyPath of stories) {
37
37
  const storyContent = await readFile(storyPath, "utf-8");
38
38
 
39
- const storyIdLine = storyContent.split("\n").find((line, idx, array) => {
40
- return line.includes("id:") && idx && array[idx - 1].includes("export default");
41
- });
39
+ const storyIdLineIndex = getStoryMetaKeyIndex(storyContent, "id");
40
+ const storyIdLine = storyContent.split("\n").at(storyIdLineIndex);
42
41
 
43
42
  if (!storyIdLine) continue;
44
43
 
@@ -49,5 +48,36 @@ export async function getLastStorybookId() {
49
48
  }
50
49
  }
51
50
 
52
- return id;
51
+ return id + 10;
52
+ }
53
+
54
+ export function getStoryMetaKeyIndex(fileContent, key) {
55
+ const lines = fileContent.split("\n");
56
+ let insideExportBlock = false;
57
+ let bracketDepth = 0;
58
+
59
+ for (let i = 0; i < lines.length; i++) {
60
+ const line = lines[i].trim();
61
+
62
+ if (line.startsWith("export default {")) {
63
+ insideExportBlock = true;
64
+ bracketDepth = 1;
65
+ continue;
66
+ }
67
+
68
+ if (insideExportBlock) {
69
+ bracketDepth += (line.match(/{/g) || []).length;
70
+ bracketDepth -= (line.match(/}/g) || []).length;
71
+
72
+ if (bracketDepth === 1 && line.startsWith(`${key}:`)) {
73
+ return i;
74
+ }
75
+
76
+ if (bracketDepth === 0) {
77
+ break;
78
+ }
79
+ }
80
+ }
81
+
82
+ return -1; // Return -1 if no top-level `id` is found
53
83
  }
@@ -1,5 +1,7 @@
1
1
  import path from "node:path";
2
2
 
3
+ import { VUELESS_LIBRARY } from "../../constants.js";
4
+
3
5
  export function replaceRelativeImports(componentName, filePath, fileContent) {
4
6
  const isTopLevelFile = path.dirname(filePath).endsWith(componentName);
5
7
  const contentLines = fileContent.split("\n");
@@ -9,6 +11,7 @@ export function replaceRelativeImports(componentName, filePath, fileContent) {
9
11
 
10
12
  function replaceRelativeLineImports(line, isTopLevelFile) {
11
13
  const importRegex = /import\s+(?:[\w\s{},*]+)\s+from\s+(['"])(\.\.?\/.*?)(\.[tj]s)?\1(?!\?)/g;
14
+ const multiLineImportRegExp = /from\s+(['"])(\.\.?\/.*?)(\.[tj]s)?\1(?!\?)/g; // Matches import's "from" part
12
15
 
13
16
  const isTopLevelLocalImport = isTopLevelFile && !line.includes("../");
14
17
  const isInnerLocalImport =
@@ -18,6 +21,12 @@ function replaceRelativeLineImports(line, isTopLevelFile) {
18
21
  return line;
19
22
  }
20
23
 
24
+ if (line.startsWith("}")) {
25
+ return line.replace(multiLineImportRegExp, (match, quote, oldPath, ext) => {
26
+ return match.replace(oldPath + (ext || ""), VUELESS_LIBRARY);
27
+ });
28
+ }
29
+
21
30
  return line.replace(importRegex, (match, quote, oldPath, ext) => {
22
31
  const isDefaultImport = match.includes("{");
23
32
 
@@ -25,7 +34,7 @@ function replaceRelativeLineImports(line, isTopLevelFile) {
25
34
  match = defaultToNamedImport(match);
26
35
  }
27
36
 
28
- return match.replace(oldPath + (ext || ""), "vueless");
37
+ return match.replace(oldPath + (ext || ""), VUELESS_LIBRARY);
29
38
  });
30
39
  }
31
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.680",
3
+ "version": "0.0.681",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [