auto-svelte-pages-ts 1.2.2 → 2.2.2
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/CHANGELOG.md +19 -0
- package/README.md +27 -0
- package/package.json +1 -1
- package/src/cli.js +7 -0
- package/src/generator.js +173 -46
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `auto-svelte-pages-ts` will be documented in this file.
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
## [2.2.2] - 2026-04-11
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- Config file support via `auto-svelte-pages.config.ts`.
|
|
10
|
+
- New `--config <file>` option to load config from a custom path.
|
|
11
|
+
- Configurable defaults for:
|
|
12
|
+
- directories (`src`, `entry`, `component`)
|
|
13
|
+
- Vite input markers (`start`, `end`)
|
|
14
|
+
- CSS import path for generated entry files
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Option priority is now: CLI args > config file > built-in defaults.
|
|
18
|
+
- TypeScript-first config discovery now uses:
|
|
19
|
+
- `auto-svelte-pages.config.ts` (default)
|
|
20
|
+
- fallback to `auto-svelte-pages.config.js` for backward compatibility.
|
|
21
|
+
- Updated CLI/help and README to reflect the new default config filename.
|
|
22
|
+
|
|
23
|
+
|
|
5
24
|
## [1.2.2] - 2026-04-10
|
|
6
25
|
|
|
7
26
|
### Dropped
|
package/README.md
CHANGED
|
@@ -46,6 +46,8 @@ The CLI replaces only the content between those markers.
|
|
|
46
46
|
- `--component-dir <dir>` component directory under src (default: `component`)
|
|
47
47
|
- `--vite-config <file>` Vite config path from root (default: `vite.config.ts`)
|
|
48
48
|
- `--css-import <path>` CSS import path for generated entry files (default: `../app.css`)
|
|
49
|
+
- `--config <file>` config file path (default: `auto-svelte-pages.config.ts`, fallback `.js`)
|
|
50
|
+
- `--watch` watch root HTML files and regenerate on changes
|
|
49
51
|
|
|
50
52
|
## Script Setup Example
|
|
51
53
|
|
|
@@ -59,6 +61,31 @@ The CLI replaces only the content between those markers.
|
|
|
59
61
|
}
|
|
60
62
|
```
|
|
61
63
|
|
|
64
|
+
## Config File
|
|
65
|
+
|
|
66
|
+
Create `auto-svelte-pages.config.ts` in project root:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
export default {
|
|
70
|
+
dirs: {
|
|
71
|
+
src: 'src',
|
|
72
|
+
entry: 'entry',
|
|
73
|
+
component: 'component',
|
|
74
|
+
},
|
|
75
|
+
cssImport: '../app.css',
|
|
76
|
+
markers: {
|
|
77
|
+
start: '// AUTO-GENERATED VITE INPUT START',
|
|
78
|
+
end: '// AUTO-GENERATED VITE INPUT END',
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Priority order:
|
|
84
|
+
|
|
85
|
+
- CLI args
|
|
86
|
+
- config file
|
|
87
|
+
- built-in defaults
|
|
88
|
+
|
|
62
89
|
|
|
63
90
|
## Use
|
|
64
91
|
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -59,6 +59,12 @@ function parseArgs(argv) {
|
|
|
59
59
|
continue;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
if (arg === "--config") {
|
|
63
|
+
options.configPath = argv[i + 1];
|
|
64
|
+
i += 1;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
62
68
|
if (arg === "--help" || arg === "-h") {
|
|
63
69
|
options.help = true;
|
|
64
70
|
continue;
|
|
@@ -94,6 +100,7 @@ Options:
|
|
|
94
100
|
--component-dir <dir>Component dir under src (default: component)
|
|
95
101
|
--vite-config <file> Vite config path from root (default: vite.config.ts, fallback vite.config.js)
|
|
96
102
|
--css-import <path> CSS import path used in generated entry file (default: ../app.css)
|
|
103
|
+
--config <file> Config file path (default: auto-svelte-pages.config.ts, fallback .js)
|
|
97
104
|
--watch Watch root HTML files and regenerate on changes
|
|
98
105
|
--help, -h Show help
|
|
99
106
|
|
package/src/generator.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
-
const
|
|
5
|
+
const DEFAULT_INPUT_START_MARKER = "// AUTO-GENERATED VITE INPUT START";
|
|
6
|
+
const DEFAULT_INPUT_END_MARKER = "// AUTO-GENERATED VITE INPUT END";
|
|
7
|
+
const DEFAULT_CONFIG_TS_FILE = "auto-svelte-pages.config.ts";
|
|
8
|
+
const DEFAULT_CONFIG_JS_FILE = "auto-svelte-pages.config.js";
|
|
6
9
|
|
|
7
10
|
function toPascalCase(value) {
|
|
8
11
|
return value
|
|
@@ -22,13 +25,18 @@ function toViteInputKey(relativeHtmlPath) {
|
|
|
22
25
|
return segments.join("_").toLowerCase();
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
function
|
|
28
|
+
function toImportPath(fromDir, toFile) {
|
|
29
|
+
const relativePath = normalizePath(path.relative(fromDir, toFile));
|
|
30
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function entryTemplate(componentName, appCssImportPath, componentImportPath) {
|
|
26
34
|
return `import { mount } from 'svelte'
|
|
27
35
|
import '${appCssImportPath}'
|
|
28
|
-
import App from '
|
|
36
|
+
import App from '${componentImportPath}'
|
|
29
37
|
|
|
30
38
|
const app = mount(App, {
|
|
31
|
-
target: document.getElementById('app')
|
|
39
|
+
target: document.getElementById('app')!,
|
|
32
40
|
})
|
|
33
41
|
|
|
34
42
|
export default app
|
|
@@ -44,7 +52,10 @@ function componentTemplate(componentName) {
|
|
|
44
52
|
`;
|
|
45
53
|
}
|
|
46
54
|
|
|
47
|
-
function htmlTemplate(pageName) {
|
|
55
|
+
function htmlTemplate(pageName, entryDirName) {
|
|
56
|
+
const entrySrc = normalizePath(
|
|
57
|
+
path.join("src", entryDirName, `${pageName}.ts`),
|
|
58
|
+
);
|
|
48
59
|
return `<!DOCTYPE html>
|
|
49
60
|
<html lang="en">
|
|
50
61
|
<head>
|
|
@@ -54,7 +65,7 @@ function htmlTemplate(pageName) {
|
|
|
54
65
|
</head>
|
|
55
66
|
<body>
|
|
56
67
|
<div id="app"></div>
|
|
57
|
-
<script type="module" src="
|
|
68
|
+
<script type="module" src="./${entrySrc}"></script>
|
|
58
69
|
</body>
|
|
59
70
|
</html>
|
|
60
71
|
`;
|
|
@@ -90,7 +101,7 @@ async function listHtmlFilesRecursively(rootDir, dir, ignoreDirs) {
|
|
|
90
101
|
return htmlFiles;
|
|
91
102
|
}
|
|
92
103
|
|
|
93
|
-
function createInputBlock(relativeHtmlPaths) {
|
|
104
|
+
function createInputBlock(relativeHtmlPaths, markers) {
|
|
94
105
|
const pathByKey = new Map();
|
|
95
106
|
for (const relativePath of relativeHtmlPaths) {
|
|
96
107
|
pathByKey.set(toViteInputKey(relativePath), normalizePath(relativePath));
|
|
@@ -100,11 +111,9 @@ function createInputBlock(relativeHtmlPaths) {
|
|
|
100
111
|
.sort((a, b) => a[0].localeCompare(b[0]))
|
|
101
112
|
.map(([key, relativePath]) => ` ${key}: '${relativePath}',`);
|
|
102
113
|
|
|
103
|
-
return [
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
` ${INPUT_END_MARKER}`,
|
|
107
|
-
].join("\n");
|
|
114
|
+
return [` ${markers.start}`, ...lines, ` ${markers.end}`].join(
|
|
115
|
+
"\n",
|
|
116
|
+
);
|
|
108
117
|
}
|
|
109
118
|
|
|
110
119
|
function parseExistingInputEntries(blockContent) {
|
|
@@ -141,6 +150,56 @@ async function resolveDefaultViteConfigPath(rootDir) {
|
|
|
141
150
|
}
|
|
142
151
|
}
|
|
143
152
|
|
|
153
|
+
async function loadConfig(rootDir, configPathFromCli) {
|
|
154
|
+
let candidatePath = null;
|
|
155
|
+
if (configPathFromCli) {
|
|
156
|
+
candidatePath = path.resolve(rootDir, configPathFromCli);
|
|
157
|
+
try {
|
|
158
|
+
await fs.access(candidatePath);
|
|
159
|
+
} catch {
|
|
160
|
+
return {};
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
const tsCandidate = path.join(rootDir, DEFAULT_CONFIG_TS_FILE);
|
|
164
|
+
const jsCandidate = path.join(rootDir, DEFAULT_CONFIG_JS_FILE);
|
|
165
|
+
try {
|
|
166
|
+
await fs.access(tsCandidate);
|
|
167
|
+
candidatePath = tsCandidate;
|
|
168
|
+
} catch {
|
|
169
|
+
try {
|
|
170
|
+
await fs.access(jsCandidate);
|
|
171
|
+
candidatePath = jsCandidate;
|
|
172
|
+
} catch {
|
|
173
|
+
return {};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const configModule = await import(pathToFileURL(candidatePath).href);
|
|
179
|
+
const loadedConfig = configModule.default ?? configModule;
|
|
180
|
+
|
|
181
|
+
if (
|
|
182
|
+
!loadedConfig ||
|
|
183
|
+
typeof loadedConfig !== "object" ||
|
|
184
|
+
Array.isArray(loadedConfig)
|
|
185
|
+
) {
|
|
186
|
+
throw new Error(
|
|
187
|
+
`Invalid config file: ${path.relative(rootDir, candidatePath)}`,
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return loadedConfig;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function resolveConfigValue(...values) {
|
|
195
|
+
for (const value of values) {
|
|
196
|
+
if (value !== undefined) {
|
|
197
|
+
return value;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
|
|
144
203
|
async function resolveRootTargetHtmlFiles(rootDir, targets) {
|
|
145
204
|
const resolved = [];
|
|
146
205
|
for (const target of targets) {
|
|
@@ -189,23 +248,25 @@ async function writeIfNeeded(filePath, content) {
|
|
|
189
248
|
return "skipped";
|
|
190
249
|
}
|
|
191
250
|
|
|
192
|
-
async function writeHtmlBoilerplateIfNeeded(htmlPath, pageName) {
|
|
251
|
+
async function writeHtmlBoilerplateIfNeeded(htmlPath, pageName, entryDirName) {
|
|
193
252
|
const existingContent = await fs.readFile(htmlPath, "utf8");
|
|
194
253
|
if (existingContent.trim().length > 0) {
|
|
195
254
|
return "skipped";
|
|
196
255
|
}
|
|
197
256
|
|
|
198
|
-
await fs.writeFile(htmlPath, htmlTemplate(pageName), "utf8");
|
|
257
|
+
await fs.writeFile(htmlPath, htmlTemplate(pageName, entryDirName), "utf8");
|
|
199
258
|
return "templated";
|
|
200
259
|
}
|
|
201
260
|
|
|
202
|
-
async function updateViteInput({
|
|
261
|
+
async function updateViteInput({
|
|
262
|
+
rootDir,
|
|
263
|
+
viteConfigPath,
|
|
264
|
+
htmlFiles,
|
|
265
|
+
markers,
|
|
266
|
+
}) {
|
|
203
267
|
const viteContent = await fs.readFile(viteConfigPath, "utf8");
|
|
204
|
-
const escapedStart =
|
|
205
|
-
|
|
206
|
-
"\\$&",
|
|
207
|
-
);
|
|
208
|
-
const escapedEnd = INPUT_END_MARKER.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
268
|
+
const escapedStart = markers.start.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
269
|
+
const escapedEnd = markers.end.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
209
270
|
const markerPattern = getMarkerPattern(escapedStart, escapedEnd);
|
|
210
271
|
|
|
211
272
|
if (!markerPattern.test(viteContent)) {
|
|
@@ -213,13 +274,13 @@ async function updateViteInput({ rootDir, viteConfigPath, htmlFiles }) {
|
|
|
213
274
|
`Cannot update Vite input. Missing markers in ${path.relative(
|
|
214
275
|
rootDir,
|
|
215
276
|
viteConfigPath,
|
|
216
|
-
)}: "${
|
|
277
|
+
)}: "${markers.start}" and "${markers.end}".`,
|
|
217
278
|
);
|
|
218
279
|
}
|
|
219
280
|
|
|
220
281
|
const nextContent = viteContent.replace(
|
|
221
282
|
markerPattern,
|
|
222
|
-
createInputBlock(htmlFiles),
|
|
283
|
+
createInputBlock(htmlFiles, markers),
|
|
223
284
|
);
|
|
224
285
|
await fs.writeFile(viteConfigPath, nextContent, "utf8");
|
|
225
286
|
}
|
|
@@ -228,13 +289,11 @@ async function upsertViteInputTargets({
|
|
|
228
289
|
rootDir,
|
|
229
290
|
viteConfigPath,
|
|
230
291
|
htmlTargets,
|
|
292
|
+
markers,
|
|
231
293
|
}) {
|
|
232
294
|
const viteContent = await fs.readFile(viteConfigPath, "utf8");
|
|
233
|
-
const escapedStart =
|
|
234
|
-
|
|
235
|
-
"\\$&",
|
|
236
|
-
);
|
|
237
|
-
const escapedEnd = INPUT_END_MARKER.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
295
|
+
const escapedStart = markers.start.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
296
|
+
const escapedEnd = markers.end.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
238
297
|
const markerPattern = getMarkerPattern(escapedStart, escapedEnd);
|
|
239
298
|
const match = viteContent.match(markerPattern);
|
|
240
299
|
|
|
@@ -243,7 +302,7 @@ async function upsertViteInputTargets({
|
|
|
243
302
|
`Cannot update Vite input. Missing markers in ${path.relative(
|
|
244
303
|
rootDir,
|
|
245
304
|
viteConfigPath,
|
|
246
|
-
)}: "${
|
|
305
|
+
)}: "${markers.start}" and "${markers.end}".`,
|
|
247
306
|
);
|
|
248
307
|
}
|
|
249
308
|
|
|
@@ -255,28 +314,90 @@ async function upsertViteInputTargets({
|
|
|
255
314
|
const mergedPaths = [...existingEntries.values()];
|
|
256
315
|
const nextContent = viteContent.replace(
|
|
257
316
|
markerPattern,
|
|
258
|
-
createInputBlock(mergedPaths),
|
|
317
|
+
createInputBlock(mergedPaths, markers),
|
|
259
318
|
);
|
|
260
319
|
await fs.writeFile(viteConfigPath, nextContent, "utf8");
|
|
261
320
|
}
|
|
262
321
|
|
|
263
322
|
export async function generatePages(userOptions = {}) {
|
|
264
323
|
const rootDir = path.resolve(userOptions.rootDir ?? process.cwd());
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
srcDir,
|
|
269
|
-
|
|
324
|
+
const loadedConfig = await loadConfig(rootDir, userOptions.configPath);
|
|
325
|
+
|
|
326
|
+
const srcDirName = resolveConfigValue(
|
|
327
|
+
userOptions.srcDir,
|
|
328
|
+
loadedConfig.srcDir,
|
|
329
|
+
loadedConfig.dirs?.src,
|
|
330
|
+
loadedConfig.dir?.src,
|
|
331
|
+
"src",
|
|
332
|
+
);
|
|
333
|
+
const entryDirName = resolveConfigValue(
|
|
334
|
+
userOptions.entryDir,
|
|
335
|
+
loadedConfig.entryDir,
|
|
336
|
+
loadedConfig.dirs?.entry,
|
|
337
|
+
loadedConfig.dir?.entry,
|
|
338
|
+
"entry",
|
|
339
|
+
);
|
|
340
|
+
const componentDirName = resolveConfigValue(
|
|
341
|
+
userOptions.componentDir,
|
|
342
|
+
loadedConfig.componentDir,
|
|
343
|
+
loadedConfig.dirs?.component,
|
|
344
|
+
loadedConfig.dir?.component,
|
|
345
|
+
"component",
|
|
270
346
|
);
|
|
271
|
-
const
|
|
272
|
-
|
|
347
|
+
const viteConfigFile = resolveConfigValue(
|
|
348
|
+
userOptions.viteConfig,
|
|
349
|
+
loadedConfig.viteConfig,
|
|
350
|
+
undefined,
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
const srcDir = path.join(rootDir, srcDirName);
|
|
354
|
+
const entryDir = path.join(srcDir, entryDirName);
|
|
355
|
+
const componentDir = path.join(srcDir, componentDirName);
|
|
356
|
+
const viteConfigPath = viteConfigFile
|
|
357
|
+
? path.join(rootDir, viteConfigFile)
|
|
273
358
|
: await resolveDefaultViteConfigPath(rootDir);
|
|
274
|
-
|
|
275
|
-
const
|
|
359
|
+
|
|
360
|
+
const updateVite =
|
|
361
|
+
resolveConfigValue(
|
|
362
|
+
userOptions.updateVite,
|
|
363
|
+
loadedConfig.updateVite,
|
|
364
|
+
true,
|
|
365
|
+
) !== false;
|
|
366
|
+
const includeNestedHtml =
|
|
367
|
+
resolveConfigValue(
|
|
368
|
+
userOptions.includeNestedHtml,
|
|
369
|
+
loadedConfig.includeNestedHtml,
|
|
370
|
+
true,
|
|
371
|
+
) !== false;
|
|
276
372
|
const ignoreDirs = new Set(
|
|
277
|
-
userOptions.ignoreDirs
|
|
373
|
+
resolveConfigValue(userOptions.ignoreDirs, loadedConfig.ignoreDirs, [
|
|
374
|
+
".git",
|
|
375
|
+
"node_modules",
|
|
376
|
+
"dist",
|
|
377
|
+
]),
|
|
378
|
+
);
|
|
379
|
+
const appCssImportPath = resolveConfigValue(
|
|
380
|
+
userOptions.appCssImportPath,
|
|
381
|
+
loadedConfig.appCssImportPath,
|
|
382
|
+
loadedConfig.cssImport,
|
|
383
|
+
"../app.css",
|
|
278
384
|
);
|
|
279
|
-
const
|
|
385
|
+
const markers = {
|
|
386
|
+
start: resolveConfigValue(
|
|
387
|
+
userOptions.inputStartMarker,
|
|
388
|
+
loadedConfig.inputStartMarker,
|
|
389
|
+
loadedConfig.markers?.start,
|
|
390
|
+
loadedConfig.marker?.start,
|
|
391
|
+
DEFAULT_INPUT_START_MARKER,
|
|
392
|
+
),
|
|
393
|
+
end: resolveConfigValue(
|
|
394
|
+
userOptions.inputEndMarker,
|
|
395
|
+
loadedConfig.inputEndMarker,
|
|
396
|
+
loadedConfig.markers?.end,
|
|
397
|
+
loadedConfig.marker?.end,
|
|
398
|
+
DEFAULT_INPUT_END_MARKER,
|
|
399
|
+
),
|
|
400
|
+
};
|
|
280
401
|
const targetFiles = Array.isArray(userOptions.targets)
|
|
281
402
|
? userOptions.targets
|
|
282
403
|
: [];
|
|
@@ -301,15 +422,20 @@ export async function generatePages(userOptions = {}) {
|
|
|
301
422
|
const htmlPath = path.join(rootDir, htmlFile);
|
|
302
423
|
const entryPath = path.join(entryDir, `${baseName}.ts`);
|
|
303
424
|
const componentPath = path.join(componentDir, `${componentName}.svelte`);
|
|
425
|
+
const componentImportPath = toImportPath(entryDir, componentPath);
|
|
304
426
|
|
|
305
|
-
const htmlResult = await writeHtmlBoilerplateIfNeeded(
|
|
427
|
+
const htmlResult = await writeHtmlBoilerplateIfNeeded(
|
|
428
|
+
htmlPath,
|
|
429
|
+
baseName,
|
|
430
|
+
entryDirName,
|
|
431
|
+
);
|
|
306
432
|
logs.push(
|
|
307
433
|
`${htmlResult.toUpperCase()} ${path.relative(rootDir, htmlPath)}`,
|
|
308
434
|
);
|
|
309
435
|
|
|
310
436
|
const entryResult = await writeIfNeeded(
|
|
311
437
|
entryPath,
|
|
312
|
-
entryTemplate(componentName, appCssImportPath),
|
|
438
|
+
entryTemplate(componentName, appCssImportPath, componentImportPath),
|
|
313
439
|
);
|
|
314
440
|
logs.push(
|
|
315
441
|
`${entryResult.toUpperCase()} ${path.relative(rootDir, entryPath)}`,
|
|
@@ -330,13 +456,14 @@ export async function generatePages(userOptions = {}) {
|
|
|
330
456
|
rootDir,
|
|
331
457
|
viteConfigPath,
|
|
332
458
|
htmlTargets: rootHtmlFiles,
|
|
459
|
+
markers,
|
|
333
460
|
});
|
|
334
461
|
} else {
|
|
335
462
|
const htmlFiles = includeNestedHtml
|
|
336
463
|
? await listHtmlFilesRecursively(rootDir, rootDir, ignoreDirs)
|
|
337
464
|
: rootHtmlFiles;
|
|
338
465
|
htmlFiles.sort((a, b) => a.localeCompare(b));
|
|
339
|
-
await updateViteInput({ rootDir, viteConfigPath, htmlFiles });
|
|
466
|
+
await updateViteInput({ rootDir, viteConfigPath, htmlFiles, markers });
|
|
340
467
|
}
|
|
341
468
|
logs.push(`UPDATED ${path.relative(rootDir, viteConfigPath)} Vite input`);
|
|
342
469
|
}
|
|
@@ -349,8 +476,8 @@ export async function generatePages(userOptions = {}) {
|
|
|
349
476
|
rootHtmlFiles,
|
|
350
477
|
logs,
|
|
351
478
|
markers: {
|
|
352
|
-
start:
|
|
353
|
-
end:
|
|
479
|
+
start: markers.start,
|
|
480
|
+
end: markers.end,
|
|
354
481
|
},
|
|
355
482
|
};
|
|
356
483
|
}
|