@test328932/test328933 1.0.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.
@@ -0,0 +1,7 @@
1
+ import { WebWorkerMLCEngineHandler } from '@mlc-ai/web-llm'
2
+
3
+ const handler = new WebWorkerMLCEngineHandler()
4
+
5
+ self.onmessage = (msg) => {
6
+ handler.onmessage(msg)
7
+ }
@@ -0,0 +1,46 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ function handleSaveRequest(req, res, filePath) {
5
+ if (req.method !== 'POST') {
6
+ res.statusCode = 405
7
+ res.end('Method not allowed')
8
+ return
9
+ }
10
+
11
+ let body = ''
12
+ req.on('data', chunk => { body += chunk })
13
+ req.on('end', () => {
14
+ try {
15
+ const items = JSON.parse(body)
16
+ fs.writeFileSync(filePath, JSON.stringify(items, null, 2))
17
+ res.setHeader('Content-Type', 'application/json')
18
+ res.end(JSON.stringify({ ok: true }))
19
+ } catch (e) {
20
+ res.statusCode = 400
21
+ res.end(JSON.stringify({ error: e.message }))
22
+ }
23
+ })
24
+ }
25
+
26
+ export default function saveFilePlugin() {
27
+ let rootDir = ''
28
+
29
+ return {
30
+ name: 'vite-plugin-save-file',
31
+ configResolved(config) {
32
+ rootDir = path.resolve(config.root, 'public')
33
+ },
34
+ configureServer(server) {
35
+ server.middlewares.use('/__save-list-items', (req, res) => {
36
+ if (!fs.existsSync(rootDir)) fs.mkdirSync(rootDir, { recursive: true })
37
+ handleSaveRequest(req, res, path.join(rootDir, 'listitems.json'))
38
+ })
39
+
40
+ server.middlewares.use('/__save-api-objects', (req, res) => {
41
+ if (!fs.existsSync(rootDir)) fs.mkdirSync(rootDir, { recursive: true })
42
+ handleSaveRequest(req, res, path.join(rootDir, 'apiobjects.json'))
43
+ })
44
+ },
45
+ }
46
+ }
@@ -0,0 +1,352 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { parse } from '@babel/parser'
4
+ import traverse from '@babel/traverse'
5
+ import generate from '@babel/generator'
6
+ import * as t from '@babel/types'
7
+
8
+ const traverseAst = traverse.default ?? traverse
9
+ const generateCode = generate.default ?? generate
10
+
11
+ const SOURCE_EXTENSIONS = new Set(['.tsx', '.ts', '.jsx', '.js'])
12
+ const SKIP_DIRS = new Set(['node_modules', 'dist', '.git', 'public'])
13
+ const SKIP_PATTERNS = [/\.test\./, /\.spec\./, /\.d\.ts$/, /\.config\./]
14
+
15
+ const TAILWIND_RE = /^[a-z][\w-]*(?:\s+[a-z][\w-/[\]:]*){2,}$/
16
+ const MAX_STRING_LENGTH = 100
17
+
18
+ // --- File collection ---
19
+
20
+ function collectSourceFiles(dir, root = dir) {
21
+ const results = []
22
+ let entries
23
+ try {
24
+ entries = fs.readdirSync(dir, { withFileTypes: true })
25
+ } catch {
26
+ return results
27
+ }
28
+
29
+ for (const entry of entries) {
30
+ if (entry.name.startsWith('.')) continue
31
+
32
+ const abs = path.join(dir, entry.name)
33
+ const rel = path.relative(root, abs).split(path.sep).join('/')
34
+
35
+ if (entry.isDirectory()) {
36
+ if (!SKIP_DIRS.has(entry.name)) {
37
+ results.push(...collectSourceFiles(abs, root))
38
+ }
39
+ continue
40
+ }
41
+
42
+ const ext = path.extname(entry.name)
43
+ if (!SOURCE_EXTENSIONS.has(ext)) continue
44
+ if (SKIP_PATTERNS.some(p => p.test(entry.name))) continue
45
+
46
+ results.push({ abs, rel })
47
+ }
48
+
49
+ return results.sort((a, b) => a.rel.localeCompare(b.rel))
50
+ }
51
+
52
+ // --- AST transforms ---
53
+
54
+ function isJSXFile(filename) {
55
+ return /\.[jt]sx$/.test(filename)
56
+ }
57
+
58
+ function parseCode(code, filename) {
59
+ return parse(code, {
60
+ sourceType: 'module',
61
+ plugins: [
62
+ 'jsx',
63
+ ...(filename.endsWith('.ts') || filename.endsWith('.tsx') ? ['typescript'] : []),
64
+ 'decorators-legacy',
65
+ 'classProperties',
66
+ 'optionalChaining',
67
+ 'nullishCoalescingOperator',
68
+ ],
69
+ })
70
+ }
71
+
72
+ function compressFile(code, filename) {
73
+ let ast
74
+ try {
75
+ ast = parseCode(code, filename)
76
+ } catch {
77
+ // If we can't parse it, return the raw code truncated
78
+ return `// [parse error — raw source]\n${code.slice(0, 500)}`
79
+ }
80
+
81
+ traverseAst(ast, {
82
+ // 1. Strip import paths — keep bindings only
83
+ ImportDeclaration(nodePath) {
84
+ // import { X, Y } from 'some/long/path' → import { X, Y }
85
+ // Keep the source for relative imports (they show project structure)
86
+ const src = nodePath.node.source.value
87
+ if (!src.startsWith('.') && !src.startsWith('/')) {
88
+ // External package — shorten to just the package name
89
+ const parts = src.split('/')
90
+ const pkgName = src.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0]
91
+ nodePath.node.source.value = pkgName
92
+ }
93
+ },
94
+
95
+ // 2. Strip Tailwind className values + strip large inline style objects
96
+ JSXAttribute(nodePath) {
97
+ const attrName = nodePath.node.name.name
98
+
99
+ if (attrName === 'className') {
100
+ const value = nodePath.node.value
101
+ if (t.isStringLiteral(value) && TAILWIND_RE.test(value.value)) {
102
+ value.value = '[tw]'
103
+ return
104
+ }
105
+ if (t.isJSXExpressionContainer(value)) {
106
+ const expr = value.expression
107
+ if (t.isTemplateLiteral(expr)) {
108
+ const hasTw = expr.quasis.some(q => TAILWIND_RE.test(q.value.raw.trim()))
109
+ if (hasTw) {
110
+ nodePath.node.value = t.stringLiteral('[tw]')
111
+ }
112
+ }
113
+ if (t.isCallExpression(expr)) {
114
+ const callee = expr.callee
115
+ const name = t.isIdentifier(callee) ? callee.name : null
116
+ if (name === 'cn' || name === 'clsx' || name === 'cva' || name === 'twMerge') {
117
+ nodePath.node.value = t.stringLiteral('[tw]')
118
+ }
119
+ }
120
+ }
121
+ return
122
+ }
123
+
124
+ if (attrName === 'style') {
125
+ const value = nodePath.node.value
126
+ if (!t.isJSXExpressionContainer(value)) return
127
+ const expr = value.expression
128
+ if (t.isObjectExpression(expr) && expr.properties.length > 2) {
129
+ value.expression = t.identifier('styles')
130
+ }
131
+ }
132
+ },
133
+
134
+ // 3. Collapse SVG elements
135
+ JSXElement(nodePath) {
136
+ const opening = nodePath.node.openingElement
137
+ if (t.isJSXIdentifier(opening.name) && opening.name.name === 'svg') {
138
+ nodePath.replaceWith(
139
+ t.jsxElement(
140
+ t.jsxOpeningElement(t.jsxIdentifier('svg'), [], true),
141
+ null,
142
+ [],
143
+ true,
144
+ ),
145
+ )
146
+ nodePath.skip()
147
+ }
148
+ },
149
+
150
+ // 4. Truncate long string literals
151
+ StringLiteral(nodePath) {
152
+ if (nodePath.node.value.length > MAX_STRING_LENGTH) {
153
+ if (t.isImportDeclaration(nodePath.parent)) return
154
+ nodePath.node.value = nodePath.node.value.slice(0, MAX_STRING_LENGTH) + '...'
155
+ }
156
+ },
157
+
158
+ TemplateLiteral(nodePath) {
159
+ for (const quasi of nodePath.node.quasis) {
160
+ if (quasi.value.raw.length > MAX_STRING_LENGTH) {
161
+ const truncated = quasi.value.raw.slice(0, MAX_STRING_LENGTH) + '...'
162
+ quasi.value = { raw: truncated, cooked: truncated }
163
+ }
164
+ }
165
+ },
166
+
167
+ // 6. Strip comments
168
+ enter(nodePath) {
169
+ const node = nodePath.node
170
+ if (node.leadingComments) node.leadingComments = []
171
+ if (node.trailingComments) node.trailingComments = []
172
+ if (node.innerComments) node.innerComments = []
173
+ },
174
+
175
+ // 7. Strip type annotations (keep simple ones, remove complex generics)
176
+ TSTypeAnnotation(nodePath) {
177
+ const annotation = nodePath.node.typeAnnotation
178
+ // Keep simple types like : string, : number, : boolean
179
+ if (t.isTSStringKeyword(annotation)) return
180
+ if (t.isTSNumberKeyword(annotation)) return
181
+ if (t.isTSBooleanKeyword(annotation)) return
182
+ // Remove complex types
183
+ if (t.isTSUnionType(annotation) || t.isTSIntersectionType(annotation) ||
184
+ t.isTSTypeLiteral(annotation) || t.isTSMappedType(annotation) ||
185
+ t.isTSConditionalType(annotation)) {
186
+ nodePath.remove()
187
+ }
188
+ },
189
+
190
+ // Remove type-only exports and interfaces
191
+ TSInterfaceDeclaration(nodePath) {
192
+ nodePath.remove()
193
+ },
194
+ TSTypeAliasDeclaration(nodePath) {
195
+ nodePath.remove()
196
+ },
197
+ })
198
+
199
+ const { code: output } = generateCode(ast, {
200
+ retainLines: false,
201
+ compact: false,
202
+ concise: true,
203
+ comments: false,
204
+ })
205
+
206
+ return output
207
+ }
208
+
209
+ // --- Repeated JSX siblings collapse ---
210
+
211
+ function collapseRepeatedJSX(code) {
212
+ // Post-process: detect consecutive identical JSX tags and collapse
213
+ // This is simpler as a text transform after generation
214
+ const lines = code.split('\n')
215
+ const result = []
216
+ let repeatTag = null
217
+ let repeatCount = 0
218
+
219
+ for (const line of lines) {
220
+ const tagMatch = line.match(/^\s*<(\w+)\s/)
221
+ if (tagMatch && tagMatch[1] === repeatTag) {
222
+ repeatCount++
223
+ continue
224
+ }
225
+
226
+ if (repeatCount > 0) {
227
+ result.push(`{/* ×${repeatCount} more <${repeatTag}/> */}`)
228
+ repeatCount = 0
229
+ }
230
+
231
+ repeatTag = tagMatch ? tagMatch[1] : null
232
+ result.push(line)
233
+ }
234
+
235
+ if (repeatCount > 0) {
236
+ result.push(`{/* ×${repeatCount} more <${repeatTag}/> */}`)
237
+ }
238
+
239
+ return result.join('\n')
240
+ }
241
+
242
+ // --- Main build ---
243
+
244
+ function buildCompressedSource(srcDir) {
245
+ const files = collectSourceFiles(srcDir)
246
+ const parts = []
247
+
248
+ for (const file of files) {
249
+ let code
250
+ try {
251
+ code = fs.readFileSync(file.abs, 'utf8')
252
+ } catch {
253
+ continue
254
+ }
255
+
256
+ if (!code.trim()) continue
257
+
258
+ const compressed = compressFile(code, file.rel)
259
+ const collapsed = collapseRepeatedJSX(compressed)
260
+
261
+ parts.push(`--- ${file.rel} ---\n${collapsed}`)
262
+ }
263
+
264
+ return parts.join('\n\n')
265
+ }
266
+
267
+ // --- Vite plugin ---
268
+
269
+ function sendJson(res, statusCode, body) {
270
+ res.statusCode = statusCode
271
+ res.setHeader('Content-Type', 'application/json')
272
+ res.end(JSON.stringify(body))
273
+ }
274
+
275
+ export default function sourceCompressorPlugin() {
276
+ let srcDir = ''
277
+ let cached = null
278
+
279
+ function invalidate() {
280
+ cached = null
281
+ }
282
+
283
+ function getCompressed() {
284
+ if (cached === null) {
285
+ cached = buildCompressedSource(srcDir)
286
+ }
287
+ return cached
288
+ }
289
+
290
+ return {
291
+ name: 'vite-plugin-source-compressor',
292
+ apply: 'serve',
293
+
294
+ configResolved(config) {
295
+ srcDir = path.resolve(config.root, 'src')
296
+ },
297
+
298
+ configureServer(server) {
299
+ console.log('[source-compressor] plugin loaded, srcDir:', srcDir)
300
+
301
+ // HMR channel — Vite 6 uses server.hot, older uses server.ws
302
+ const hmr = server.hot ?? server.ws
303
+
304
+ const handleChange = (filePath) => {
305
+ if (!filePath.startsWith(srcDir)) return
306
+ const ext = path.extname(filePath)
307
+ if (!SOURCE_EXTENSIONS.has(ext)) return
308
+ invalidate()
309
+ console.log('[source-compressor] invalidated, file changed:', path.relative(srcDir, filePath))
310
+
311
+ hmr.send({
312
+ type: 'custom',
313
+ event: 'source-compressed:update',
314
+ data: { timestamp: Date.now() },
315
+ })
316
+ }
317
+
318
+ server.watcher.on('change', handleChange)
319
+ server.watcher.on('add', handleChange)
320
+ server.watcher.on('unlink', handleChange)
321
+
322
+ // Build initial cache eagerly
323
+ try {
324
+ getCompressed()
325
+ console.log('[source-compressor] initial build done,', cached.length, 'chars')
326
+ } catch (e) {
327
+ console.error('[source-compressor] initial build failed:', e.message)
328
+ }
329
+
330
+ server.middlewares.use('/__source/compressed', (req, res) => {
331
+ if (req.method !== 'GET') {
332
+ sendJson(res, 405, { error: 'Method not allowed' })
333
+ return
334
+ }
335
+
336
+ try {
337
+ const compressed = getCompressed()
338
+ sendJson(res, 200, {
339
+ content: compressed,
340
+ charCount: compressed.length,
341
+ timestamp: Date.now(),
342
+ })
343
+ } catch (error) {
344
+ console.error('[source-compressor] error:', error)
345
+ sendJson(res, 500, {
346
+ error: error instanceof Error ? error.message : 'Compression failed',
347
+ })
348
+ }
349
+ })
350
+ },
351
+ }
352
+ }
@@ -0,0 +1,129 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ const BLOCKED_DIRS = new Set(['node_modules', 'dist'])
5
+
6
+ function isBlockedPathSegment(segment) {
7
+ return BLOCKED_DIRS.has(segment) || /^\.env($|\.)/.test(segment)
8
+ }
9
+
10
+ function toPosixPath(filePath) {
11
+ return filePath.split(path.sep).join('/')
12
+ }
13
+
14
+ function listSourceTree(rootDir, currentDir = rootDir) {
15
+ const entries = fs.readdirSync(currentDir, { withFileTypes: true })
16
+ const visibleEntries = entries
17
+ .filter(entry => !isBlockedPathSegment(entry.name))
18
+ .sort((a, b) => {
19
+ if (a.isDirectory() && !b.isDirectory()) return -1
20
+ if (!a.isDirectory() && b.isDirectory()) return 1
21
+ return a.name.localeCompare(b.name)
22
+ })
23
+
24
+ return visibleEntries.map(entry => {
25
+ const absolutePath = path.join(currentDir, entry.name)
26
+ const relativePath = toPosixPath(path.relative(rootDir, absolutePath))
27
+
28
+ if (entry.isDirectory()) {
29
+ return {
30
+ name: entry.name,
31
+ path: relativePath,
32
+ type: 'dir',
33
+ children: listSourceTree(rootDir, absolutePath),
34
+ }
35
+ }
36
+
37
+ return {
38
+ name: entry.name,
39
+ path: relativePath,
40
+ type: 'file',
41
+ }
42
+ })
43
+ }
44
+
45
+ function sendJson(res, statusCode, body) {
46
+ res.statusCode = statusCode
47
+ res.setHeader('Content-Type', 'application/json')
48
+ res.end(JSON.stringify(body))
49
+ }
50
+
51
+ function isSafeSourcePath(relativePath) {
52
+ if (!relativePath || relativePath.includes('\0')) return false
53
+ if (path.isAbsolute(relativePath)) return false
54
+
55
+ const normalized = path.posix.normalize(relativePath.replace(/\\/g, '/'))
56
+ if (normalized === '..' || normalized.startsWith('../')) return false
57
+
58
+ const segments = normalized.split('/').filter(Boolean)
59
+ if (segments.some(isBlockedPathSegment)) return false
60
+
61
+ return true
62
+ }
63
+
64
+ export default function sourceExplorerPlugin() {
65
+ return {
66
+ name: 'vite-plugin-source-explorer',
67
+ apply: 'serve',
68
+ configureServer(server) {
69
+ const sourceRoot = path.resolve(process.cwd(), 'src')
70
+
71
+ server.middlewares.use('/__source/tree', (req, res) => {
72
+ if (req.method !== 'GET') {
73
+ sendJson(res, 405, { error: 'Method not allowed' })
74
+ return
75
+ }
76
+
77
+ try {
78
+ const tree = listSourceTree(sourceRoot)
79
+ sendJson(res, 200, tree)
80
+ } catch (error) {
81
+ sendJson(res, 500, {
82
+ error: error instanceof Error ? error.message : 'Failed to read source tree',
83
+ })
84
+ }
85
+ })
86
+
87
+ server.middlewares.use('/__source/file', (req, res) => {
88
+ if (req.method !== 'GET') {
89
+ sendJson(res, 405, { error: 'Method not allowed' })
90
+ return
91
+ }
92
+
93
+ const requestUrl = new URL(req.url ?? '/', 'http://localhost')
94
+ const requestedPath = requestUrl.searchParams.get('path') ?? ''
95
+
96
+ if (!isSafeSourcePath(requestedPath)) {
97
+ sendJson(res, 400, { error: 'Invalid or blocked path' })
98
+ return
99
+ }
100
+
101
+ const normalizedPath = path.posix.normalize(requestedPath.replace(/\\/g, '/'))
102
+ const absolutePath = path.resolve(sourceRoot, normalizedPath)
103
+ const safeRootPrefix = `${sourceRoot}${path.sep}`
104
+ if (absolutePath !== sourceRoot && !absolutePath.startsWith(safeRootPrefix)) {
105
+ sendJson(res, 403, { error: 'Path is outside source root' })
106
+ return
107
+ }
108
+
109
+ try {
110
+ const stats = fs.statSync(absolutePath)
111
+ if (!stats.isFile()) {
112
+ sendJson(res, 400, { error: 'Path must point to a file' })
113
+ return
114
+ }
115
+
116
+ const content = fs.readFileSync(absolutePath, 'utf8')
117
+ sendJson(res, 200, {
118
+ path: toPosixPath(path.relative(sourceRoot, absolutePath)),
119
+ content,
120
+ })
121
+ } catch (error) {
122
+ sendJson(res, 404, {
123
+ error: error instanceof Error ? error.message : 'File not found',
124
+ })
125
+ }
126
+ })
127
+ },
128
+ }
129
+ }