@immense/vue-pom-generator 1.0.21 → 1.0.22

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 CHANGED
@@ -21,7 +21,11 @@ npm install @immense/vue-pom-generator
21
21
 
22
22
  ## Usage
23
23
 
24
- Exported entrypoint: `createVuePomGeneratorPlugins()`.
24
+ Exported entrypoints:
25
+
26
+ - `createVuePomGeneratorPlugins()`
27
+ - `vuePomGenerator()` (alias)
28
+ - `defineVuePomGeneratorConfig()` (typed config helper)
25
29
 
26
30
  ## Configuration
27
31
 
@@ -43,102 +47,103 @@ If `generation.playwright.fixtures` is enabled, it also emits:
43
47
 
44
48
  ```ts
45
49
  import { defineConfig } from "vite";
46
- import vue from "@vitejs/plugin-vue";
47
- import { createVuePomGeneratorPlugins } from "@immense/vue-pom-generator";
50
+ import { defineVuePomGeneratorConfig, vuePomGenerator } from "@immense/vue-pom-generator";
48
51
 
49
52
  export default defineConfig(() => {
50
53
  const vueOptions = {
51
54
  script: { defineModel: true, propsDestructure: true },
52
55
  };
53
56
 
54
- return {
55
- plugins: [
56
- ...createVuePomGeneratorPlugins({
57
- vueOptions,
58
- logging: { verbosity: "info" },
59
-
60
- injection: {
61
- // Attribute to inject/read as the test id (default: data-testid)
62
- attribute: "data-testid",
63
-
64
- // Used to classify Vue files as "views" vs components (default: src/views)
65
- viewsDir: "src/views",
66
-
67
- // Directories to scan for .vue files when building the POM library (default: ["src"])
68
- // For Nuxt, you might want ["app", "components", "pages", "layouts"]
69
- scanDirs: ["src"],
70
-
71
- // Optional: wrapper semantics for design-system components
72
- nativeWrappers: {
73
- MyButton: { role: "button" },
74
- MyInput: { role: "input" },
57
+ const pomConfig = defineVuePomGeneratorConfig({
58
+ vueOptions,
59
+ logging: { verbosity: "info" },
60
+
61
+ injection: {
62
+ // Attribute to inject/read as the test id (default: data-testid)
63
+ attribute: "data-testid",
64
+
65
+ // Used to classify Vue files as "views" vs components (default: src/views)
66
+ viewsDir: "src/views",
67
+
68
+ // Directories to scan for .vue files when building the POM library (default: ["src"])
69
+ // For Nuxt, you might want ["app", "components", "pages", "layouts"]
70
+ scanDirs: ["src"],
71
+
72
+ // Optional: wrapper semantics for design-system components
73
+ nativeWrappers: {
74
+ MyButton: { role: "button" },
75
+ MyInput: { role: "input" },
76
+ },
77
+
78
+ // Optional: opt specific components out of injection
79
+ excludeComponents: ["MyButton"],
80
+
81
+ // Optional: preserve/overwrite/error when an author already set the attribute
82
+ existingIdBehavior: "preserve",
83
+ },
84
+
85
+ generation: {
86
+ // Default: ["ts"]
87
+ emit: ["ts", "csharp"],
88
+
89
+ // C# specific configuration
90
+ csharp: {
91
+ // The namespace for generated C# classes (default: Playwright.Generated)
92
+ namespace: "MyProject.Tests.Generated",
93
+ },
94
+
95
+ // Default: tests/playwright/generated
96
+ outDir: "tests/playwright/generated",
97
+
98
+ // Controls how to handle duplicate generated member names within a single POM class.
99
+ // - "error": fail compilation
100
+ // - "warn": warn and suffix
101
+ // - "suffix": suffix silently (default)
102
+ nameCollisionBehavior: "suffix",
103
+
104
+ // Enable router introspection. When provided, router-aware POM helpers are generated.
105
+ router: {
106
+ // For standard Vue apps:
107
+ entry: "src/router.ts",
108
+ moduleShims: {
109
+ "@/config/app-insights": {
110
+ getAppInsights: () => null,
75
111
  },
76
-
77
- // Optional: opt specific components out of injection
78
- excludeComponents: ["MyButton"],
79
-
80
- // Optional: preserve/overwrite/error when an author already set the attribute
81
- existingIdBehavior: "preserve",
112
+ "@/store/pinia/app-alert-store": ["useAppAlertsStore"],
82
113
  },
83
-
84
- generation: {
85
- // Default: ["ts"]
86
- emit: ["ts", "csharp"],
87
-
88
- // C# specific configuration
89
- csharp: {
90
- // The namespace for generated C# classes (default: Playwright.Generated)
91
- namespace: "MyProject.Tests.Generated",
92
- },
93
-
94
- // Default: tests/playwright/generated
95
- outDir: "tests/playwright/generated",
96
-
97
- // Controls how to handle duplicate generated member names within a single POM class.
98
- // - "error": fail compilation
99
- // - "warn": warn and suffix
100
- // - "suffix": suffix silently (default)
101
- nameCollisionBehavior: "suffix",
102
-
103
- // Enable router introspection. When provided, router-aware POM helpers are generated.
104
- router: {
105
- // For standard Vue apps:
106
- entry: "src/router.ts",
107
- moduleShims: {
108
- "@/config/app-insights": {
109
- getAppInsights: () => null,
110
- },
111
- "@/store/pinia/app-alert-store": ["useAppAlertsStore"],
114
+ // For Nuxt apps (file-based routing):
115
+ // type: "nuxt"
116
+ },
117
+
118
+ playwright: {
119
+ fixtures: true,
120
+ customPoms: {
121
+ // Default: tests/playwright/pom/custom
122
+ dir: "tests/playwright/pom/custom",
123
+ importAliases: { MyCheckBox: "CheckboxWidget" },
124
+ attachments: [
125
+ {
126
+ className: "ConfirmationModal",
127
+ propertyName: "confirmationModal",
128
+ attachWhenUsesComponents: ["Page"],
112
129
  },
113
- // For Nuxt apps (file-based routing):
114
- // type: "nuxt"
115
- },
116
-
117
- playwright: {
118
- fixtures: true,
119
- customPoms: {
120
- // Default: tests/playwright/pom/custom
121
- dir: "tests/playwright/pom/custom",
122
- importAliases: { MyCheckBox: "CheckboxWidget" },
123
- attachments: [
124
- {
125
- className: "ConfirmationModal",
126
- propertyName: "confirmationModal",
127
- attachWhenUsesComponents: ["Page"],
128
- },
129
- ],
130
- },
131
- },
130
+ ],
132
131
  },
133
- }),
134
- vue(vueOptions),
135
- ],
132
+ },
133
+ },
134
+ });
135
+
136
+ return {
137
+ plugins: [...vuePomGenerator(pomConfig)],
136
138
  };
137
139
  });
138
140
  ```
139
141
 
140
142
  Notes:
141
143
 
144
+ - `vuePomGenerator(...)` already wires `@vitejs/plugin-vue` internally for non-Nuxt apps.
145
+ - Do not pass `vue()` into `createVuePomGeneratorPlugins(...)`; pass Vue options via `vueOptions`.
146
+
142
147
  - **Injection is enabled by plugin inclusion** (there is no longer an `injection.enabled` flag).
143
148
  - **Generation is enabled by default** and can be disabled via `generation: false`.
144
149
  - **Router-aware POM helpers are enabled** when `generation.router.entry` is provided (the generator will introspect your router).
package/RELEASE_NOTES.md CHANGED
@@ -1,31 +1,28 @@
1
- ```markdown
1
+ # Release Notes: v1.0.22
2
+
2
3
  ## Highlights
3
4
 
4
- - Added support for typed router module shims, enabling better TypeScript integration with Vue
5
- Router
6
- - Enhanced router introspection capabilities with 150+ lines of new functionality
7
- - Expanded test coverage for router introspection and options handling
8
- - Improved plugin system with updated type definitions
5
+ - 🎨 Improved plugin API ergonomics for better developer experience
6
+ - 📚 Major README documentation updates and reorganization
7
+ - 🧹 Refactored ASCII character-code helpers to reduce code duplication
8
+ - 🗑️ Removed unused Playwright fixture file (175 lines cleaned up)
9
9
 
10
10
  ## Changes
11
11
 
12
- **Router & TypeScript**
13
- - Implemented typed router module shim support
14
- - Enhanced router introspection logic with improved type inference
15
- - Updated plugin types to accommodate router module shims
16
-
17
- **Plugin System**
18
- - Updated `create-vue-pom-generator-plugins.ts` with new plugin configuration
19
- - Modified support plugins (build, dev) for typed router compatibility
20
- - Enhanced plugin type definitions
12
+ **Plugin API & Core**
13
+ - Enhanced plugin creation API in `create-vue-pom-generator-plugins.ts`
14
+ - Improved `index.ts` exports and main entry point
15
+ - Updated `transform.ts` with better handling logic
21
16
 
22
- **Testing & Documentation**
23
- - Added new test cases for router introspection (50+ lines)
24
- - Expanded options test coverage
25
- - Updated README with latest usage information
17
+ **Code Quality**
18
+ - DRY refactor of ASCII char-code helper functions across `utils.ts`, `router-introspection.ts`,
19
+ and `routing/to-directive.ts`
20
+ - Removed unused `playwright/pomFixture.ts` (175 lines)
21
+ - Updated ESLint configuration
26
22
 
27
- **Dependencies**
28
- - Version bump to 1.0.21
23
+ **Documentation & Tests**
24
+ - Significant README improvements (167 line changes)
25
+ - Expanded test coverage in `options.test.ts` (24 additions)
29
26
 
30
27
  ## Breaking Changes
31
28
 
@@ -38,7 +35,9 @@
38
35
 
39
36
  ## Testing
40
37
 
41
- Comprehensive test coverage added for router introspection functionality and options handling.
42
- All tests passing.
43
- ```
38
+ Test suite updated with additional coverage in `options.test.ts`.
39
+
40
+ ---
41
+
42
+ **Full Changelog**: v1.0.21...v1.0.22
44
43
 
@@ -1 +1 @@
1
- {"version":3,"file":"eslint.config.d.ts","sourceRoot":"","sources":["../eslint.config.ts"],"names":[],"mappings":";AAEA,wBAwFG"}
1
+ {"version":3,"file":"eslint.config.d.ts","sourceRoot":"","sources":["../eslint.config.ts"],"names":[],"mappings":";AAEA,wBA0FG"}
package/dist/index.cjs CHANGED
@@ -370,10 +370,8 @@ function toPascalCaseRouteKey(value) {
370
370
  for (let i = 0; i < value.length; i++) {
371
371
  const ch = value[i];
372
372
  const code = ch.charCodeAt(0);
373
- const isDigit = code >= 48 && code <= 57;
374
- const isUpper = code >= 65 && code <= 90;
375
- const isLower = code >= 97 && code <= 122;
376
- const isAlphaNum = isDigit || isUpper || isLower;
373
+ const isLower = isAsciiLowercaseLetterCode(code);
374
+ const isAlphaNum = isAsciiAlphaNumericCode(code);
377
375
  if (!isAlphaNum) {
378
376
  newWord = true;
379
377
  continue;
@@ -526,6 +524,21 @@ function upperFirst(value) {
526
524
  }
527
525
  return value.charAt(0).toUpperCase() + value.slice(1);
528
526
  }
527
+ function isAsciiUppercaseLetterCode(code) {
528
+ return code >= 65 && code <= 90;
529
+ }
530
+ function isAsciiLowercaseLetterCode(code) {
531
+ return code >= 97 && code <= 122;
532
+ }
533
+ function isAsciiLetterCode(code) {
534
+ return isAsciiUppercaseLetterCode(code) || isAsciiLowercaseLetterCode(code);
535
+ }
536
+ function isAsciiDigitCode(code) {
537
+ return code >= 48 && code <= 57;
538
+ }
539
+ function isAsciiAlphaNumericCode(code) {
540
+ return isAsciiLetterCode(code) || isAsciiDigitCode(code);
541
+ }
529
542
  function staticAttributeValue(value) {
530
543
  return { kind: "static", value };
531
544
  }
@@ -1557,8 +1570,8 @@ function isAllCapsOrDigits(value) {
1557
1570
  }
1558
1571
  for (let i = 0; i < value.length; i++) {
1559
1572
  const c = value.charCodeAt(i);
1560
- const isUpper = c >= 65 && c <= 90;
1561
- const isDigit = c >= 48 && c <= 57;
1573
+ const isUpper = isAsciiUppercaseLetterCode(c);
1574
+ const isDigit = isAsciiDigitCode(c);
1562
1575
  if (!isUpper && !isDigit) {
1563
1576
  return false;
1564
1577
  }
@@ -1570,17 +1583,14 @@ function startsWithDigit(value) {
1570
1583
  return false;
1571
1584
  }
1572
1585
  const c = value.charCodeAt(0);
1573
- return c >= 48 && c <= 57;
1586
+ return isAsciiDigitCode(c);
1574
1587
  }
1575
1588
  function stripNonIdentifierChars(value) {
1576
1589
  let out = "";
1577
1590
  for (let i = 0; i < value.length; i++) {
1578
1591
  const c = value.charCodeAt(i);
1579
- const isUpper = c >= 65 && c <= 90;
1580
- const isLower = c >= 97 && c <= 122;
1581
- const isDigit = c >= 48 && c <= 57;
1582
1592
  const isUnderscore = c === 95;
1583
- if (isUpper || isLower || isDigit || isUnderscore) {
1593
+ if (isAsciiAlphaNumericCode(c) || isUnderscore) {
1584
1594
  out += value[i];
1585
1595
  }
1586
1596
  }
@@ -2348,12 +2358,6 @@ function debugLog(message) {
2348
2358
  console.log(`[vue-pom-generator][router-introspection] ${message}`);
2349
2359
  }
2350
2360
  }
2351
- function isAsciiLetterCode(code) {
2352
- return code >= 65 && code <= 90 || code >= 97 && code <= 122;
2353
- }
2354
- function isAsciiDigitCode(code) {
2355
- return code >= 48 && code <= 57;
2356
- }
2357
2361
  function isIdentifierStartCode(code) {
2358
2362
  return code === 95 || code === 36 || isAsciiLetterCode(code);
2359
2363
  }
@@ -4155,15 +4159,13 @@ function tryExtractStableHintFromConditionalExpressionSource(source) {
4155
4159
  const v = value.trim();
4156
4160
  if (!v)
4157
4161
  return false;
4158
- const isAlpha = (ch) => ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122;
4159
- const isDigit = (ch) => ch >= 48 && ch <= 57;
4160
4162
  const isUnderscore = (ch) => ch === 95;
4161
4163
  const first = v.charCodeAt(0);
4162
- if (!isAlpha(first))
4164
+ if (!isAsciiLetterCode(first))
4163
4165
  return false;
4164
4166
  for (let i = 1; i < v.length; i += 1) {
4165
4167
  const ch = v.charCodeAt(i);
4166
- if (isAlpha(ch) || isDigit(ch) || isUnderscore(ch)) {
4168
+ if (isAsciiLetterCode(ch) || isAsciiDigitCode(ch) || isUnderscore(ch)) {
4167
4169
  continue;
4168
4170
  }
4169
4171
  return false;
@@ -4222,7 +4224,7 @@ function tryExtractStableHintFromConditionalExpressionSource(source) {
4222
4224
  }
4223
4225
  function tryInferNativeWrapperRoleFromSfc(tag, vueFilesPathMap) {
4224
4226
  const first = tag.charCodeAt(0);
4225
- const isUpper = first >= 65 && first <= 90;
4227
+ const isUpper = isAsciiUppercaseLetterCode(first);
4226
4228
  if (!isUpper)
4227
4229
  return null;
4228
4230
  const cached = inferredNativeWrapperConfigByTag.get(tag);
@@ -4541,7 +4543,7 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
4541
4543
  const isComponentLikeTag = (tag) => {
4542
4544
  if (!tag) return false;
4543
4545
  const first = tag.charCodeAt(0);
4544
- const isUpper = first >= 65 && first <= 90;
4546
+ const isUpper = isAsciiUppercaseLetterCode(first);
4545
4547
  return isUpper || tag.includes("-");
4546
4548
  };
4547
4549
  if (isComponentLikeTag(element.tag)) {
@@ -5603,7 +5605,29 @@ function assertRouterModuleShims(value, name) {
5603
5605
  function resolveFromProjectRoot(projectRoot, maybePath) {
5604
5606
  return path.isAbsolute(maybePath) ? maybePath : path.resolve(projectRoot, maybePath);
5605
5607
  }
5608
+ function assertNotVitePluginInstance(options) {
5609
+ const candidate = options;
5610
+ const pluginLikeKeys = [
5611
+ "name",
5612
+ "enforce",
5613
+ "apply",
5614
+ "transform",
5615
+ "resolveId",
5616
+ "load",
5617
+ "config",
5618
+ "configResolved",
5619
+ "handleHotUpdate"
5620
+ ];
5621
+ const pluginLikeKey = pluginLikeKeys.find((key) => key in candidate);
5622
+ if (!pluginLikeKey) {
5623
+ return;
5624
+ }
5625
+ throw new TypeError(
5626
+ `[vue-pom-generator] Invalid options: received an object that looks like a Vite plugin (found key: "${pluginLikeKey}"). Do not pass vue() into createVuePomGeneratorPlugins(...). Pass Vue plugin options via { vueOptions: { ... } } instead.`
5627
+ );
5628
+ }
5606
5629
  function createVuePomGeneratorPlugins(options = {}) {
5630
+ assertNotVitePluginInstance(options);
5607
5631
  const injection = options.injection ?? {};
5608
5632
  const generationSetting = options.generation;
5609
5633
  const generationOptions = generationSetting === false ? null : generationSetting ?? {};
@@ -5720,6 +5744,11 @@ function createVuePomGeneratorPlugins(options = {}) {
5720
5744
  }
5721
5745
  return resultPlugins;
5722
5746
  }
5747
+ function defineVuePomGeneratorConfig(options) {
5748
+ return options;
5749
+ }
5723
5750
  exports.createVuePomGeneratorPlugins = createVuePomGeneratorPlugins;
5724
5751
  exports.default = createVuePomGeneratorPlugins;
5752
+ exports.defineVuePomGeneratorConfig = defineVuePomGeneratorConfig;
5753
+ exports.vuePomGenerator = createVuePomGeneratorPlugins;
5725
5754
  //# sourceMappingURL=index.cjs.map