@svgedit/svgcanvas 7.2.6 → 7.4.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.
- package/CHANGES.md +6 -0
- package/common/browser.js +104 -37
- package/common/logger.js +151 -0
- package/common/util.js +96 -155
- package/core/blur-event.js +106 -42
- package/core/clear.js +13 -3
- package/core/coords.js +214 -90
- package/core/copy-elem.js +27 -13
- package/core/dataStorage.js +84 -21
- package/core/draw.js +80 -40
- package/core/elem-get-set.js +161 -77
- package/core/event.js +143 -28
- package/core/history.js +51 -31
- package/core/historyrecording.js +4 -2
- package/core/json.js +54 -12
- package/core/layer.js +11 -17
- package/core/math.js +102 -23
- package/core/namespaces.js +5 -5
- package/core/paint.js +100 -23
- package/core/paste-elem.js +58 -19
- package/core/path-actions.js +812 -791
- package/core/path-method.js +236 -37
- package/core/path.js +45 -10
- package/core/recalculate.js +438 -24
- package/core/sanitize.js +71 -34
- package/core/select.js +44 -20
- package/core/selected-elem.js +146 -31
- package/core/selection.js +16 -6
- package/core/svg-exec.js +103 -29
- package/core/svgroot.js +1 -1
- package/core/text-actions.js +327 -306
- package/core/undo.js +20 -5
- package/core/units.js +8 -6
- package/core/utilities.js +316 -203
- package/dist/svgcanvas.js +31616 -53281
- package/dist/svgcanvas.js.map +1 -1
- package/package.json +55 -54
- package/publish.md +1 -6
- package/svgcanvas.d.ts +225 -0
- package/svgcanvas.js +9 -9
- package/vite.config.mjs +20 -0
- package/rollup.config.mjs +0 -38
package/package.json
CHANGED
|
@@ -1,58 +1,59 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
2
|
+
"name": "@svgedit/svgcanvas",
|
|
3
|
+
"version": "7.4.1",
|
|
4
|
+
"description": "SVG Canvas",
|
|
5
|
+
"main": "dist/svgcanvas.js",
|
|
6
|
+
"types": "svgcanvas.d.ts",
|
|
7
|
+
"author": "Narendra Sisodiya",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/SVG-Edit/svgedit/issues"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/SVG-Edit/svgedit.git"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/SVG-Edit/svgedit#readme",
|
|
19
|
+
"contributors": [
|
|
20
|
+
"Pavol Rusnak",
|
|
21
|
+
"Jeff Schiller",
|
|
22
|
+
"Vidar Hokstad",
|
|
23
|
+
"Alexis Deveria",
|
|
24
|
+
"Brett Zamir",
|
|
25
|
+
"Fabien Jacq",
|
|
26
|
+
"OptimistikSAS"
|
|
27
|
+
],
|
|
28
|
+
"keywords": [
|
|
29
|
+
"svg-editor",
|
|
30
|
+
"javascript",
|
|
31
|
+
"svg-edit",
|
|
32
|
+
"svg",
|
|
33
|
+
"svgcanvas"
|
|
34
|
+
],
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"browserslist": [
|
|
37
|
+
"defaults",
|
|
38
|
+
"not IE 11",
|
|
39
|
+
"not OperaMini all"
|
|
40
|
+
],
|
|
41
|
+
"standard": {
|
|
42
|
+
"ignore": [
|
|
43
|
+
"dist"
|
|
26
44
|
],
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"svg-edit",
|
|
31
|
-
"svg",
|
|
32
|
-
"svgcanvas"
|
|
45
|
+
"globals": [
|
|
46
|
+
"cy",
|
|
47
|
+
"assert"
|
|
33
48
|
],
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"globals": [
|
|
45
|
-
"cy",
|
|
46
|
-
"assert"
|
|
47
|
-
],
|
|
48
|
-
"env": [
|
|
49
|
-
"mocha",
|
|
50
|
-
"browser"
|
|
51
|
-
]
|
|
52
|
-
},
|
|
53
|
-
"scripts": {
|
|
54
|
-
"build": "rollup -c",
|
|
55
|
-
"prebuild": "standard . && npm i",
|
|
56
|
-
"prepublishOnly": "npm run build"
|
|
57
|
-
}
|
|
49
|
+
"env": [
|
|
50
|
+
"mocha",
|
|
51
|
+
"browser"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "vite build",
|
|
56
|
+
"prebuild": "standard . && npm i",
|
|
57
|
+
"prepublishOnly": "npm run build"
|
|
58
|
+
}
|
|
58
59
|
}
|
package/publish.md
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
|
|
2
|
-
1. update the version number in package.json
|
|
3
|
-
2. run 'npm install' to update the corresponding package-lock.json
|
|
4
|
-
3. update the CHANGES.md
|
|
5
|
-
4. run 'npm publish' (that will automate the build)
|
|
6
|
-
5. create a commit with above changes called 'release x.y.z'
|
|
1
|
+
see docs/ReleaseInstructions.md
|
package/svgcanvas.d.ts
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript definitions for @svgedit/svgcanvas
|
|
3
|
+
* @module @svgedit/svgcanvas
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Core types
|
|
7
|
+
export interface SVGElementJSON {
|
|
8
|
+
element: string
|
|
9
|
+
attr: Record<string, string>
|
|
10
|
+
curStyles?: boolean
|
|
11
|
+
children?: SVGElementJSON[]
|
|
12
|
+
namespace?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface Config {
|
|
16
|
+
canvasName?: string
|
|
17
|
+
canvas_expansion?: number
|
|
18
|
+
initFill?: {
|
|
19
|
+
color?: string
|
|
20
|
+
opacity?: number
|
|
21
|
+
}
|
|
22
|
+
initStroke?: {
|
|
23
|
+
width?: number
|
|
24
|
+
color?: string
|
|
25
|
+
opacity?: number
|
|
26
|
+
}
|
|
27
|
+
text?: {
|
|
28
|
+
stroke_width?: number
|
|
29
|
+
font_size?: number
|
|
30
|
+
font_family?: string
|
|
31
|
+
}
|
|
32
|
+
selectionColor?: string
|
|
33
|
+
imgPath?: string
|
|
34
|
+
extensions?: string[]
|
|
35
|
+
initTool?: string
|
|
36
|
+
wireframe?: boolean
|
|
37
|
+
showlayers?: boolean
|
|
38
|
+
no_save_warning?: boolean
|
|
39
|
+
imgImport?: boolean
|
|
40
|
+
baseUnit?: string
|
|
41
|
+
snappingStep?: number
|
|
42
|
+
gridSnapping?: boolean
|
|
43
|
+
gridColor?: string
|
|
44
|
+
dimensions?: [number, number]
|
|
45
|
+
initOpacity?: number
|
|
46
|
+
colorPickerCSS?: string | null
|
|
47
|
+
initRight?: string
|
|
48
|
+
initBottom?: string
|
|
49
|
+
show_outside_canvas?: boolean
|
|
50
|
+
selectNew?: boolean
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface Resolution {
|
|
54
|
+
w: number
|
|
55
|
+
h: number
|
|
56
|
+
zoom?: number
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface BBox {
|
|
60
|
+
x: number
|
|
61
|
+
y: number
|
|
62
|
+
width: number
|
|
63
|
+
height: number
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface EditorContext {
|
|
67
|
+
getSvgContent(): SVGSVGElement
|
|
68
|
+
addSVGElementsFromJson(data: SVGElementJSON): Element
|
|
69
|
+
getSelectedElements(): Element[]
|
|
70
|
+
getDOMDocument(): HTMLDocument
|
|
71
|
+
getDOMContainer(): HTMLElement
|
|
72
|
+
getSvgRoot(): SVGSVGElement
|
|
73
|
+
getBaseUnit(): string
|
|
74
|
+
getSnappingStep(): number | string
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Paint types
|
|
78
|
+
export interface PaintOptions {
|
|
79
|
+
alpha?: number
|
|
80
|
+
solidColor?: string
|
|
81
|
+
type?: 'solidColor' | 'linearGradient' | 'radialGradient' | 'none'
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// History command types
|
|
85
|
+
export interface HistoryCommand {
|
|
86
|
+
apply(handler: HistoryEventHandler): void | true
|
|
87
|
+
unapply(handler: HistoryEventHandler): void | true
|
|
88
|
+
elements(): Element[]
|
|
89
|
+
type(): string
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface HistoryEventHandler {
|
|
93
|
+
handleHistoryEvent(eventType: string, cmd: HistoryCommand): void
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface UndoManager {
|
|
97
|
+
getUndoStackSize(): number
|
|
98
|
+
getRedoStackSize(): number
|
|
99
|
+
getNextUndoCommandText(): string
|
|
100
|
+
getNextRedoCommandText(): string
|
|
101
|
+
resetUndoStack(): void
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Logger types
|
|
105
|
+
export enum LogLevel {
|
|
106
|
+
NONE = 0,
|
|
107
|
+
ERROR = 1,
|
|
108
|
+
WARN = 2,
|
|
109
|
+
INFO = 3,
|
|
110
|
+
DEBUG = 4
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface Logger {
|
|
114
|
+
LogLevel: typeof LogLevel
|
|
115
|
+
setLogLevel(level: LogLevel): void
|
|
116
|
+
setLoggingEnabled(enabled: boolean): void
|
|
117
|
+
setLogPrefix(prefix: string): void
|
|
118
|
+
error(message: string, error?: Error | any, context?: string): void
|
|
119
|
+
warn(message: string, data?: any, context?: string): void
|
|
120
|
+
info(message: string, data?: any, context?: string): void
|
|
121
|
+
debug(message: string, data?: any, context?: string): void
|
|
122
|
+
getConfig(): { currentLevel: LogLevel; enabled: boolean; prefix: string }
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Main SvgCanvas class
|
|
126
|
+
export default class SvgCanvas {
|
|
127
|
+
constructor(container: HTMLElement, config?: Partial<Config>)
|
|
128
|
+
|
|
129
|
+
// Core methods
|
|
130
|
+
getSvgContent(): SVGSVGElement
|
|
131
|
+
getSvgRoot(): SVGSVGElement
|
|
132
|
+
getSvgString(): string
|
|
133
|
+
setSvgString(xmlString: string, preventUndo?: boolean): boolean
|
|
134
|
+
clearSelection(noCall?: boolean): void
|
|
135
|
+
selectOnly(elements: Element[], showGrips?: boolean): void
|
|
136
|
+
getResolution(): Resolution
|
|
137
|
+
setResolution(width: number | string, height: number | string): boolean
|
|
138
|
+
getZoom(): number
|
|
139
|
+
setZoom(zoomLevel: number): void
|
|
140
|
+
|
|
141
|
+
// Element manipulation
|
|
142
|
+
moveSelectedElements(dx: number, dy: number, undoable?: boolean): void
|
|
143
|
+
deleteSelectedElements(): void
|
|
144
|
+
cutSelectedElements(): void
|
|
145
|
+
copySelectedElements(): void
|
|
146
|
+
pasteElements(type?: string, x?: number, y?: number): void
|
|
147
|
+
groupSelectedElements(type?: string, urlArg?: string): Element | null
|
|
148
|
+
ungroupSelectedElement(): void
|
|
149
|
+
moveToTopSelectedElement(): void
|
|
150
|
+
moveToBottomSelectedElement(): void
|
|
151
|
+
moveUpDownSelected(dir: 'Up' | 'Down'): void
|
|
152
|
+
|
|
153
|
+
// Path operations
|
|
154
|
+
pathActions: {
|
|
155
|
+
clear: () => void
|
|
156
|
+
resetOrientation: (path: SVGPathElement) => boolean
|
|
157
|
+
zoomChange: () => void
|
|
158
|
+
getNodePoint: () => {x: number, y: number}
|
|
159
|
+
linkControlPoints: (linkPoints: boolean) => void
|
|
160
|
+
clonePathNode: () => void
|
|
161
|
+
deletePathNode: () => void
|
|
162
|
+
smoothPolylineIntoPath: () => void
|
|
163
|
+
setSegType: (type: number) => void
|
|
164
|
+
moveNode: (attr: string, newValue: number) => void
|
|
165
|
+
selectNode: (node?: Element) => void
|
|
166
|
+
opencloseSubPath: () => void
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Layer operations
|
|
170
|
+
getCurrentDrawing(): any
|
|
171
|
+
getNumLayers(): number
|
|
172
|
+
getLayer(name: string): any
|
|
173
|
+
getCurrentLayerName(): string
|
|
174
|
+
setCurrentLayer(name: string): boolean
|
|
175
|
+
renameCurrentLayer(newName: string): boolean
|
|
176
|
+
setCurrentLayerPosition(newPos: number): boolean
|
|
177
|
+
setLayerVisibility(name: string, bVisible: boolean): void
|
|
178
|
+
moveSelectedToLayer(layerName: string): void
|
|
179
|
+
cloneLayer(name?: string): void
|
|
180
|
+
deleteCurrentLayer(): boolean
|
|
181
|
+
|
|
182
|
+
// Drawing modes
|
|
183
|
+
setMode(name: string): void
|
|
184
|
+
getMode(): string
|
|
185
|
+
|
|
186
|
+
// Undo/Redo
|
|
187
|
+
undoMgr: UndoManager
|
|
188
|
+
undo(): void
|
|
189
|
+
redo(): void
|
|
190
|
+
|
|
191
|
+
// Events
|
|
192
|
+
call(event: string, args?: any[]): void
|
|
193
|
+
bind(event: string, callback: Function): void
|
|
194
|
+
unbind(event: string, callback: Function): void
|
|
195
|
+
|
|
196
|
+
// Attribute manipulation
|
|
197
|
+
changeSelectedAttribute(attr: string, val: string | number, elems?: Element[]): void
|
|
198
|
+
changeSelectedAttributeNoUndo(attr: string, val: string | number, elems?: Element[]): void
|
|
199
|
+
|
|
200
|
+
// Canvas properties
|
|
201
|
+
contentW: number
|
|
202
|
+
contentH: number
|
|
203
|
+
|
|
204
|
+
// Text operations
|
|
205
|
+
textActions: any
|
|
206
|
+
|
|
207
|
+
// Extensions
|
|
208
|
+
addExtension(name: string, extFunc: Function): void
|
|
209
|
+
|
|
210
|
+
// Export
|
|
211
|
+
getSvgString(): string
|
|
212
|
+
embedImage(dataURI: string): Promise<Element>
|
|
213
|
+
|
|
214
|
+
// Other utilities
|
|
215
|
+
getPrivateMethods(): any
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Export additional utilities
|
|
219
|
+
export * from './common/logger.js'
|
|
220
|
+
export { NS } from './core/namespaces.js'
|
|
221
|
+
export * from './core/math.js'
|
|
222
|
+
export * from './core/units.js'
|
|
223
|
+
export * from './core/utilities.js'
|
|
224
|
+
export { sanitizeSvg } from './core/sanitize.js'
|
|
225
|
+
export { default as dataStorage } from './core/dataStorage.js'
|
package/svgcanvas.js
CHANGED
|
@@ -201,7 +201,7 @@ class SvgCanvas {
|
|
|
201
201
|
this.curConfig.initFill.color,
|
|
202
202
|
fill_paint: null,
|
|
203
203
|
fill_opacity: this.curConfig.initFill.opacity,
|
|
204
|
-
stroke:
|
|
204
|
+
stroke: `#${this.curConfig.initStroke.color}`,
|
|
205
205
|
stroke_paint: null,
|
|
206
206
|
stroke_opacity: this.curConfig.initStroke.opacity,
|
|
207
207
|
stroke_width: this.curConfig.initStroke.width,
|
|
@@ -288,9 +288,9 @@ class SvgCanvas {
|
|
|
288
288
|
*/
|
|
289
289
|
const storageChange = ev => {
|
|
290
290
|
if (!ev.newValue) return // This is a call from removeItem.
|
|
291
|
-
if (ev.key === CLIPBOARD_ID
|
|
291
|
+
if (ev.key === `${CLIPBOARD_ID}_startup`) {
|
|
292
292
|
// Another tab asked for our sessionStorage.
|
|
293
|
-
localStorage.removeItem(CLIPBOARD_ID
|
|
293
|
+
localStorage.removeItem(`${CLIPBOARD_ID}_startup`)
|
|
294
294
|
this.flashStorage()
|
|
295
295
|
} else if (ev.key === CLIPBOARD_ID) {
|
|
296
296
|
// Another tab sent data.
|
|
@@ -301,7 +301,7 @@ class SvgCanvas {
|
|
|
301
301
|
// Listen for changes to localStorage.
|
|
302
302
|
window.addEventListener('storage', storageChange, false)
|
|
303
303
|
// Ask other tabs for sessionStorage (this is ONLY to trigger event).
|
|
304
|
-
localStorage.setItem(CLIPBOARD_ID
|
|
304
|
+
localStorage.setItem(`${CLIPBOARD_ID}_startup`, Math.random())
|
|
305
305
|
|
|
306
306
|
pasteInit(this)
|
|
307
307
|
|
|
@@ -902,7 +902,7 @@ class SvgCanvas {
|
|
|
902
902
|
})
|
|
903
903
|
Object.values(attrs).forEach(val => {
|
|
904
904
|
if (val?.startsWith('url(')) {
|
|
905
|
-
const id = getUrlFromAttr(val).
|
|
905
|
+
const id = getUrlFromAttr(val).slice(1)
|
|
906
906
|
const ref = getElement(id)
|
|
907
907
|
if (!ref) {
|
|
908
908
|
findDefs().append(this.removedElements[id])
|
|
@@ -1138,11 +1138,11 @@ class SvgCanvas {
|
|
|
1138
1138
|
* @returns {void}
|
|
1139
1139
|
*/
|
|
1140
1140
|
setPaintOpacity (type, val, preventUndo) {
|
|
1141
|
-
this.curShape[type
|
|
1141
|
+
this.curShape[`${type}_opacity`] = val
|
|
1142
1142
|
if (!preventUndo) {
|
|
1143
|
-
this.changeSelectedAttribute(type
|
|
1143
|
+
this.changeSelectedAttribute(`${type}-opacity`, val)
|
|
1144
1144
|
} else {
|
|
1145
|
-
this.changeSelectedAttributeNoUndo(type
|
|
1145
|
+
this.changeSelectedAttributeNoUndo(`${type}-opacity`, val)
|
|
1146
1146
|
}
|
|
1147
1147
|
}
|
|
1148
1148
|
|
|
@@ -1167,7 +1167,7 @@ class SvgCanvas {
|
|
|
1167
1167
|
if (elem) {
|
|
1168
1168
|
const filterUrl = elem.getAttribute('filter')
|
|
1169
1169
|
if (filterUrl) {
|
|
1170
|
-
const blur = getElement(elem.id
|
|
1170
|
+
const blur = getElement(`${elem.id}_blur`)
|
|
1171
1171
|
if (blur) {
|
|
1172
1172
|
val = blur.firstChild.getAttribute('stdDeviation')
|
|
1173
1173
|
} else {
|
package/vite.config.mjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { resolve } from 'node:path'
|
|
2
|
+
import { defineConfig } from 'vite'
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
build: {
|
|
6
|
+
outDir: 'dist',
|
|
7
|
+
emptyOutDir: true,
|
|
8
|
+
sourcemap: true,
|
|
9
|
+
lib: {
|
|
10
|
+
entry: resolve(__dirname, 'svgcanvas.js'),
|
|
11
|
+
formats: ['es'],
|
|
12
|
+
fileName: () => 'svgcanvas.js'
|
|
13
|
+
},
|
|
14
|
+
rollupOptions: {
|
|
15
|
+
output: {
|
|
16
|
+
inlineDynamicImports: true
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
})
|
package/rollup.config.mjs
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/* eslint-env node */
|
|
2
|
-
// This rollup script is run by the command:
|
|
3
|
-
// 'npm run build'
|
|
4
|
-
|
|
5
|
-
import { rimraf } from 'rimraf'
|
|
6
|
-
import babel from '@rollup/plugin-babel'
|
|
7
|
-
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
|
8
|
-
import commonjs from '@rollup/plugin-commonjs'
|
|
9
|
-
|
|
10
|
-
// import progress from 'rollup-plugin-progress';
|
|
11
|
-
import filesize from 'rollup-plugin-filesize'
|
|
12
|
-
|
|
13
|
-
// remove existing distribution
|
|
14
|
-
await rimraf('./dist')
|
|
15
|
-
console.info('recreating dist')
|
|
16
|
-
|
|
17
|
-
// config for svgedit core module
|
|
18
|
-
const config = [{
|
|
19
|
-
input: ['./svgcanvas.js'],
|
|
20
|
-
output: [
|
|
21
|
-
{
|
|
22
|
-
format: 'es',
|
|
23
|
-
inlineDynamicImports: true,
|
|
24
|
-
sourcemap: true,
|
|
25
|
-
file: 'dist/svgcanvas.js'
|
|
26
|
-
}
|
|
27
|
-
],
|
|
28
|
-
plugins: [
|
|
29
|
-
nodeResolve({
|
|
30
|
-
browser: true,
|
|
31
|
-
preferBuiltins: false
|
|
32
|
-
}),
|
|
33
|
-
commonjs(),
|
|
34
|
-
babel({ babelHelpers: 'bundled', exclude: [/\/core-js\//] }), // exclude core-js to avoid circular dependencies.
|
|
35
|
-
filesize()
|
|
36
|
-
]
|
|
37
|
-
}]
|
|
38
|
-
export default config
|