@storybook/addon-svelte-csf 3.0.0-next.3 → 3.0.0-next.4
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/dist/cjs/config-loader.js +187 -0
- package/dist/cjs/preset/indexer.js +11 -1
- package/dist/esm/config-loader.js +187 -0
- package/dist/esm/preset/indexer.js +11 -1
- package/package.json +2 -1
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// This file is a rewrite of `@sveltejs/vite-plugin-svelte` without the `Vite`
|
|
2
|
+
// parts: https://github.com/sveltejs/vite-plugin-svelte/blob/e8e52deef93948da735c4ab69c54aced914926cf/packages/vite-plugin-svelte/src/utils/load-svelte-config.ts
|
|
3
|
+
import { logger } from '@storybook/client-logger';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import { pathExists } from "fs-extra";
|
|
8
|
+
import { pathToFileURL, fileURLToPath } from 'url';
|
|
9
|
+
/**
|
|
10
|
+
* Try find svelte config and then load it.
|
|
11
|
+
*
|
|
12
|
+
* @returns {import('@sveltejs/kit').Config | undefined}
|
|
13
|
+
* Returns the svelte configuration object.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export async function loadSvelteConfig() {
|
|
17
|
+
const configFile = await findSvelteConfig(); // no need to throw error since we handle projects without config files
|
|
18
|
+
|
|
19
|
+
if (configFile === undefined) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let err; // try to use dynamic import for svelte.config.js first
|
|
24
|
+
|
|
25
|
+
if (configFile.endsWith('.js') || configFile.endsWith('.mjs')) {
|
|
26
|
+
try {
|
|
27
|
+
return importSvelteOptions(configFile);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
logger.error(`failed to import config ${configFile}`, e);
|
|
30
|
+
err = e;
|
|
31
|
+
}
|
|
32
|
+
} // cjs or error with dynamic import
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if (configFile.endsWith('.js') || configFile.endsWith('.cjs')) {
|
|
36
|
+
try {
|
|
37
|
+
return requireSvelteOptions(configFile);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
logger.error(`failed to require config ${configFile}`, e);
|
|
40
|
+
|
|
41
|
+
if (!err) {
|
|
42
|
+
err = e;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
} // failed to load existing config file
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
throw new Error(`failed to load config ${configFile}`, {
|
|
49
|
+
cause: err
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const importSvelteOptions = (() => {
|
|
54
|
+
// hide dynamic import from ts transform to prevent it turning into a require
|
|
55
|
+
// see https://github.com/microsoft/TypeScript/issues/43329#issuecomment-811606238
|
|
56
|
+
// also use timestamp query to avoid caching on reload
|
|
57
|
+
const dynamicImportDefault = new Function('path', 'timestamp', 'return import(path + "?t=" + timestamp).then(m => m.default)');
|
|
58
|
+
/**
|
|
59
|
+
* Try import specified svelte configuration.
|
|
60
|
+
*
|
|
61
|
+
* @param {string} configFile
|
|
62
|
+
* Absolute path of the svelte config file to import.
|
|
63
|
+
*
|
|
64
|
+
* @returns {import('@sveltejs/kit').Config}
|
|
65
|
+
* Returns the svelte configuration object.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
return async configFile => {
|
|
69
|
+
const result = await dynamicImportDefault(pathToFileURL(configFile).href, fs.statSync(configFile).mtimeMs);
|
|
70
|
+
|
|
71
|
+
if (result != null) {
|
|
72
|
+
return { ...result,
|
|
73
|
+
configFile
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
throw new Error(`invalid export in ${configFile}`);
|
|
78
|
+
};
|
|
79
|
+
})();
|
|
80
|
+
|
|
81
|
+
const requireSvelteOptions = (() => {
|
|
82
|
+
/** @type {NodeRequire} */
|
|
83
|
+
let esmRequire;
|
|
84
|
+
/**
|
|
85
|
+
* Try import specified svelte configuration.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} configFile
|
|
88
|
+
* Absolute path of the svelte config file to require.
|
|
89
|
+
*
|
|
90
|
+
* @returns {import('@sveltejs/kit').Config}
|
|
91
|
+
* Returns the svelte configuration object.
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
return configFile => {
|
|
95
|
+
// identify which require function to use (esm and cjs mode)
|
|
96
|
+
const requireFn = import.meta.url ? esmRequire = esmRequire ?? createRequire(import.meta.url) : require; // avoid loading cached version on reload
|
|
97
|
+
|
|
98
|
+
delete requireFn.cache[requireFn.resolve(configFile)];
|
|
99
|
+
const result = requireFn(configFile);
|
|
100
|
+
|
|
101
|
+
if (result != null) {
|
|
102
|
+
return { ...result,
|
|
103
|
+
configFile
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
throw new Error(`invalid export in ${configFile}`);
|
|
108
|
+
};
|
|
109
|
+
})();
|
|
110
|
+
/**
|
|
111
|
+
* Try find svelte config. First in current working dir otherwise try to
|
|
112
|
+
* find it by climbing up the directory tree.
|
|
113
|
+
*
|
|
114
|
+
* @returns {Promise<string | undefined>}
|
|
115
|
+
* Returns the absolute path of the config file.
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
async function findSvelteConfig() {
|
|
120
|
+
const lookupDir = process.cwd();
|
|
121
|
+
let configFiles = await getConfigFiles(lookupDir);
|
|
122
|
+
|
|
123
|
+
if (configFiles.length === 0) {
|
|
124
|
+
configFiles = await getConfigFilesUp();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (configFiles.length === 0) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (configFiles.length > 1) {
|
|
132
|
+
logger.warn('Multiple svelte configuration files were found, which is unexpected. The first one will be used.', configFiles);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return configFiles[0];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Gets the file path of the svelte config by walking up the tree.
|
|
139
|
+
* Returning the first found. Should solves most of monorepos with
|
|
140
|
+
* only one config at workspace root.
|
|
141
|
+
*
|
|
142
|
+
* @returns {Promise<string[]>}
|
|
143
|
+
* Returns an array containing all available config files.
|
|
144
|
+
*/
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
async function getConfigFilesUp() {
|
|
148
|
+
const importPath = fileURLToPath(import.meta.url);
|
|
149
|
+
const pathChunks = path.dirname(importPath).split(path.sep);
|
|
150
|
+
|
|
151
|
+
while (pathChunks.length) {
|
|
152
|
+
pathChunks.pop();
|
|
153
|
+
const parentDir = pathChunks.join(path.posix.sep); // eslint-disable-next-line no-await-in-loop
|
|
154
|
+
|
|
155
|
+
const configFiles = await getConfigFiles(parentDir);
|
|
156
|
+
|
|
157
|
+
if (configFiles.length !== 0) {
|
|
158
|
+
return configFiles;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Gets all svelte config from a specified `lookupDir`.
|
|
166
|
+
*
|
|
167
|
+
* @param {string} lookupDir
|
|
168
|
+
* Directory in which to look for svelte files.
|
|
169
|
+
*
|
|
170
|
+
* @returns {Promise<string[]>}
|
|
171
|
+
* Returns an array containing all available config files.
|
|
172
|
+
*/
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
async function getConfigFiles(lookupDir) {
|
|
176
|
+
/** @type {[string, boolean][]} */
|
|
177
|
+
const fileChecks = await Promise.all(knownConfigFiles.map(async candidate => {
|
|
178
|
+
const filePath = path.resolve(lookupDir, candidate);
|
|
179
|
+
return [filePath, await pathExists(filePath)];
|
|
180
|
+
}));
|
|
181
|
+
return fileChecks.reduce((files, [file, exists]) => {
|
|
182
|
+
if (exists) files.push(file);
|
|
183
|
+
return files;
|
|
184
|
+
}, []);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const knownConfigFiles = ['js', 'cjs', 'mjs'].map(ext => `svelte.config.${ext}`);
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import { extractStories } from '../parser/extract-stories';
|
|
2
1
|
import fs from 'fs-extra';
|
|
2
|
+
import * as svelte from 'svelte/compiler';
|
|
3
|
+
import { extractStories } from '../parser/extract-stories';
|
|
4
|
+
import { loadSvelteConfig } from '../config-loader';
|
|
3
5
|
export async function svelteIndexer(fileName, {
|
|
4
6
|
makeTitle
|
|
5
7
|
}) {
|
|
6
8
|
let code = (await fs.readFile(fileName, 'utf-8')).toString();
|
|
9
|
+
const svelteOptions = await loadSvelteConfig();
|
|
10
|
+
|
|
11
|
+
if (svelteOptions && svelteOptions.preprocess) {
|
|
12
|
+
code = (await svelte.preprocess(code, svelteOptions.preprocess, {
|
|
13
|
+
filename: fileName
|
|
14
|
+
})).code;
|
|
15
|
+
}
|
|
16
|
+
|
|
7
17
|
const defs = extractStories(code);
|
|
8
18
|
return {
|
|
9
19
|
meta: {
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// This file is a rewrite of `@sveltejs/vite-plugin-svelte` without the `Vite`
|
|
2
|
+
// parts: https://github.com/sveltejs/vite-plugin-svelte/blob/e8e52deef93948da735c4ab69c54aced914926cf/packages/vite-plugin-svelte/src/utils/load-svelte-config.ts
|
|
3
|
+
import { logger } from '@storybook/client-logger';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import { pathExists } from "fs-extra";
|
|
8
|
+
import { pathToFileURL, fileURLToPath } from 'url';
|
|
9
|
+
/**
|
|
10
|
+
* Try find svelte config and then load it.
|
|
11
|
+
*
|
|
12
|
+
* @returns {import('@sveltejs/kit').Config | undefined}
|
|
13
|
+
* Returns the svelte configuration object.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export async function loadSvelteConfig() {
|
|
17
|
+
const configFile = await findSvelteConfig(); // no need to throw error since we handle projects without config files
|
|
18
|
+
|
|
19
|
+
if (configFile === undefined) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let err; // try to use dynamic import for svelte.config.js first
|
|
24
|
+
|
|
25
|
+
if (configFile.endsWith('.js') || configFile.endsWith('.mjs')) {
|
|
26
|
+
try {
|
|
27
|
+
return importSvelteOptions(configFile);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
logger.error(`failed to import config ${configFile}`, e);
|
|
30
|
+
err = e;
|
|
31
|
+
}
|
|
32
|
+
} // cjs or error with dynamic import
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if (configFile.endsWith('.js') || configFile.endsWith('.cjs')) {
|
|
36
|
+
try {
|
|
37
|
+
return requireSvelteOptions(configFile);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
logger.error(`failed to require config ${configFile}`, e);
|
|
40
|
+
|
|
41
|
+
if (!err) {
|
|
42
|
+
err = e;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
} // failed to load existing config file
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
throw new Error(`failed to load config ${configFile}`, {
|
|
49
|
+
cause: err
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const importSvelteOptions = (() => {
|
|
54
|
+
// hide dynamic import from ts transform to prevent it turning into a require
|
|
55
|
+
// see https://github.com/microsoft/TypeScript/issues/43329#issuecomment-811606238
|
|
56
|
+
// also use timestamp query to avoid caching on reload
|
|
57
|
+
const dynamicImportDefault = new Function('path', 'timestamp', 'return import(path + "?t=" + timestamp).then(m => m.default)');
|
|
58
|
+
/**
|
|
59
|
+
* Try import specified svelte configuration.
|
|
60
|
+
*
|
|
61
|
+
* @param {string} configFile
|
|
62
|
+
* Absolute path of the svelte config file to import.
|
|
63
|
+
*
|
|
64
|
+
* @returns {import('@sveltejs/kit').Config}
|
|
65
|
+
* Returns the svelte configuration object.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
return async configFile => {
|
|
69
|
+
const result = await dynamicImportDefault(pathToFileURL(configFile).href, fs.statSync(configFile).mtimeMs);
|
|
70
|
+
|
|
71
|
+
if (result != null) {
|
|
72
|
+
return { ...result,
|
|
73
|
+
configFile
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
throw new Error(`invalid export in ${configFile}`);
|
|
78
|
+
};
|
|
79
|
+
})();
|
|
80
|
+
|
|
81
|
+
const requireSvelteOptions = (() => {
|
|
82
|
+
/** @type {NodeRequire} */
|
|
83
|
+
let esmRequire;
|
|
84
|
+
/**
|
|
85
|
+
* Try import specified svelte configuration.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} configFile
|
|
88
|
+
* Absolute path of the svelte config file to require.
|
|
89
|
+
*
|
|
90
|
+
* @returns {import('@sveltejs/kit').Config}
|
|
91
|
+
* Returns the svelte configuration object.
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
return configFile => {
|
|
95
|
+
// identify which require function to use (esm and cjs mode)
|
|
96
|
+
const requireFn = import.meta.url ? esmRequire = esmRequire ?? createRequire(import.meta.url) : require; // avoid loading cached version on reload
|
|
97
|
+
|
|
98
|
+
delete requireFn.cache[requireFn.resolve(configFile)];
|
|
99
|
+
const result = requireFn(configFile);
|
|
100
|
+
|
|
101
|
+
if (result != null) {
|
|
102
|
+
return { ...result,
|
|
103
|
+
configFile
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
throw new Error(`invalid export in ${configFile}`);
|
|
108
|
+
};
|
|
109
|
+
})();
|
|
110
|
+
/**
|
|
111
|
+
* Try find svelte config. First in current working dir otherwise try to
|
|
112
|
+
* find it by climbing up the directory tree.
|
|
113
|
+
*
|
|
114
|
+
* @returns {Promise<string | undefined>}
|
|
115
|
+
* Returns the absolute path of the config file.
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
async function findSvelteConfig() {
|
|
120
|
+
const lookupDir = process.cwd();
|
|
121
|
+
let configFiles = await getConfigFiles(lookupDir);
|
|
122
|
+
|
|
123
|
+
if (configFiles.length === 0) {
|
|
124
|
+
configFiles = await getConfigFilesUp();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (configFiles.length === 0) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (configFiles.length > 1) {
|
|
132
|
+
logger.warn('Multiple svelte configuration files were found, which is unexpected. The first one will be used.', configFiles);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return configFiles[0];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Gets the file path of the svelte config by walking up the tree.
|
|
139
|
+
* Returning the first found. Should solves most of monorepos with
|
|
140
|
+
* only one config at workspace root.
|
|
141
|
+
*
|
|
142
|
+
* @returns {Promise<string[]>}
|
|
143
|
+
* Returns an array containing all available config files.
|
|
144
|
+
*/
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
async function getConfigFilesUp() {
|
|
148
|
+
const importPath = fileURLToPath(import.meta.url);
|
|
149
|
+
const pathChunks = path.dirname(importPath).split(path.sep);
|
|
150
|
+
|
|
151
|
+
while (pathChunks.length) {
|
|
152
|
+
pathChunks.pop();
|
|
153
|
+
const parentDir = pathChunks.join(path.posix.sep); // eslint-disable-next-line no-await-in-loop
|
|
154
|
+
|
|
155
|
+
const configFiles = await getConfigFiles(parentDir);
|
|
156
|
+
|
|
157
|
+
if (configFiles.length !== 0) {
|
|
158
|
+
return configFiles;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Gets all svelte config from a specified `lookupDir`.
|
|
166
|
+
*
|
|
167
|
+
* @param {string} lookupDir
|
|
168
|
+
* Directory in which to look for svelte files.
|
|
169
|
+
*
|
|
170
|
+
* @returns {Promise<string[]>}
|
|
171
|
+
* Returns an array containing all available config files.
|
|
172
|
+
*/
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
async function getConfigFiles(lookupDir) {
|
|
176
|
+
/** @type {[string, boolean][]} */
|
|
177
|
+
const fileChecks = await Promise.all(knownConfigFiles.map(async candidate => {
|
|
178
|
+
const filePath = path.resolve(lookupDir, candidate);
|
|
179
|
+
return [filePath, await pathExists(filePath)];
|
|
180
|
+
}));
|
|
181
|
+
return fileChecks.reduce((files, [file, exists]) => {
|
|
182
|
+
if (exists) files.push(file);
|
|
183
|
+
return files;
|
|
184
|
+
}, []);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const knownConfigFiles = ['js', 'cjs', 'mjs'].map(ext => `svelte.config.${ext}`);
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import { extractStories } from '../parser/extract-stories';
|
|
2
1
|
import fs from 'fs-extra';
|
|
2
|
+
import * as svelte from 'svelte/compiler';
|
|
3
|
+
import { extractStories } from '../parser/extract-stories';
|
|
4
|
+
import { loadSvelteConfig } from '../config-loader';
|
|
3
5
|
export async function svelteIndexer(fileName, {
|
|
4
6
|
makeTitle
|
|
5
7
|
}) {
|
|
6
8
|
let code = (await fs.readFile(fileName, 'utf-8')).toString();
|
|
9
|
+
const svelteOptions = await loadSvelteConfig();
|
|
10
|
+
|
|
11
|
+
if (svelteOptions && svelteOptions.preprocess) {
|
|
12
|
+
code = (await svelte.preprocess(code, svelteOptions.preprocess, {
|
|
13
|
+
filename: fileName
|
|
14
|
+
})).code;
|
|
15
|
+
}
|
|
16
|
+
|
|
7
17
|
const defs = extractStories(code);
|
|
8
18
|
return {
|
|
9
19
|
meta: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook/addon-svelte-csf",
|
|
3
|
-
"version": "3.0.0-next.
|
|
3
|
+
"version": "3.0.0-next.4",
|
|
4
4
|
"description": "Allows to write stories in Svelte syntax",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"storybook-addons",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@babel/runtime": "^7.17.5",
|
|
38
|
+
"fs-extra": "^11.1.1",
|
|
38
39
|
"magic-string": "^0.26.6",
|
|
39
40
|
"ts-dedent": "^2.0.0"
|
|
40
41
|
},
|