dazscript-framework 1.0.5 → 1.0.7
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 +15 -1
- package/dist/scripts/build.js +1 -0
- package/dist/scripts/cli.js +8 -0
- package/dist/scripts/init.js +1 -0
- package/dist/scripts/install-generator.js +52 -6
- package/package.json +1 -1
- package/src/common/log.test.ts +45 -0
- package/src/common/log.ts +62 -14
- package/src/scripts/install-generator.test.ts +105 -0
- package/webpack.config.js +5 -0
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ npm install dazscript-framework dazscript-types
|
|
|
53
53
|
npx dazscript init
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
Follow the prompt for your AppData author namespace (e.g. `YourName/my-project`). This creates `dazscript.config.ts`, `tsconfig.json`, and wires the `build`, `build:encrypted`, `watch`, `encrypt`, `icons`, and `installer` scripts into `package.json`.
|
|
56
|
+
Follow the prompt for your AppData author namespace (e.g. `YourName/my-project`). This creates `dazscript.config.ts`, `tsconfig.json`, and wires the `build`, `build:encrypted`, `build:release`, `watch`, `encrypt`, `icons`, and `installer` scripts into `package.json`.
|
|
57
57
|
|
|
58
58
|
### 3. Write the script
|
|
59
59
|
|
|
@@ -160,6 +160,7 @@ This generates:
|
|
|
160
160
|
- `dazscript.config.ts`
|
|
161
161
|
- `tsconfig.json`
|
|
162
162
|
- `package.json` script wiring for `build`, `build:encrypted`, `watch`, `encrypt`, `icons`, and `installer`
|
|
163
|
+
- `build:release` uses `--log-level warn` before encryption so release packages suppress debug and trace output
|
|
163
164
|
|
|
164
165
|
Available `init` flags:
|
|
165
166
|
|
|
@@ -174,6 +175,8 @@ npx dazscript init --menu-path /MyScripts --scripts-path ./src --out-dir ./out -
|
|
|
174
175
|
| `--out-dir` | Where `build` writes `.dsa` files and copies icons |
|
|
175
176
|
| `--app-data-path` | AppData namespace for launcher fallback (`Author/Product` format) |
|
|
176
177
|
|
|
178
|
+
Builds also accept `--log-level <trace|debug|info|warn|error|off>`. This sets the minimum runtime log level for the compiled scripts. Use `debug` or `trace` during development and `warn` for release packages.
|
|
179
|
+
|
|
177
180
|
Use `--scripts-path ./src/scripts` when runnable files live under a subfolder; use `--scripts-path ./src` when they are at the source root.
|
|
178
181
|
|
|
179
182
|
---
|
|
@@ -235,6 +238,7 @@ action({ text: 'My Script' }, MyScript);
|
|
|
235
238
|
| `toolbar` | Toolbar name the action should appear on |
|
|
236
239
|
| `group` | Grouping label for related actions in Daz Studio |
|
|
237
240
|
| `description` | Longer description for the action |
|
|
241
|
+
| `icon` | Image path used for the installed custom action. Overrides discovered icon files. |
|
|
238
242
|
| `bundle` | Generates a setup script beside the action. `true` → `Setup.dsa.ts`, a string → `Setup <name>.dsa.ts` |
|
|
239
243
|
|
|
240
244
|
---
|
|
@@ -286,6 +290,15 @@ Applying the dialog:
|
|
|
286
290
|
- Affected toolbars are rebuilt; empty framework-created toolbars are removed
|
|
287
291
|
- Selected keyboard shortcut rows are applied after actions are installed
|
|
288
292
|
|
|
293
|
+
Custom action icons are selected from `action(...)` metadata and sibling image files in this order:
|
|
294
|
+
|
|
295
|
+
1. Explicit `action({ icon: '...' })`
|
|
296
|
+
2. `scriptname.action.png`
|
|
297
|
+
3. `scriptname.png`
|
|
298
|
+
4. `scriptname.dsa.png` legacy fallback
|
|
299
|
+
|
|
300
|
+
`scriptname.action.png` is the installed custom action icon. Daz Studio uses the same action icon for menu and toolbar placements. `scriptname.png` is the preferred script/content icon fallback. `scriptname.dsa.png` is a legacy fallback kept for older projects and will be removed in a future breaking release.
|
|
301
|
+
|
|
289
302
|
This replaces the older `Install.dsa.ts` / `Uninstall.dsa.ts` pattern. The installer generator removes those legacy files if they exist.
|
|
290
303
|
|
|
291
304
|
### Setup Keyboard Shortcuts
|
|
@@ -517,6 +530,7 @@ Files ending in `.dsa.ts` are treated as runnable entry points and compiled to `
|
|
|
517
530
|
| Command | What it does |
|
|
518
531
|
|---|---|
|
|
519
532
|
| `npm run build` | Compile TypeScript → Daz Script |
|
|
533
|
+
| `npm run build:release` | Build with `--log-level warn`, then encrypt implementation bundles |
|
|
520
534
|
| `npm run watch` | Recompile on every save |
|
|
521
535
|
| `npm run installer` | Generate the setup dialog |
|
|
522
536
|
| `npm run icons` | Copy icon assets to the output folder |
|
package/dist/scripts/build.js
CHANGED
package/dist/scripts/cli.js
CHANGED
|
@@ -26,6 +26,7 @@ Options:
|
|
|
26
26
|
--scripts-path <path> Source directory to scan. Default: ./src
|
|
27
27
|
--out-dir <path> Build output directory. Default: ./out
|
|
28
28
|
--app-data-path <path> AppData namespace used by launcher fallbacks. Example: Author/Product
|
|
29
|
+
--log-level <level> Minimum runtime log level: trace, debug, info, warn, error, off
|
|
29
30
|
--daz-studio <path> Daz Studio executable for encrypt
|
|
30
31
|
--keep-source Keep source script.dsa files after encrypting
|
|
31
32
|
--timeout-ms <value> Daz Studio encrypt timeout. Default: 300000
|
|
@@ -115,6 +116,12 @@ function parseOptions(args, defaults) {
|
|
|
115
116
|
continue;
|
|
116
117
|
}
|
|
117
118
|
|
|
119
|
+
if (arg === '--log-level') {
|
|
120
|
+
options.logLevel = args[index + 1];
|
|
121
|
+
index += 1;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
|
|
118
125
|
if (arg === '--daz-studio') {
|
|
119
126
|
options.dazStudio = args[index + 1];
|
|
120
127
|
index += 1;
|
|
@@ -179,6 +186,7 @@ async function main(argv) {
|
|
|
179
186
|
scriptsPath: undefined,
|
|
180
187
|
outDir: undefined,
|
|
181
188
|
appDataPath: undefined,
|
|
189
|
+
logLevel: undefined,
|
|
182
190
|
file: undefined,
|
|
183
191
|
dazStudio: undefined,
|
|
184
192
|
keepSource: false,
|
package/dist/scripts/init.js
CHANGED
|
@@ -94,6 +94,7 @@ function updatePackageJson(workdir, options) {
|
|
|
94
94
|
prebuild: 'npm run installer',
|
|
95
95
|
build: 'dazscript build',
|
|
96
96
|
'build:encrypted': 'npm run build && npm run encrypt',
|
|
97
|
+
'build:release': 'npm run build -- --log-level warn && npm run encrypt',
|
|
97
98
|
postbuild: 'npm run icons',
|
|
98
99
|
watch: 'dazscript watch',
|
|
99
100
|
encrypt: 'dazscript encrypt --out-dir ./out --daz-studio "C:\\Program Files\\DAZ 3D\\DAZStudio4\\DAZStudio.exe"',
|
|
@@ -21,6 +21,54 @@ function stringOrDefault(str, defaultValue) {
|
|
|
21
21
|
return str !== undefined && str !== null && str !== '' ? str : defaultValue;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
function replaceEntrySourceSuffix(filePath, suffix) {
|
|
25
|
+
if (filePath.endsWith('.dsa.ts')) {
|
|
26
|
+
return `${filePath.slice(0, -'.dsa.ts'.length)}${suffix}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return filePath.replace(/\.ts$/, suffix);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function replaceEntryOutputSuffix(filePath, suffix) {
|
|
33
|
+
if (filePath.endsWith('.dsa')) {
|
|
34
|
+
return `${filePath.slice(0, -'.dsa'.length)}${suffix}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return `${filePath}${suffix}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getActionIconPath(filePath, decorator) {
|
|
41
|
+
if (decorator.icon) {
|
|
42
|
+
return decorator.icon;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const actionIcon = replaceEntrySourceSuffix(filePath, '.action.png');
|
|
46
|
+
const scriptIcon = replaceEntrySourceSuffix(filePath, '.png');
|
|
47
|
+
const legacyScriptIcon = filePath.replace('.ts', '.png');
|
|
48
|
+
|
|
49
|
+
if (!fs.existsSync(actionIcon) && !fs.existsSync(scriptIcon) && !fs.existsSync(legacyScriptIcon)) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const isBundleAction = decorator.bundle !== undefined;
|
|
54
|
+
|
|
55
|
+
if (fs.existsSync(actionIcon)) {
|
|
56
|
+
return isBundleAction
|
|
57
|
+
? replaceEntryOutputSuffix(path.parse(filePath).name, '.action.png')
|
|
58
|
+
: replaceEntryOutputSuffix(getPartialPath(filePath), '.action.png');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (fs.existsSync(scriptIcon)) {
|
|
62
|
+
return isBundleAction
|
|
63
|
+
? replaceEntryOutputSuffix(path.parse(filePath).name, '.png')
|
|
64
|
+
: replaceEntryOutputSuffix(getPartialPath(filePath), '.png');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return isBundleAction
|
|
68
|
+
? path.parse(filePath).name.replace('.dsa', '.dsa.png')
|
|
69
|
+
: `${getPartialPath(filePath)}.png`;
|
|
70
|
+
}
|
|
71
|
+
|
|
24
72
|
function generateInstallerTemplate(data, options) {
|
|
25
73
|
return `
|
|
26
74
|
import { showSetupCustomActionsDialog as setup } from '@dsf/helpers/custom-action-installer-helper';
|
|
@@ -178,12 +226,9 @@ function processScript(filePath, container, defaultMenuPath, setupOptions) {
|
|
|
178
226
|
toolbar: stringOrDefault(decorator.toolbar, undefined),
|
|
179
227
|
};
|
|
180
228
|
|
|
181
|
-
const icon = filePath
|
|
182
|
-
if (
|
|
183
|
-
script.icon =
|
|
184
|
-
decorator.bundle === undefined
|
|
185
|
-
? `${getPartialPath(filePath)}.png`
|
|
186
|
-
: fileInfo.name.replace('.dsa', '.dsa.png');
|
|
229
|
+
const icon = getActionIconPath(filePath, decorator);
|
|
230
|
+
if (icon) {
|
|
231
|
+
script.icon = icon;
|
|
187
232
|
}
|
|
188
233
|
|
|
189
234
|
script.text = stringOrDefault(decorator.text, script.text);
|
|
@@ -364,4 +409,5 @@ if (require.main === module) {
|
|
|
364
409
|
module.exports = {
|
|
365
410
|
generateInstallerFiles,
|
|
366
411
|
findActionEntryFiles,
|
|
412
|
+
getActionIconPath,
|
|
367
413
|
};
|
package/package.json
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { debug, error, getLogLevel, info, setLogLevel, shouldLog, trace, warn } from './log'
|
|
3
|
+
|
|
4
|
+
describe('log levels', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
;(globalThis as any).App = {
|
|
7
|
+
debug: vi.fn(),
|
|
8
|
+
log: vi.fn(),
|
|
9
|
+
warning: vi.fn(),
|
|
10
|
+
flushLogBuffer: vi.fn(),
|
|
11
|
+
statusLine: vi.fn()
|
|
12
|
+
}
|
|
13
|
+
setLogLevel('debug')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('filters messages below the active level', () => {
|
|
17
|
+
setLogLevel('warn')
|
|
18
|
+
|
|
19
|
+
debug('hidden debug')
|
|
20
|
+
info('hidden info')
|
|
21
|
+
warn('visible warn')
|
|
22
|
+
error('visible error')
|
|
23
|
+
|
|
24
|
+
expect((globalThis as any).App.debug).not.toHaveBeenCalled()
|
|
25
|
+
expect((globalThis as any).App.log).not.toHaveBeenCalled()
|
|
26
|
+
expect((globalThis as any).App.warning).toHaveBeenCalledTimes(2)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('allows trace only when active level is trace', () => {
|
|
30
|
+
setLogLevel('debug')
|
|
31
|
+
trace('hidden trace')
|
|
32
|
+
|
|
33
|
+
setLogLevel('trace')
|
|
34
|
+
trace('visible trace')
|
|
35
|
+
|
|
36
|
+
expect((globalThis as any).App.debug).toHaveBeenCalledTimes(1)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('normalizes invalid levels to debug', () => {
|
|
40
|
+
setLogLevel('not-a-level')
|
|
41
|
+
|
|
42
|
+
expect(getLogLevel()).toBe('debug')
|
|
43
|
+
expect(shouldLog('debug')).toBe(true)
|
|
44
|
+
})
|
|
45
|
+
})
|
package/src/common/log.ts
CHANGED
|
@@ -1,32 +1,73 @@
|
|
|
1
|
-
|
|
1
|
+
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'off'
|
|
2
|
+
|
|
3
|
+
declare const __DAZSCRIPT_LOG_LEVEL__: string | undefined
|
|
4
|
+
|
|
5
|
+
const logLevels: LogLevel[] = ['trace', 'debug', 'info', 'warn', 'error', 'off']
|
|
6
|
+
const logLevelWeights: { [key in LogLevel]: number } = {
|
|
7
|
+
trace: 0,
|
|
8
|
+
debug: 1,
|
|
9
|
+
info: 2,
|
|
10
|
+
warn: 3,
|
|
11
|
+
error: 4,
|
|
12
|
+
off: 5
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let currentLogLevel: LogLevel = normalizeLogLevel(
|
|
16
|
+
typeof __DAZSCRIPT_LOG_LEVEL__ === 'string'
|
|
17
|
+
? __DAZSCRIPT_LOG_LEVEL__
|
|
18
|
+
: 'debug'
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
export const setLogLevel = (level: string): LogLevel => {
|
|
22
|
+
currentLogLevel = normalizeLogLevel(level)
|
|
23
|
+
return currentLogLevel
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const getLogLevel = (): LogLevel => currentLogLevel
|
|
27
|
+
|
|
28
|
+
export function normalizeLogLevel(level: string): LogLevel {
|
|
29
|
+
if (!level) return 'debug'
|
|
30
|
+
const normalized = level.toLowerCase() as LogLevel
|
|
31
|
+
return logLevels.indexOf(normalized) >= 0 ? normalized : 'debug'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const shouldLog = (level: LogLevel): boolean => {
|
|
35
|
+
return logLevelWeights[level] >= logLevelWeights[currentLogLevel]
|
|
36
|
+
&& currentLogLevel !== 'off'
|
|
37
|
+
}
|
|
2
38
|
|
|
3
39
|
export const debug = (message: any) => {
|
|
4
|
-
|
|
5
|
-
|
|
40
|
+
if (!shouldLog('debug')) return
|
|
41
|
+
app().debug(format(message))
|
|
42
|
+
flush()
|
|
6
43
|
}
|
|
7
44
|
|
|
8
45
|
export const info = (message: any) => {
|
|
9
|
-
|
|
10
|
-
|
|
46
|
+
if (!shouldLog('info')) return
|
|
47
|
+
app().log(format(message))
|
|
48
|
+
flush()
|
|
11
49
|
}
|
|
12
50
|
|
|
13
51
|
export const error = (message: any) => {
|
|
14
|
-
|
|
15
|
-
|
|
52
|
+
if (!shouldLog('error')) return
|
|
53
|
+
app().warning(format(message, "ERROR"))
|
|
54
|
+
flush()
|
|
16
55
|
}
|
|
17
56
|
|
|
18
57
|
export const warn = (message: any) => {
|
|
19
|
-
|
|
20
|
-
|
|
58
|
+
if (!shouldLog('warn')) return
|
|
59
|
+
app().warning(message)
|
|
60
|
+
flush()
|
|
21
61
|
}
|
|
22
62
|
|
|
23
63
|
export const trace = (message: any) => {
|
|
24
|
-
|
|
25
|
-
|
|
64
|
+
if (!shouldLog('trace')) return
|
|
65
|
+
app().debug(format(message, "TRACE"))
|
|
66
|
+
flush()
|
|
26
67
|
}
|
|
27
68
|
|
|
28
69
|
export const status = (message: any, log: boolean = true) => {
|
|
29
|
-
|
|
70
|
+
app().statusLine(message, log)
|
|
30
71
|
}
|
|
31
72
|
|
|
32
73
|
/**
|
|
@@ -39,8 +80,9 @@ export const raise = (err: string) => {
|
|
|
39
80
|
}
|
|
40
81
|
|
|
41
82
|
export const dump = (obj: any) => {
|
|
42
|
-
|
|
43
|
-
|
|
83
|
+
if (!shouldLog('debug')) return
|
|
84
|
+
app().debug(`[DUMP]\r\n${JSON.stringify(obj, null, 2)}`)
|
|
85
|
+
flush()
|
|
44
86
|
}
|
|
45
87
|
|
|
46
88
|
const format = (message: string, level?: 'ERROR' | 'TRACE' | 'DUMP' | 'INFO') => {
|
|
@@ -54,3 +96,9 @@ const format = (message: string, level?: 'ERROR' | 'TRACE' | 'DUMP' | 'INFO') =>
|
|
|
54
96
|
return text
|
|
55
97
|
}
|
|
56
98
|
|
|
99
|
+
const app = (): any => App
|
|
100
|
+
|
|
101
|
+
const flush = () => {
|
|
102
|
+
app().flushLogBuffer()
|
|
103
|
+
}
|
|
104
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
5
|
+
|
|
6
|
+
const { generateInstallerFiles } = require('../../dist/scripts/install-generator')
|
|
7
|
+
|
|
8
|
+
const tempDirs: string[] = []
|
|
9
|
+
|
|
10
|
+
const makeProject = (): string => {
|
|
11
|
+
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dsf-install-generator-'))
|
|
12
|
+
tempDirs.push(projectDir)
|
|
13
|
+
fs.mkdirSync(path.join(projectDir, 'src'), { recursive: true })
|
|
14
|
+
fs.writeFileSync(
|
|
15
|
+
path.join(projectDir, 'dazscript.config.cjs'),
|
|
16
|
+
"module.exports = { appDataPath: 'Test/ActionIcons' }\n"
|
|
17
|
+
)
|
|
18
|
+
return projectDir
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const writeScript = (projectDir: string, name: string, actionOptions: string = ''): void => {
|
|
22
|
+
fs.writeFileSync(
|
|
23
|
+
path.join(projectDir, 'src', `${name}.dsa.ts`),
|
|
24
|
+
`action({ text: '${name}'${actionOptions} }, function() {})\n`
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const writePng = (projectDir: string, fileName: string): void => {
|
|
29
|
+
fs.writeFileSync(path.join(projectDir, 'src', fileName), 'png')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const generateSetup = (projectDir: string): string => {
|
|
33
|
+
const previousCwd = process.cwd()
|
|
34
|
+
process.chdir(projectDir)
|
|
35
|
+
try {
|
|
36
|
+
generateInstallerFiles(projectDir, {
|
|
37
|
+
scriptsPath: './src',
|
|
38
|
+
defaultMenuPath: '/Test',
|
|
39
|
+
appDataPath: undefined,
|
|
40
|
+
})
|
|
41
|
+
} finally {
|
|
42
|
+
process.chdir(previousCwd)
|
|
43
|
+
}
|
|
44
|
+
return fs.readFileSync(path.join(projectDir, 'src', 'Setup.dsa.ts'), 'utf8')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
afterEach(() => {
|
|
48
|
+
while (tempDirs.length > 0) {
|
|
49
|
+
const dir = tempDirs.pop()
|
|
50
|
+
if (dir) fs.rmSync(dir, { recursive: true, force: true })
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe('install generator action icons', () => {
|
|
55
|
+
it('prefers the action icon convention over the script icon fallback', () => {
|
|
56
|
+
const projectDir = makeProject()
|
|
57
|
+
writeScript(projectDir, 'render-tools')
|
|
58
|
+
writePng(projectDir, 'render-tools.action.png')
|
|
59
|
+
writePng(projectDir, 'render-tools.png')
|
|
60
|
+
writePng(projectDir, 'render-tools.dsa.png')
|
|
61
|
+
|
|
62
|
+
const setup = generateSetup(projectDir)
|
|
63
|
+
|
|
64
|
+
expect(setup).toContain('"icon": "./render-tools.action.png"')
|
|
65
|
+
expect(setup).not.toContain('"icon": "./render-tools.png"')
|
|
66
|
+
expect(setup).not.toContain('"icon": "./render-tools.dsa.png"')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('falls back to the script icon when no action icon exists', () => {
|
|
70
|
+
const projectDir = makeProject()
|
|
71
|
+
writeScript(projectDir, 'power-menu')
|
|
72
|
+
writePng(projectDir, 'power-menu.png')
|
|
73
|
+
writePng(projectDir, 'power-menu.dsa.png')
|
|
74
|
+
|
|
75
|
+
const setup = generateSetup(projectDir)
|
|
76
|
+
|
|
77
|
+
expect(setup).toContain('"icon": "./power-menu.png"')
|
|
78
|
+
expect(setup).not.toContain('"icon": "./power-menu.dsa.png"')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('keeps the dsa-named script icon as a legacy fallback', () => {
|
|
82
|
+
const projectDir = makeProject()
|
|
83
|
+
writeScript(projectDir, 'legacy-icon')
|
|
84
|
+
writePng(projectDir, 'legacy-icon.dsa.png')
|
|
85
|
+
|
|
86
|
+
const setup = generateSetup(projectDir)
|
|
87
|
+
|
|
88
|
+
expect(setup).toContain('"icon": "./legacy-icon.dsa.png"')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('lets explicit action icon metadata override discovered icon files', () => {
|
|
92
|
+
const projectDir = makeProject()
|
|
93
|
+
writeScript(projectDir, 'custom-icon', ", icon: 'icons/custom-action.png'")
|
|
94
|
+
writePng(projectDir, 'custom-icon.action.png')
|
|
95
|
+
writePng(projectDir, 'custom-icon.png')
|
|
96
|
+
writePng(projectDir, 'custom-icon.dsa.png')
|
|
97
|
+
|
|
98
|
+
const setup = generateSetup(projectDir)
|
|
99
|
+
|
|
100
|
+
expect(setup).toContain('"icon": "icons/custom-action.png"')
|
|
101
|
+
expect(setup).not.toContain('"icon": "custom-icon.action.png"')
|
|
102
|
+
expect(setup).not.toContain('"icon": "custom-icon.png"')
|
|
103
|
+
expect(setup).not.toContain('"icon": "custom-icon.dsa.png"')
|
|
104
|
+
})
|
|
105
|
+
})
|
package/webpack.config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const glob = require('glob');
|
|
3
|
+
const webpack = require('webpack');
|
|
3
4
|
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
|
4
5
|
const { createActionLaunchers } = require('./dist/scripts/launchers');
|
|
5
6
|
const { validateAppDataPath } = require('./dist/scripts/app-data-path');
|
|
@@ -29,6 +30,7 @@ module.exports = (env, argv) => {
|
|
|
29
30
|
(env && env.appDataPath) || projectConfig.appDataPath,
|
|
30
31
|
projectRoot
|
|
31
32
|
);
|
|
33
|
+
const logLevel = (env && env.logLevel) || '';
|
|
32
34
|
const sourceRoot = path.resolve(projectRoot, 'src');
|
|
33
35
|
const projectNodeModules = path.resolve(projectRoot, 'node_modules');
|
|
34
36
|
const frameworkSourceRoot = path.resolve(
|
|
@@ -120,6 +122,9 @@ module.exports = (env, argv) => {
|
|
|
120
122
|
},
|
|
121
123
|
},
|
|
122
124
|
plugins: [
|
|
125
|
+
new webpack.DefinePlugin({
|
|
126
|
+
__DAZSCRIPT_LOG_LEVEL__: JSON.stringify(logLevel),
|
|
127
|
+
}),
|
|
123
128
|
new ActionLauncherPlugin({
|
|
124
129
|
workdir: projectRoot,
|
|
125
130
|
outDir: outputPath,
|