@sfgrp/taxonpages 0.1.1 → 0.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sfgrp/taxonpages",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "CLI tool for building taxon pages powered by SpeciesFileGroup",
5
5
  "type": "module",
6
6
  "private": false,
@@ -1,87 +1,117 @@
1
1
  /**
2
- * Vite plugin that replaces import.meta.glob calls in component
3
- * registration files with pre-resolved absolute paths.
2
+ * Vite plugin that resolves import.meta.glob calls containing @/ or ~/
3
+ * aliases into pre-resolved absolute paths.
4
4
  *
5
- * This is necessary because import.meta.glob with aliases (@/, ~/)
6
- * won't scan inside node_modules when the package is installed
7
- * as a dependency.
5
+ * This is necessary because import.meta.glob with aliases pointing into
6
+ * node_modules won't scan those directories. This plugin intercepts the
7
+ * glob calls, performs the scanning with absolute paths, and replaces
8
+ * the call with a pre-built object of lazy imports.
8
9
  */
9
- import { resolve } from 'node:path'
10
+ import { resolve, dirname } from 'node:path'
10
11
  import { globSync } from 'glob'
11
12
 
12
- const GLOBAL_PATTERNS = [
13
- 'src/components/**/*.global.vue',
14
- 'src/modules/**/components/**/*.global.vue'
15
- ]
16
-
17
- const CLIENT_PATTERNS = [
18
- 'src/components/**/*.client.vue',
19
- 'src/modules/**/components/**/*.client.vue'
20
- ]
21
-
22
- const USER_GLOBAL_PATTERNS = [
23
- 'components/**/*.global.vue',
24
- 'modules/**/components/**/*.global.vue'
25
- ]
26
-
27
- const USER_CLIENT_PATTERNS = [
28
- 'components/**/*.client.vue',
29
- 'modules/**/components/**/*.client.vue'
30
- ]
31
-
32
- function findComponents(baseDir, patterns) {
33
- const files = []
34
-
35
- for (const pattern of patterns) {
36
- const matches = globSync(pattern, { cwd: baseDir })
37
- files.push(...matches.map((f) => resolve(baseDir, f)))
38
- }
39
-
40
- return files
41
- }
42
-
43
- function buildGlobObject(files) {
44
- return (
45
- '{\n' +
46
- files
47
- .map((f) => ` '${f}': () => import('${f}')`)
48
- .join(',\n') +
49
- '\n}'
50
- )
51
- }
13
+ const STYLE_EXT = /\.(css|scss|sass|less|styl)$/
52
14
 
53
15
  export function componentRegistrationPlugin({ packageRoot, projectRoot }) {
16
+ const srcPath = resolve(packageRoot, 'src')
17
+
54
18
  return {
55
- name: 'taxonpages:component-registration',
19
+ name: 'taxonpages:resolve-glob-aliases',
56
20
  enforce: 'pre',
57
21
  transform(code, id) {
58
- if (
59
- !id.includes('globalComponents') &&
60
- !id.includes('clientComponents')
61
- ) {
62
- return
63
- }
64
-
65
22
  if (!code.includes('import.meta.glob')) return
66
23
 
67
- const isGlobal = id.includes('globalComponents')
68
- const pkgPatterns = isGlobal ? GLOBAL_PATTERNS : CLIENT_PATTERNS
69
- const userPatterns = isGlobal ? USER_GLOBAL_PATTERNS : USER_CLIENT_PATTERNS
70
-
71
- const pkgFiles = findComponents(packageRoot, pkgPatterns)
72
- const userFiles = findComponents(projectRoot, userPatterns)
73
- const allFiles = [...pkgFiles, ...userFiles]
24
+ let changed = false
25
+ let prependImports = ''
26
+ let varCounter = 0
74
27
 
75
- const globObject = buildGlobObject(allFiles)
28
+ const globRegex =
29
+ /import\.meta\.glob\(\s*(\[[\s\S]*?\]|['"][^'"]*['"])\s*(?:,\s*(\{[\s\S]*?\}))?\s*\)/g
76
30
 
77
31
  const transformed = code.replace(
78
- /import\.meta\.glob\(\s*\[[\s\S]*?\]\s*,\s*\{[\s\S]*?\}\s*\)/,
79
- globObject
32
+ globRegex,
33
+ (match, patternsStr, optionsStr) => {
34
+ if (!patternsStr.includes('@/') && !patternsStr.includes('~/')) {
35
+ return match
36
+ }
37
+
38
+ const patternMatches = [
39
+ ...patternsStr.matchAll(/['"]([^'"]+)['"]/g)
40
+ ]
41
+ const patterns = patternMatches.map((m) => m[1])
42
+
43
+ const isEager = optionsStr && /eager\s*:\s*true/.test(optionsStr)
44
+ const importDefault =
45
+ optionsStr && /import\s*:\s*['"]default['"]/.test(optionsStr)
46
+
47
+ const allFiles = []
48
+
49
+ // Resolve the directory of the file being transformed
50
+ const fileDir = dirname(id.replace(/\?.*$/, ''))
51
+
52
+ for (const pattern of patterns) {
53
+ let baseDir
54
+ let resolvedPattern
55
+
56
+ if (pattern.startsWith('@/')) {
57
+ baseDir = srcPath
58
+ resolvedPattern = pattern.slice(2)
59
+ } else if (pattern.startsWith('~/')) {
60
+ baseDir = projectRoot
61
+ resolvedPattern = pattern.slice(2)
62
+ } else if (pattern.startsWith('./') || pattern.startsWith('../')) {
63
+ baseDir = fileDir
64
+ resolvedPattern = pattern
65
+ } else {
66
+ continue
67
+ }
68
+
69
+ const matches = globSync(resolvedPattern, { cwd: baseDir })
70
+ allFiles.push(...matches.map((f) => resolve(baseDir, f)))
71
+ }
72
+
73
+ changed = true
74
+
75
+ if (allFiles.length === 0) return '{}'
76
+
77
+ if (isEager) {
78
+ const allStyles = allFiles.every((f) => STYLE_EXT.test(f))
79
+
80
+ if (allStyles) {
81
+ // Style files: generate side-effect imports
82
+ prependImports += allFiles
83
+ .map((f) => `import '${f}';`)
84
+ .join('\n') + '\n'
85
+ return '{}'
86
+ }
87
+
88
+ const entries = allFiles.map((f) => {
89
+ const varName = `__glob_${varCounter++}`
90
+ prependImports += importDefault
91
+ ? `import { default as ${varName} } from '${f}';\n`
92
+ : `import * as ${varName} from '${f}';\n`
93
+ return ` '${f}': ${varName}`
94
+ })
95
+
96
+ return '{\n' + entries.join(',\n') + '\n}'
97
+ }
98
+
99
+ const entries = allFiles.map((f) => {
100
+ const suffix = importDefault ? '.then(m => m.default)' : ''
101
+ return ` '${f}': () => import('${f}')${suffix}`
102
+ })
103
+
104
+ return '{\n' + entries.join(',\n') + '\n}'
105
+ }
80
106
  )
81
107
 
82
- if (transformed === code) return
108
+ if (!changed) return
109
+
110
+ const result = prependImports
111
+ ? prependImports + transformed
112
+ : transformed
83
113
 
84
- return { code: transformed, map: null }
114
+ return { code: result, map: null }
85
115
  }
86
116
  }
87
117
  }