@neuxnet/neux-cli 0.2.4 → 0.2.5

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,63 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://neuxnet.com/schemas/neux/app.schema.json",
4
+ "title": "Neux app configuration",
5
+ "description": "Application-level configuration consumed by the Neux mini program compiler.",
6
+ "type": "object",
7
+ "properties": {
8
+ "pages": { "type": "array", "description": "Page entry paths, relative to miniprogramRoot.", "items": { "type": "string", "minLength": 1 } },
9
+ "entryPagePath": { "type": "string", "description": "Optional initial page path." },
10
+ "window": { "$ref": "#/definitions/window" },
11
+ "tabBar": { "$ref": "#/definitions/tabBar" },
12
+ "subPackages": { "$ref": "#/definitions/subPackages" },
13
+ "subpackages": { "$ref": "#/definitions/subPackages" },
14
+ "preloadRule": { "type": "object", "description": "Page preload configuration.", "additionalProperties": { "type": "object" } },
15
+ "networkTimeout": { "type": "object", "properties": { "request": { "type": "number", "minimum": 0 }, "connectSocket": { "type": "number", "minimum": 0 }, "uploadFile": { "type": "number", "minimum": 0 }, "downloadFile": { "type": "number", "minimum": 0 } }, "additionalProperties": true },
16
+ "permission": { "type": "object", "description": "Permission declarations used by the host runtime.", "additionalProperties": true },
17
+ "usingComponents": { "$ref": "#/definitions/usingComponents" },
18
+ "style": { "type": "string" },
19
+ "sitemapLocation": { "type": "string" }
20
+ },
21
+ "additionalProperties": true,
22
+ "definitions": {
23
+ "window": {
24
+ "type": "object",
25
+ "properties": {
26
+ "navigationBarTitleText": { "type": "string" },
27
+ "navigationBarBackgroundColor": { "type": "string", "pattern": "^#?[0-9a-fA-F]{3,8}$" },
28
+ "navigationBarTextStyle": { "type": "string", "enum": ["black", "white"] },
29
+ "backgroundColor": { "type": "string", "pattern": "^#?[0-9a-fA-F]{3,8}$" },
30
+ "backgroundTextStyle": { "type": "string", "enum": ["dark", "light"] },
31
+ "enablePullDownRefresh": { "type": "boolean" },
32
+ "onReachBottomDistance": { "type": "number", "minimum": 0 },
33
+ "pageOrientation": { "type": "string" }
34
+ },
35
+ "additionalProperties": true
36
+ },
37
+ "tabBar": {
38
+ "type": "object",
39
+ "properties": {
40
+ "color": { "type": "string" },
41
+ "selectedColor": { "type": "string" },
42
+ "backgroundColor": { "type": "string" },
43
+ "borderStyle": { "type": "string", "enum": ["black", "white"] },
44
+ "position": { "type": "string", "enum": ["bottom", "top"] },
45
+ "custom": { "type": "boolean" },
46
+ "list": { "type": "array", "minItems": 1, "maxItems": 5, "items": { "$ref": "#/definitions/tabBarItem" } }
47
+ },
48
+ "required": ["list"],
49
+ "additionalProperties": true
50
+ },
51
+ "tabBarItem": {
52
+ "type": "object",
53
+ "properties": { "pagePath": { "type": "string" }, "text": { "type": "string" }, "iconPath": { "type": "string" }, "selectedIconPath": { "type": "string" } },
54
+ "required": ["pagePath", "text"],
55
+ "additionalProperties": true
56
+ },
57
+ "subPackages": {
58
+ "type": "array",
59
+ "items": { "type": "object", "properties": { "root": { "type": "string" }, "pages": { "type": "array", "items": { "type": "string" } }, "independent": { "type": "boolean" } }, "required": ["root", "pages"], "additionalProperties": true }
60
+ },
61
+ "usingComponents": { "type": "object", "description": "Maps component names to component files or package names.", "additionalProperties": { "type": "string", "minLength": 1 } }
62
+ }
63
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://neuxnet.com/schemas/neux/neux-config.schema.json",
4
+ "title": "Neux CLI project configuration",
5
+ "description": "Non-secret project settings read by the Neux CLI. Never put CLI keys in this file.",
6
+ "type": "object",
7
+ "properties": {
8
+ "serverUrl": { "type": "string", "format": "uri", "description": "Signed service base URL." },
9
+ "appId": { "type": "string" },
10
+ "appid": { "type": "string" },
11
+ "profile": { "type": "string" },
12
+ "version": { "type": "string" },
13
+ "versionName": { "type": "string" },
14
+ "versionCode": { "type": "integer", "minimum": 1 }
15
+ },
16
+ "not": { "anyOf": [ { "required": ["key"] }, { "required": ["cliKey"] }, { "required": ["neuxCliKey"] } ] },
17
+ "additionalProperties": true
18
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://neuxnet.com/schemas/neux/page.schema.json",
4
+ "title": "Neux page configuration",
5
+ "description": "Page-level configuration consumed by the Neux mini program compiler.",
6
+ "type": "object",
7
+ "properties": {
8
+ "navigationBarTitleText": { "type": "string" },
9
+ "navigationBarBackgroundColor": { "type": "string" },
10
+ "navigationBarTextStyle": { "type": "string", "enum": ["black", "white"] },
11
+ "backgroundColor": { "type": "string" },
12
+ "backgroundTextStyle": { "type": "string", "enum": ["dark", "light"] },
13
+ "enablePullDownRefresh": { "type": "boolean" },
14
+ "onReachBottomDistance": { "type": "number", "minimum": 0 },
15
+ "usingComponents": { "type": "object", "additionalProperties": { "type": "string", "minLength": 1 } },
16
+ "disableScroll": { "type": "boolean" },
17
+ "pageOrientation": { "type": "string" }
18
+ },
19
+ "additionalProperties": true
20
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://neuxnet.com/schemas/neux/project-config.schema.json",
4
+ "title": "Neux project configuration",
5
+ "description": "Project and compiler settings consumed by neux and the Neux compiler.",
6
+ "type": "object",
7
+ "properties": {
8
+ "description": { "type": "string" }, "appid": { "type": "string" }, "appId": { "type": "string" },
9
+ "projectname": { "type": "string" }, "projectName": { "type": "string" },
10
+ "compileType": { "type": "string", "enum": ["miniprogram"] }, "libVersion": { "type": "string" },
11
+ "miniprogramRoot": { "type": "string" }, "versionName": { "type": "string" }, "version": { "type": "string" }, "versionCode": { "type": "integer", "minimum": 1 },
12
+ "setting": { "$ref": "#/definitions/setting" }, "condition": { "type": "object", "additionalProperties": true },
13
+ "packOptions": { "$ref": "#/definitions/packOptions" }, "editorSetting": { "$ref": "#/definitions/editorSetting" },
14
+ "neux": { "$ref": "#/definitions/neux" }, "neuxCli": { "$ref": "#/definitions/neux" }
15
+ },
16
+ "additionalProperties": true,
17
+ "definitions": {
18
+ "setting": { "type": "object", "properties": { "urlCheck": { "type": "boolean" }, "es6": { "type": "boolean" }, "postcss": { "type": "boolean" }, "minified": { "type": "boolean" }, "newFeature": { "type": "boolean" }, "babelSetting": { "type": "object", "properties": { "ignore": { "type": "array", "items": { "type": "string" } }, "disablePlugins": { "type": "array", "items": { "type": "string" } }, "outputPath": { "type": "string" } }, "additionalProperties": true } }, "additionalProperties": true },
19
+ "packOptions": { "type": "object", "properties": { "ignore": { "type": "array", "items": { "type": "string" } }, "include": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": true },
20
+ "editorSetting": { "type": "object", "properties": { "tabIndent": { "type": "string", "enum": ["insertSpaces", "indexSize"] }, "tabSize": { "type": "integer", "minimum": 1 } }, "additionalProperties": true },
21
+ "neux": { "type": "object", "properties": { "serverUrl": { "type": "string", "format": "uri" }, "appId": { "type": "string" }, "profile": { "type": "string" } }, "additionalProperties": true }
22
+ }
23
+ }
@@ -0,0 +1,161 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://neuxnet.com/schemas/neux/project-private-config.schema.json",
4
+ "title": "Neux private project configuration",
5
+ "description": "Optional local overrides for project.config.json. All fields are optional.",
6
+ "type": "object",
7
+ "properties": {
8
+ "description": {
9
+ "type": "string"
10
+ },
11
+ "appid": {
12
+ "type": "string"
13
+ },
14
+ "appId": {
15
+ "type": "string"
16
+ },
17
+ "projectname": {
18
+ "type": "string"
19
+ },
20
+ "projectName": {
21
+ "type": "string"
22
+ },
23
+ "compileType": {
24
+ "type": "string",
25
+ "enum": [
26
+ "miniprogram"
27
+ ]
28
+ },
29
+ "libVersion": {
30
+ "type": "string"
31
+ },
32
+ "miniprogramRoot": {
33
+ "type": "string"
34
+ },
35
+ "versionName": {
36
+ "type": "string"
37
+ },
38
+ "version": {
39
+ "type": "string"
40
+ },
41
+ "versionCode": {
42
+ "type": "integer",
43
+ "minimum": 1
44
+ },
45
+ "setting": {
46
+ "$ref": "#/definitions/setting"
47
+ },
48
+ "condition": {
49
+ "type": "object",
50
+ "additionalProperties": true
51
+ },
52
+ "packOptions": {
53
+ "$ref": "#/definitions/packOptions"
54
+ },
55
+ "editorSetting": {
56
+ "$ref": "#/definitions/editorSetting"
57
+ },
58
+ "neux": {
59
+ "$ref": "#/definitions/neux"
60
+ },
61
+ "neuxCli": {
62
+ "$ref": "#/definitions/neux"
63
+ }
64
+ },
65
+ "additionalProperties": true,
66
+ "definitions": {
67
+ "setting": {
68
+ "type": "object",
69
+ "properties": {
70
+ "urlCheck": {
71
+ "type": "boolean"
72
+ },
73
+ "es6": {
74
+ "type": "boolean"
75
+ },
76
+ "postcss": {
77
+ "type": "boolean"
78
+ },
79
+ "minified": {
80
+ "type": "boolean"
81
+ },
82
+ "newFeature": {
83
+ "type": "boolean"
84
+ },
85
+ "babelSetting": {
86
+ "type": "object",
87
+ "properties": {
88
+ "ignore": {
89
+ "type": "array",
90
+ "items": {
91
+ "type": "string"
92
+ }
93
+ },
94
+ "disablePlugins": {
95
+ "type": "array",
96
+ "items": {
97
+ "type": "string"
98
+ }
99
+ },
100
+ "outputPath": {
101
+ "type": "string"
102
+ }
103
+ },
104
+ "additionalProperties": true
105
+ }
106
+ },
107
+ "additionalProperties": true
108
+ },
109
+ "packOptions": {
110
+ "type": "object",
111
+ "properties": {
112
+ "ignore": {
113
+ "type": "array",
114
+ "items": {
115
+ "type": "string"
116
+ }
117
+ },
118
+ "include": {
119
+ "type": "array",
120
+ "items": {
121
+ "type": "string"
122
+ }
123
+ }
124
+ },
125
+ "additionalProperties": true
126
+ },
127
+ "editorSetting": {
128
+ "type": "object",
129
+ "properties": {
130
+ "tabIndent": {
131
+ "type": "string",
132
+ "enum": [
133
+ "insertSpaces",
134
+ "indexSize"
135
+ ]
136
+ },
137
+ "tabSize": {
138
+ "type": "integer",
139
+ "minimum": 1
140
+ }
141
+ },
142
+ "additionalProperties": true
143
+ },
144
+ "neux": {
145
+ "type": "object",
146
+ "properties": {
147
+ "serverUrl": {
148
+ "type": "string",
149
+ "format": "uri"
150
+ },
151
+ "appId": {
152
+ "type": "string"
153
+ },
154
+ "profile": {
155
+ "type": "string"
156
+ }
157
+ },
158
+ "additionalProperties": true
159
+ }
160
+ }
161
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuxnet/neux-cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Standalone CLI and Node API for Neux mini program build, pack, preview, and CI automation.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -28,7 +28,8 @@
28
28
  "smoke:init-types:registry": "node ./scripts/smoke-init-types.mjs --registry",
29
29
  "test": "node --test",
30
30
  "smoke:help": "node ./src/bin/cli.js --help",
31
- "pack:dry": "npm pack --dry-run"
31
+ "pack:dry": "npm pack --dry-run",
32
+ "verify:schemas": "node ./scripts/verify-json-schemas.mjs"
32
33
  },
33
34
  "engines": {
34
35
  "node": ">=20"
@@ -63,7 +64,7 @@
63
64
  "neux": {
64
65
  "typesPackage": {
65
66
  "name": "@neuxnet/neux-miniapp-types",
66
- "versionRange": "^0.1.7"
67
+ "versionRange": "^0.1.8"
67
68
  }
68
69
  },
69
70
  "publishConfig": {
@@ -0,0 +1,40 @@
1
+ import fs from 'node:fs/promises'
2
+ import path from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+
5
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
6
+ const schemaDir = path.join(root, 'assets', 'init', 'schemas')
7
+ const initSource = await fs.readFile(path.join(root, 'src', 'core', 'init.js'), 'utf8')
8
+ const projectSource = await fs.readFile(path.join(root, 'src', 'core', 'project.js'), 'utf8')
9
+ const serviceSource = await fs.readFile(path.join(root, 'src', 'providers', 'service-config.js'), 'utf8')
10
+
11
+ const manifest = {
12
+ 'app.schema.json': { fields: ['pages', 'entryPagePath', 'window', 'tabBar', 'subPackages', 'subpackages', 'preloadRule', 'networkTimeout', 'permission', 'usingComponents'] },
13
+ 'page.schema.json': { fields: ['navigationBarTitleText', 'navigationBarBackgroundColor', 'navigationBarTextStyle', 'backgroundColor', 'backgroundTextStyle', 'enablePullDownRefresh', 'onReachBottomDistance', 'usingComponents', 'disableScroll', 'pageOrientation'] },
14
+ 'project-config.schema.json': { fields: ['appid', 'projectname', 'compileType', 'libVersion', 'miniprogramRoot', 'versionName', 'versionCode', 'setting', 'condition', 'packOptions', 'editorSetting', 'neuxCli'] },
15
+ 'project-private-config.schema.json': { fields: ['appid', 'projectname', 'versionName', 'versionCode', 'setting', 'packOptions', 'neuxCli'] },
16
+ 'neux-config.schema.json': { fields: ['serverUrl', 'appId', 'appid', 'profile', 'version', 'versionName', 'versionCode'] },
17
+ }
18
+
19
+ const errors = []
20
+ for (const [name, entry] of Object.entries(manifest)) {
21
+ const file = path.join(schemaDir, name)
22
+ let schema
23
+ try { schema = JSON.parse(await fs.readFile(file, 'utf8')) } catch (error) { errors.push(`${name}: invalid JSON (${error.message})`); continue }
24
+ if (schema.$schema !== 'http://json-schema.org/draft-07/schema#') errors.push(`${name}: missing draft-07 $schema`)
25
+ if (!schema.title || !schema.description) errors.push(`${name}: title and description are required`)
26
+ const serialized = JSON.stringify(schema)
27
+ for (const field of entry.fields) if (!serialized.includes(`"${field}"`)) errors.push(`${name}: source field is missing from schema: ${field}`)
28
+ if (name === 'neux-config.schema.json') {
29
+ for (const secret of ['key', 'cliKey', 'neuxCliKey']) if (schema.properties?.[secret]) errors.push(`${name}: secret field must not be declared: ${secret}`)
30
+ if (!schema.not?.anyOf?.some(rule => rule.required?.includes('key'))) errors.push(`${name}: must reject key`)
31
+ }
32
+ }
33
+ const settings = initSource.match(/function createJsonSchemaSettings\(\)\s*\{([\s\S]*?)\n\}/)?.[1] || ''
34
+ for (const name of Object.keys(manifest)) {
35
+ if (!settings.includes(name)) errors.push(`init.js: schema is not registered: ${name}`)
36
+ try { await fs.access(path.join(schemaDir, name)) } catch { errors.push(`missing schema asset: ${name}`) }
37
+ }
38
+ if (!projectSource.includes('readProjectCliConfig') || !serviceSource.includes('assertNoKey')) errors.push('source guard: expected configuration readers were not found')
39
+ if (errors.length) { console.error(['JSON Schema verification failed:', ...errors.map(error => `- ${error}`)].join('\n')); process.exitCode = 1 }
40
+ else console.log(`JSON Schema verification passed (${Object.keys(manifest).length} schemas, ${Object.values(manifest).reduce((n, item) => n + item.fields.length, 0)} source-backed fields).`)
package/src/bin/cli.js CHANGED
@@ -307,6 +307,12 @@ async function writeResult(result, rawOptions) {
307
307
  process.stdout.write(`key: ${result.key?.present ? 'configured' : 'missing'}\n`)
308
308
  if (result.missing?.length) process.stdout.write(`missing: ${result.missing.join(', ')}\n`)
309
309
  }
310
+ if (Array.isArray(result.diagnostics) && result.diagnostics.length > 0) {
311
+ process.stdout.write(`diagnostics: ${result.diagnostics.length}\n`)
312
+ for (const diagnostic of result.diagnostics) {
313
+ process.stdout.write(` [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}\n`)
314
+ }
315
+ }
310
316
  if (result.qrPayload && qrFormat === 'terminal') {
311
317
  process.stdout.write('\n')
312
318
  process.stdout.write(await renderTerminalQr(result.qrPayload))
@@ -315,6 +321,12 @@ async function writeResult(result, rawOptions) {
315
321
 
316
322
  function formatErrorPayload(payload, locale = 'en') {
317
323
  const lines = [`${payload.code}: ${payload.message}`]
324
+ if (payload.details?.diagnostics?.length) {
325
+ lines.push('', 'Diagnostics:')
326
+ for (const diagnostic of payload.details.diagnostics) {
327
+ lines.push(` [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`)
328
+ }
329
+ }
318
330
  const suggestions = payload.details?.suggestions
319
331
  if (payload.code === 'NEUX_CLI_CONFIG_MISSING' && Array.isArray(suggestions) && suggestions.length > 0) {
320
332
  lines.push('', translate(locale, 'suggestedFixes'))
@@ -49,6 +49,7 @@ async function loadCompiler(moduleSpecifier) {
49
49
 
50
50
  export async function buildProject(options = {}) {
51
51
  const projectInfo = await inspectProject(options)
52
+ assertProjectConfiguration(projectInfo, options)
52
53
  const out = resolvePath(options.out || options.output || defaultOut('build'))
53
54
  const compilerModule = options.compiler || await loadCompiler(options.compilerModule || process.env.DIMINA_COMPILER_MODULE)
54
55
  const build = compilerModule.default || compilerModule.build || compilerModule
@@ -92,12 +93,22 @@ export async function buildProject(options = {}) {
92
93
  compilerInputCreated: compilerInput.created,
93
94
  outputPath: out,
94
95
  appId: projectInfo.appId,
96
+ diagnostics: projectInfo.diagnostics,
95
97
  compilerResult,
96
98
  logs,
97
99
  errors,
98
100
  }
99
101
  }
100
102
 
103
+ function assertProjectConfiguration(projectInfo, options = {}) {
104
+ if (options.validate === false || projectInfo.ok) return
105
+ throw new DiminaCliError(
106
+ 'NEUX_PROJECT_CONFIG_INVALID',
107
+ `Project configuration validation failed with ${projectInfo.diagnostics.length} error(s).`,
108
+ { diagnostics: projectInfo.diagnostics },
109
+ )
110
+ }
111
+
101
112
  export async function buildStyleOnlyProject(options = {}) {
102
113
  const projectInfo = await inspectProject(options)
103
114
  const out = resolvePath(options.out || options.output || defaultOut('build'))
package/src/core/init.js CHANGED
@@ -139,6 +139,25 @@ async function mergeJsonFile(filePath, generated) {
139
139
  ...(existing['files.associations'] || {}),
140
140
  }
141
141
  }
142
+ if (generated?.['json.schemas'] || existing?.['json.schemas']) {
143
+ const generatedSchemas = Array.isArray(generated?.['json.schemas']) ? generated['json.schemas'] : []
144
+ const existingSchemas = Array.isArray(existing?.['json.schemas']) ? existing['json.schemas'] : []
145
+ const keys = new Set()
146
+ merged['json.schemas'] = [...generatedSchemas, ...existingSchemas].filter(schema => {
147
+ const key = `${schema?.url || ''}|${JSON.stringify(schema?.fileMatch || [])}`
148
+ if (keys.has(key)) return false
149
+ keys.add(key)
150
+ return true
151
+ })
152
+ }
153
+ if (generated?.['html.customData'] || existing?.['html.customData']) {
154
+ merged['html.customData'] = [
155
+ ...new Set([
156
+ ...(Array.isArray(generated?.['html.customData']) ? generated['html.customData'] : []),
157
+ ...(Array.isArray(existing?.['html.customData']) ? existing['html.customData'] : []),
158
+ ]),
159
+ ]
160
+ }
142
161
  if (filePath.endsWith('neux.code-snippets')) {
143
162
  Object.assign(merged, generated || {}, existing || {})
144
163
  }
@@ -277,8 +296,21 @@ function createTemplateFiles({
277
296
  '*.nxml': 'html',
278
297
  '*.nxss': 'css',
279
298
  },
299
+ 'json.schemas': createJsonSchemaSettings(),
300
+ 'html.customData': ['./.vscode/neux-html-data.json'],
280
301
  },
281
302
  },
303
+ {
304
+ path: '.vscode/neux-html-data.json',
305
+ kind: 'asset',
306
+ source: 'neux-html-data.json',
307
+ },
308
+ {
309
+ path: '.vscode/neux-components.code-snippets',
310
+ kind: 'asset',
311
+ source: 'neux-components.code-snippets',
312
+ },
313
+ ...createJsonSchemaFiles(),
282
314
  {
283
315
  path: '.vscode/neux.code-snippets',
284
316
  kind: 'merge-json',
@@ -545,6 +577,30 @@ function createTemplateFiles({
545
577
  ]
546
578
  }
547
579
 
580
+ function createJsonSchemaSettings() {
581
+ return [
582
+ { fileMatch: ['/app.json'], url: './.vscode/neux-json-schemas/app.schema.json' },
583
+ { fileMatch: ['/pages/**/*.json', '/components/**/*.json'], url: './.vscode/neux-json-schemas/page.schema.json' },
584
+ { fileMatch: ['/project.config.json'], url: './.vscode/neux-json-schemas/project-config.schema.json' },
585
+ { fileMatch: ['/project.private.config.json'], url: './.vscode/neux-json-schemas/project-private-config.schema.json' },
586
+ { fileMatch: ['/neux.config.json'], url: './.vscode/neux-json-schemas/neux-config.schema.json' },
587
+ ]
588
+ }
589
+
590
+ function createJsonSchemaFiles() {
591
+ return [
592
+ 'app.schema.json',
593
+ 'page.schema.json',
594
+ 'project-config.schema.json',
595
+ 'project-private-config.schema.json',
596
+ 'neux-config.schema.json',
597
+ ].map(name => ({
598
+ path: `.vscode/neux-json-schemas/${name}`,
599
+ kind: 'asset',
600
+ source: `schemas/${name}`,
601
+ }))
602
+ }
603
+
548
604
  function escapeJsString(value) {
549
605
  return String(value).replaceAll('\\', '\\\\').replaceAll("'", "\\'")
550
606
  }
@@ -782,13 +838,6 @@ function createNeuxCodeSnippets() {
782
838
  body: ['<view nx:if="{{${1:visible}}}">', ' ${0}', '</view>'],
783
839
  description: 'Render a view conditionally',
784
840
  },
785
- 'Tap Button': {
786
- prefix: 'nxbutton',
787
- scope: 'html',
788
- include: ['**/*.nxml'],
789
- body: ['<button bindtap="${1:handleTap}">${2:Button}</button>$0'],
790
- description: 'Insert a button with a tap handler',
791
- },
792
841
  'Page View': {
793
842
  prefix: 'nxview',
794
843
  scope: 'html',