threlte-minify 0.0.1

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,49 @@
1
+ import MagicString from 'magic-string'
2
+ import { compile } from './compile.js'
3
+ import { hasDotComponent } from './hasDotComponent.js'
4
+
5
+ const tOverwrite = `
6
+ export { default as T } from './T.svelte'
7
+
8
+ export const extend = () => {
9
+ throw new Error('Threlte Minify is not compatible with the Threlte extend() function.')
10
+ }`
11
+
12
+ /**
13
+ *
14
+ * @returns {import('vite').PluginOption}
15
+ */
16
+ export const threlteMinify = () => {
17
+ return {
18
+ name: 'threlte-minify',
19
+
20
+ enforce: 'pre',
21
+
22
+ /**
23
+ *
24
+ * @param {string} src
25
+ * @param {string} id
26
+ * @returns
27
+ */
28
+ async transform(src, id) {
29
+ if (id.endsWith('.svelte') && hasDotComponent(src)) {
30
+ const { code, map } = await compile(src, id)
31
+
32
+ return {
33
+ code,
34
+ map: map?.toString(),
35
+ }
36
+ } else if (id.includes('@threlte/core') && id.endsWith('/T.js')) {
37
+ const str = new MagicString(src, { filename: id })
38
+ str.overwrite(0, src.length, tOverwrite)
39
+
40
+ return {
41
+ code: str.toString(),
42
+ map: str.generateMap(),
43
+ }
44
+ }
45
+
46
+ return Promise.resolve()
47
+ },
48
+ }
49
+ }
@@ -0,0 +1,29 @@
1
+ import MagicString from 'magic-string'
2
+ import { extractExistingImports } from './extractExistingImports.js'
3
+
4
+ /**
5
+ *
6
+ * @param {Set<string>} imports
7
+ * @param {string} content
8
+ * @param {string=} filename
9
+ * @returns {{ code: string; map: import('magic-string').SourceMap }}
10
+ */
11
+ export const insertImports = (imports, content, filename) => {
12
+ const str = new MagicString(content, { filename })
13
+ const existingImports = extractExistingImports(content, 'three')
14
+ const filteredImports = [...imports]
15
+ .filter((item) => {
16
+ if (existingImports.includes(item)) return false
17
+ return true
18
+ })
19
+ .join(', ')
20
+
21
+ if (filteredImports.length > 0) {
22
+ str.prepend(`\nimport { ${filteredImports} } from 'three'\n`)
23
+ }
24
+
25
+ return {
26
+ code: str.toString(),
27
+ map: str.generateMap(),
28
+ }
29
+ }
@@ -0,0 +1,112 @@
1
+ import MagicString from 'magic-string'
2
+ import { findImportAlias } from './findImportAlias.js'
3
+ import { parse } from 'svelte/compiler'
4
+
5
+ /**
6
+ *
7
+ * @param {Set<string>} imports A list of imports from "THREE"
8
+ * @param {string} content The stringified component
9
+ * @param {string=} filename The component filename
10
+ * @returns {{ code: string, map: import('magic-string').SourceMap }}
11
+ */
12
+ export const replaceDotComponents = (imports, content, filename) => {
13
+ const alias = findImportAlias(content, 'T')
14
+ const str = new MagicString(content, { filename })
15
+
16
+ if (!alias) {
17
+ return {
18
+ code: str.toString(),
19
+ map: str.generateMap(),
20
+ }
21
+ }
22
+
23
+ const ast = parse(content)
24
+
25
+ /**
26
+ *
27
+ * @param {string} identifier
28
+ * @returns {boolean}
29
+ */
30
+ const hasIdentifier = (identifier) => {
31
+ const escapedIdentifier = identifier.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
32
+ return new RegExp(`(?<![\\w$])${escapedIdentifier}(?![\\w$])`).test(content)
33
+ }
34
+
35
+ /**
36
+ *
37
+ * @param {string} componentName
38
+ * @returns {string}
39
+ */
40
+ const getTaggedComponentName = (componentName) => {
41
+ for (const item of imports) {
42
+ const [imported, localName] = item.split(/\s+as\s+/)
43
+ if (imported === componentName && localName) {
44
+ return localName
45
+ }
46
+ }
47
+
48
+ let suffix = 0
49
+ let taggedComponentName = `THRELTE_MINIFY__${componentName}`
50
+
51
+ while (
52
+ hasIdentifier(taggedComponentName) ||
53
+ [...imports].some((item) => {
54
+ const [, localName] = item.split(/\s+as\s+/)
55
+ return localName === taggedComponentName
56
+ })
57
+ ) {
58
+ suffix += 1
59
+ taggedComponentName = `THRELTE_MINIFY__${componentName}_${suffix}`
60
+ }
61
+
62
+ imports.add(`${componentName} as ${taggedComponentName}`)
63
+ return taggedComponentName
64
+ }
65
+
66
+ /**
67
+ *
68
+ * @param {unknown} node
69
+ * @returns {void}
70
+ */
71
+ const visit = (node) => {
72
+ if (!node || typeof node !== 'object') return
73
+
74
+ if (Array.isArray(node)) {
75
+ for (const child of node) {
76
+ visit(child)
77
+ }
78
+ return
79
+ }
80
+
81
+ if (node.type === 'InlineComponent' && node.name.startsWith(`${alias}.`)) {
82
+ const componentName = node.name.slice(alias.length + 1)
83
+ const taggedComponentName = getTaggedComponentName(componentName)
84
+ const openTagNameStart = node.start + 1
85
+ const openTagNameEnd = openTagNameStart + node.name.length
86
+
87
+ str.overwrite(openTagNameStart, openTagNameEnd, `${alias} is={${taggedComponentName}}`)
88
+
89
+ const closeTag = `</${node.name}`
90
+ const closeTagStart = content.lastIndexOf(closeTag, node.end)
91
+
92
+ if (closeTagStart > node.start) {
93
+ const closeTagNameStart = closeTagStart + 2
94
+ const closeTagNameEnd = closeTagNameStart + node.name.length
95
+ str.overwrite(closeTagNameStart, closeTagNameEnd, alias)
96
+ }
97
+ }
98
+
99
+ for (const value of Object.values(node)) {
100
+ if (value && typeof value === 'object') {
101
+ visit(value)
102
+ }
103
+ }
104
+ }
105
+
106
+ visit(ast.html)
107
+
108
+ return {
109
+ code: str.toString(),
110
+ map: str.generateMap(),
111
+ }
112
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ *
3
+ * @param {string} code
4
+ * @returns {string}
5
+ */
6
+ export const stripScriptTags = (code) => {
7
+ return code.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/giu, '')
8
+ }