Переглянути джерело

Update uiconfig-tweakpane, uiconfig.js, ts-browser-helpers, minor css fixes in editor. Updates in TweakpaneUiPlugin - fix delay when opening tweakpane folders with render targets, interface with Undo. Remove rollup.config.mjs

master
Palash Bansal 1 рік тому
джерело
коміт
4ce8c4f826
Аккаунт користувача з таким Email не знайдено

+ 683
- 365
package-lock.json
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 5
- 5
package.json Переглянути файл

@@ -104,7 +104,7 @@
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.153.1006/package.tgz",
"tslib": "^2.5.0",
"typedoc": "^0.27.5",
"typescript": "^5.7.2",
"typescript": "5.7.2",
"typescript-plugin-css-modules": "^5.0.1",
"vite": "^6.0.5",
"vite-plugin-dts": "^4.4.0",
@@ -116,13 +116,13 @@
"@types/webxr": "^0.5.1",
"@types/wicg-file-system-access": "^2020.9.5",
"stats.js": "^0.17.0",
"ts-browser-helpers": "^0.15.0",
"uiconfig.js": "^0.0.12"
"ts-browser-helpers": "^0.16.0",
"uiconfig.js": "^0.1.1"
},
"//": {
"dependencies": {
"uiconfig.js": "^0.0.12",
"ts-browser-helpers": "^0.14.2",
"uiconfig.js": "^0.1.1",
"ts-browser-helpers": "^0.16.0",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.153.1006/package.tgz",
"three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.153.1006.tar.gz",
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz",

+ 2
- 2
plugins/tweakpane-editor/package-lock.json Переглянути файл

@@ -1,12 +1,12 @@
{
"name": "@threepipe/plugin-tweakpane-editor",
"version": "0.3.0",
"version": "0.3.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@threepipe/plugin-tweakpane-editor",
"version": "0.3.0",
"version": "0.3.2",
"license": "Apache-2.0",
"dependencies": {
"@threepipe/plugin-tweakpane": "file:./../tweakpane/src/",

+ 2
- 1
plugins/tweakpane-editor/package.json Переглянути файл

@@ -1,7 +1,7 @@
{
"name": "@threepipe/plugin-tweakpane-editor",
"description": "Tweakpane Editor Plugin for ThreePipe",
"version": "0.3.1",
"version": "0.3.2",
"devDependencies": {
"tippy.js": "^6.3.7",
"treejs": "git://github.com/repalash/treejs.git#d303016bb74e75725d13e97291ac1d4727985918"
@@ -12,6 +12,7 @@
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},

+ 2
- 0
plugins/tweakpane-editor/src/TweakpaneEditorPlugin.css Переглянути файл

@@ -106,6 +106,7 @@
cursor: pointer;
box-shadow: 0 2px 4px var(--tp-base-shadow-color);
transition: all 0.25s;
box-sizing: content-box !important;
}
.round-button:hover{
color: white;
@@ -123,6 +124,7 @@
width: auto;
height: 1.2rem;
aspect-ratio: 1;
box-sizing: content-box !important;
}

.mode-buttons-container{

+ 42
- 25
plugins/tweakpane/package-lock.json Переглянути файл

@@ -1,45 +1,50 @@
{
"name": "@threepipe/plugin-tweakpane",
"version": "0.4.1",
"version": "0.5.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@threepipe/plugin-tweakpane",
"version": "0.4.1",
"version": "0.5.0",
"license": "Apache-2.0",
"dependencies": {
"threepipe": "file:./../../src/"
},
"devDependencies": {
"tweakpane-image-plugin": "https://github.com/repalash/tweakpane-image-plugin/releases/download/v1.1.404/package.tgz",
"uiconfig-tweakpane": "^0.0.8"
"uiconfig-tweakpane": "^0.0.10"
}
},
"../../src": {},
"node_modules/@tweakpane/core": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/@tweakpane/core/-/core-1.1.8.tgz",
"integrity": "sha512-psvBf6Cbm3YSZOTmDFWkcGzHYMnw7gVZM3jw+TfbzErIC+sMXPQb85h4ayW04w2u7AGg8jD0gHXSCg5wd+rafg==",
"dev": true
"../../../uiconfig-react/packages/uiconfig-tweakpane": {
"version": "0.0.0",
"extraneous": true,
"devDependencies": {
"typescript": "~5.6.2",
"vite": "^6.0.3"
}
},
"../../src": {},
"node_modules/@tweenjs/tween.js": {
"version": "18.6.4",
"resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.6.4.tgz",
"integrity": "sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/@types/stats.js": {
"version": "0.17.3",
"resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz",
"integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/@types/three": {
"version": "0.152.1",
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.152.1.tgz",
"integrity": "sha512-PMOCQnx9JRmq+2OUGTPoY9h1hTWD2L7/nmuW/SyNq1Vbq3Lwt3MNdl3wYSa4DvLTGv62NmIXD9jYdAOwohwJyw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@tweenjs/tween.js": "~18.6.4",
"@types/stats.js": "*",
@@ -49,22 +54,25 @@
}
},
"node_modules/@types/webxr": {
"version": "0.5.12",
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.12.tgz",
"integrity": "sha512-+6LV7bN17XUWy4wIMILsGQX6ucawf64lYLG9jaGKSvOnKaJzWjcKXAkO0dZaC8MfoEqYQC7gl1GQnfITjBcazw==",
"dev": true
"version": "0.5.20",
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.20.tgz",
"integrity": "sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==",
"dev": true,
"license": "MIT"
},
"node_modules/fflate": {
"version": "0.6.10",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz",
"integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/lil-gui": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz",
"integrity": "sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/threepipe": {
"resolved": "../../src",
@@ -80,21 +88,30 @@
"@tweakpane/core": "1.1.8"
}
},
"node_modules/tweakpane-image-plugin/node_modules/@tweakpane/core": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/@tweakpane/core/-/core-1.1.8.tgz",
"integrity": "sha512-psvBf6Cbm3YSZOTmDFWkcGzHYMnw7gVZM3jw+TfbzErIC+sMXPQb85h4ayW04w2u7AGg8jD0gHXSCg5wd+rafg==",
"dev": true,
"license": "MIT"
},
"node_modules/uiconfig-tweakpane": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/uiconfig-tweakpane/-/uiconfig-tweakpane-0.0.8.tgz",
"integrity": "sha512-BZE/+6pW7qlywu4nhMjvzJ47IUORWn8rJsPpmcGqJgAz8G6MZjMXEW3Ey8EL41cVsDf5QSb0E/eTK8OWwuRfbA==",
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/uiconfig-tweakpane/-/uiconfig-tweakpane-0.0.10.tgz",
"integrity": "sha512-VF67oUg7M9EXKR3IO+TXS6jP28qfT1ci/C4Inu8CjruJk8qBfUjuxKBU5kLXH97rE5dM0xLvLg/rYxRlpJ8mog==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/three": "^0.152.1",
"uiconfig.js": "^0.0.8"
"uiconfig.js": "^0.1.1"
}
},
"node_modules/uiconfig.js": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/uiconfig.js/-/uiconfig.js-0.0.8.tgz",
"integrity": "sha512-0H1OO4CNHP5O0LBy82YWWFCzDK+Yf/GtXnR3i968FkMkf0+3/JsW7MC8ea2CcPtsi8ni4TA1FrMOC+KrYmMnCQ==",
"dev": true
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/uiconfig.js/-/uiconfig.js-0.1.1.tgz",
"integrity": "sha512-JzJyAgtFOfWVg964mmKKByULnhg4d5QpfsvXzj0T/Mncs1pK3/FACM+pAteLmT1xDeVDwwIU5s86UzlTiYwR/A==",
"dev": true,
"license": "MIT"
}
}
}

+ 6
- 5
plugins/tweakpane/package.json Переглянути файл

@@ -1,16 +1,17 @@
{
"name": "@threepipe/plugin-tweakpane",
"description": "Tweakpane UI Plugin for ThreePipe",
"version": "0.4.2",
"version": "0.5.0",
"devDependencies": {
"tweakpane-image-plugin": "https://github.com/repalash/tweakpane-image-plugin/releases/download/v1.1.404/package.tgz",
"uiconfig-tweakpane": "^0.0.8"
"uiconfig-tweakpane": "^0.0.10"
},
"dependencies": {
"threepipe": "file:./../../src/"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
@@ -63,17 +64,17 @@
],
"replace": {
"dependencies": {
"uiconfig-tweakpane": "^0.0.8"
"uiconfig-tweakpane": "^0.0.10"
},
"peerDependencies": {
"threepipe": "^0.0.21"
"threepipe": "^0.0.34"
}
}
},
"//": {
"dependencies": {
"tweakpane-image-plugin": "https://github.com/repalash/tweakpane-image-plugin/releases/download/v1.1.404/package.tgz",
"uiconfig-tweakpane": "^0.0.8"
"uiconfig-tweakpane": "^0.0.10"
},
"local_dependencies": {
"tweakpane-image-plugin": "file:./../tweakpane-image-plugin",

+ 26
- 5
plugins/tweakpane/src/TweakpaneUiPlugin.ts Переглянути файл

@@ -19,10 +19,11 @@ import {
uploadFile,
Vector2,
Vector3,
Vector4,
Vector4, UndoManagerPlugin,
} from 'threepipe'
import styles from './tpTheme.css?inline'
import {tpImageInputGenerator} from './tpImageInputGenerator'
import {JSUndoManager} from 'ts-browser-helpers'

@uiFolderContainer('Tweakpane UI')
export class TweakpaneUiPlugin extends UiConfigRendererTweakpane implements IViewerPluginSync {
@@ -30,21 +31,26 @@ export class TweakpaneUiPlugin extends UiConfigRendererTweakpane implements IVie
static readonly PluginType = 'TweakpaneUi'
enabled = true

static CONTAINER_SLOT = 'uiconfigMainPanelSlot'

@onChange(TweakpaneUiPlugin.prototype._colorModeChanged)
@uiDropdown('Color Mode', ['black', 'white', 'blue'].map(label=>({label})))
colorMode: 'black'|'white'|'blue'

constructor(expanded = false, bigTheme = true, container: HTMLElement = document.body, colorMode?: 'black'|'white'|'blue') {
super(container, {
constructor(expanded = false, bigTheme = true, container?: HTMLElement, colorMode?: 'black'|'white'|'blue') {
super(container ?? document.getElementById(TweakpaneUiPlugin.CONTAINER_SLOT) ?? document.getElementById('tweakpaneMainPanelSlot') ?? document.body, {
expanded, autoPostFrame: false,
})
}, false)
this.THREE = {Color, Vector4, Vector3, Vector2} as any
this._root!.registerPlugin(TweakpaneImagePlugin)
this._root!.registerPlugin(TweakpaneImagePlugin as any)
if (bigTheme) createStyles(styles, container)
this.colorMode = colorMode ?? (localStorage ? localStorage.getItem('tpTheme') as any : 'blue') ?? 'blue'
}

protected _viewer?: ThreeViewer

private _lastManager?: JSUndoManager

onAdded(viewer: ThreeViewer): void {
this._viewer = viewer
this.typeGenerators.image = tpImageInputGenerator(this._viewer)
@@ -52,13 +58,23 @@ export class TweakpaneUiPlugin extends UiConfigRendererTweakpane implements IVie
viewer.addEventListener('postRender', this._postRender)
viewer.addEventListener('preFrame', this._preFrame)
viewer.addEventListener('postFrame', this._postFrame)
const undo = viewer.getOrAddPluginSync(UndoManagerPlugin) // yes, manual dependency
if (undo?.undoManager) {
this._lastManager?.dispose()
this._lastManager = this.undoManager
this.undoManager = undo.undoManager
if (this._lastManager) Object.assign(this.undoManager.presets, this._lastManager.presets)
}
}

onRemove(viewer: ThreeViewer): void {
this._viewer = undefined
viewer.removeEventListener('preRender', this._preRender)
viewer.removeEventListener('postRender', this._postRender)
viewer.removeEventListener('preFrame', this._preFrame)
viewer.removeEventListener('postFrame', this._postFrame)
this.undoManager = this._lastManager
this._lastManager = undefined
this.dispose()
}

@@ -162,4 +178,9 @@ export class TweakpaneUiPlugin extends UiConfigRendererTweakpane implements IVie
localStorage.setItem('tpTheme', this.colorMode)
}

dispose() {
this.undoManager?.dispose()
this.unmount()
}

}

+ 43
- 18
plugins/tweakpane/src/tpImageInputGenerator.ts Переглянути файл

@@ -22,9 +22,16 @@ import {
import type {UiObjectConfig} from 'uiconfig.js'
import {TweakpaneUiPlugin} from './TweakpaneUiPlugin'


export const makeTextSvg2 = (text: string): string => {
return `data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Ctext style='font: 8px "Roboto Mono", "Source Code Pro", Menlo, Courier, monospace; fill: white;' x='9' y='18'%3E${text}%3C/text%3E%3C/svg%3E%0A`
}

const staticData = {
placeholderVal: 'placeholder',
// renderTarImage: makeColorSvg('ffffff'),
renderTarImage: makeTextSvg('Render Target'),
renderTarImage2: makeTextSvg2('...'),
dataTexImage: makeTextSvg('Data Texture'),
lutCubeTexImage: makeTextSvg('CUBE Texture'),
compressedTexImage: makeTextSvg('Compressed Texture'),
@@ -33,7 +40,7 @@ const staticData = {
tempMap: {} as any,
}

function proxyGetValue(cc: any, viewer: ThreeViewer) {
function proxyGetValue(cc: any, viewer: ThreeViewer, config: UiObjectConfig) {
if (cc?.get) cc = cc.get()
let ret: any = undefined
if (!cc) return staticData.placeholderVal
@@ -47,15 +54,27 @@ function proxyGetValue(cc: any, viewer: ThreeViewer) {
if (cc.isTexture) {
// console.warn('here')
// todo: use textureToCanvas for data texture
if (cc.image && !cc.image.tp_src) {
if (cc.image instanceof ImageBitmap || cc.image instanceof HTMLImageElement || cc.image instanceof HTMLVideoElement) { // todo: support playback in video
cc.image.tp_src = imageBitmapToBase64(cc.image, 160)
} else if (cc.isRenderTargetTexture) {
if (cc.image && !cc.image.tp_src && !cc.tp_src) {
if (cc.isRenderTargetTexture) {
if (cc._target) {
// here we are not doing cc.image.tp_src because cc.image can be shared across multiple textures in MRT
cc.tp_src = viewer.renderManager.renderTargetToDataUrl(cc._target, undefined, undefined, Array.isArray(cc._target.texture) ? cc._target.texture.indexOf(cc) : undefined)
setTimeout(()=>cc.tp_src && delete cc.tp_src, 1000) // clear after 1 second so it refreshes on next render
// todo do same change in blueprint
// doing in the timeout so it doesnt hang when opening a folder which does deep refresh
// if (!config._lastRtRefresh || Date.now() - config._lastRtRefresh > 5000) { // 5000 should be significantly more than 500 + 100 below
setTimeout(() => {

// here we are not doing cc.image.tp_src because cc.image can be shared across multiple textures in MRT
const dataUrl = viewer.renderManager.renderTargetToDataUrl(cc._target, undefined, undefined, Array.isArray(cc._target.texture) ? cc._target.texture.indexOf(cc) : undefined)
cc.tp_src = dataUrl
setTimeout(()=>cc.tp_src && delete cc.tp_src, 1000) // clear after 1 second so it refreshes on next render
config.uiRefresh?.(false, 'postFrame')

}, 200)
cc.tp_src = staticData.renderTarImage2
// }
// config._lastRtRefresh = Date.now()
}
} else if (cc.image instanceof ImageBitmap || cc.image instanceof HTMLImageElement || cc.image instanceof HTMLVideoElement) { // todo: support playback in video
cc.image.tp_src = imageBitmapToBase64(cc.image, 160)
} else {
cc.image.tp_src = textureToDataUrl(cc, 160, false, 'image/png', 90) // this supports DataTexture also
}
@@ -115,7 +134,7 @@ const setterTex = (v1: any, config: UiObjectConfig, renderer: TweakpaneUiPlugin)
}
}
config.__proxy.value_ = v1
renderer.methods.setValue(config, v1, {last: true}, false)
renderer.methods.setValue(config, v1, {last: true}, false, false)
config.uiRefresh?.(false, 'postFrame')
}

@@ -287,7 +306,7 @@ async function imageFromUrl(renderer: TweakpaneUiPlugin, config: UiObjectConfig,
}
}

export const tpImageInputGenerator = (viewer: ThreeViewer) => (parent: any /* FolderApi */, config: UiObjectConfig, renderer: TweakpaneUiPlugin, params?: any) => {
export const tpImageInputGenerator: (viewer: ThreeViewer) => (parent: any, config: UiObjectConfig, renderer: TweakpaneUiPlugin, params?: any) => any = (viewer: ThreeViewer) => (parent: any /* FolderApi */, config: UiObjectConfig, renderer: TweakpaneUiPlugin, params?: any) => {
// if (config.value !== undefined) throw 'Not supported yet'

if (!config.__proxy) {
@@ -297,21 +316,26 @@ export const tpImageInputGenerator = (viewer: ThreeViewer) => (parent: any /* Fo

Object.defineProperty(config.__proxy, 'value', {
get: () => {
config.__proxy.value_ = renderer.methods.getValue(config)
const ret = proxyGetValue(config.__proxy.value_, viewer)
if (typeof ret !== 'string' && !ret.id?.length) ret.id = generateUUID()
const id = typeof ret === 'string' ? ret : ret.id ?? ret
if (!staticData.textureMap[id]) staticData.textureMap[id] = config.__proxy.value_
return ret
try {
config.__proxy.value_ = renderer.methods.getRawValue(config) // sending undefined to disable comparison for undo etc
const ret = proxyGetValue(config.__proxy.value_, viewer, config)
if (typeof ret !== 'string' && !ret.id?.length) ret.id = generateUUID()
const id = typeof ret === 'string' ? ret : ret.id ?? ret
if (!staticData.textureMap[id]) staticData.textureMap[id] = config.__proxy.value_
return ret
} catch (e) {
console.error('uiconfig-tweakpane - ImageInput Unknown error', e)
return staticData.placeholderVal
}
},
set: (v: any) => {
if (getOrCall(config.readOnly)) return
config.__proxy.value_ = renderer.methods.getValue(config) // current value
config.__proxy.value_ = renderer.methods.getRawValue(config) // current value
proxySetValue(v, config.__proxy.value_, config, viewer, renderer)
},
})
}
config.__proxy.value_ = renderer.methods.getValue(config)
config.__proxy.value_ = renderer.methods.getRawValue(config)

params = params ?? {}
params.extensions = ['.jpg', '.png', '.svg', '.hdr',
@@ -347,6 +371,7 @@ export const tpImageInputGenerator = (viewer: ThreeViewer) => (parent: any /* Fo
menu.style.top = 'auto'
menu.style.bottom = rect.height + 8 + 'px'
}
config.uiRefresh?.(false, 'postFrame')
}
params.view = 'input-image'
return renderer.typeGenerators.input(parent, config, renderer, params)

+ 0
- 106
rollup.config.mjs Переглянути файл

@@ -1,106 +0,0 @@
// rollup.config.js
import json from '@rollup/plugin-json';
import resolve from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
import packageJson from './package.json' assert {type: 'json'};
import path from 'node:path'
import {fileURLToPath} from 'node:url';
import postcss from 'rollup-plugin-postcss'
import glsl from "rollup-plugin-glsl"
import replace from "@rollup/plugin-replace";
import commonjs from "@rollup/plugin-commonjs";
import license from "rollup-plugin-license";
import terser from "@rollup/plugin-terser";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const {name, version, author} = packageJson
const {main, module, browser} = packageJson["clean-package"].replace
const isProduction = process.env.NODE_ENV === 'production'

const settings = {
globals: {},
sourcemap: isProduction
}

export default {
input: './src/index.ts',
output: [
// {
// file: main,
// name: main,
// ...settings,
// format: 'cjs',
// plugins: [
// isProduction && terser()
// ]
// },
{
file: module,
...settings,
name: name,
// dir: 'dist', // indicate not create a single-file
// preserveModules: true, // indicate not create a single-file
// preserveModulesRoot: 'src', // optional but useful to create a more plain folder structure
format: 'es'
},
isProduction ? {
file: browser,
...settings,
name: name,
format: 'umd',
plugins: [
isProduction && terser()
]
} : null,
],
external: [],
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify( 'production' ),
'.css?inline': '.css',
preventAssignment: true,
}),
// replace({
// exclude: 'src/**',
// delimiters: ['', ''],
// values:{
// 'from \'three\'': 'from \'threepipe\'',
// },
// }),
glsl({ // todo: minify glsl.
include: "src/**/*.glsl"
}),
postcss({
extensions: ['.css', '.css?inline'],
modules: false,
autoModules: true, // todo; issues with typescript import css, because inject is false
inject: false,
minimize: isProduction,
// Or with custom options for `postcss-modules`
}),
json(),
resolve({}),
typescript({}),
commonjs({
include: 'node_modules/**',
extensions: ['.js'],
ignoreGlobal: false,
sourceMap: false
}),
license({
banner: `
@license
${name} v${version}
Copyright 2022<%= moment().format('YYYY') > 2022 ? '-' + moment().format('YYYY') : null %> ${author}
${packageJson.license} License
See ./dependencies.txt for bundled third-party dependencies and licenses.
`,
thirdParty: {
output: path.join(__dirname, 'dist', 'dependencies.txt'),
includePrivate: true, // Default is false.
},
})
]
}

Завантаження…
Відмінити
Зберегти