mirror of https://github.com/sveltejs/svelte
parent
fbd1d0a3b9
commit
ad9a672171
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: export ComponentType from `svelte` entrypoint
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: derived store types
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
Generate type declarations with dts-buddy
|
@ -1,5 +1,6 @@
|
||||
.idea
|
||||
.DS_Store
|
||||
.vscode
|
||||
.vscode/*
|
||||
!.vscode/launch.json
|
||||
node_modules
|
||||
.eslintcache
|
||||
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Playground: Browser",
|
||||
"url": "http://localhost:10001"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"runtimeArgs": ["--watch"],
|
||||
"name": "Playground: Server",
|
||||
"outputCapture": "std",
|
||||
"program": "start.js",
|
||||
"cwd": "${workspaceFolder}/packages/playground",
|
||||
"cascadeTerminateToConfigurations": ["Playground: Browser"]
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Playground: Full",
|
||||
"configurations": ["Playground: Server", "Playground: Browser"]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
@ -0,0 +1,7 @@
|
||||
You may use this package to experiment with your changes to Svelte.
|
||||
|
||||
To prevent any changes you make in this directory from being accidentally committed, run `git update-index --skip-worktree ./**/*.*` in this directory.
|
||||
|
||||
If you would actually like to make some changes to the files here for everyone then run `git update-index --no-skip-worktree ./**/*.*` before committing.
|
||||
|
||||
If you're using VS Code, you can use the "Playground: Full" launch configuration to run the playground and attach the debugger to both the compiler and the browser.
|
@ -0,0 +1,33 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "Node",
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
/**
|
||||
* svelte-preprocess cannot figure out whether you have
|
||||
* a value or a type, so tell TypeScript to enforce using
|
||||
* `import type` instead of `import` for Types.
|
||||
*/
|
||||
"verbatimModuleSyntax": true,
|
||||
"isolatedModules": true,
|
||||
"resolveJsonModule": true,
|
||||
/**
|
||||
* To have warnings / errors of the Svelte compiler at the
|
||||
* correct position, enable source maps by default.
|
||||
*/
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
/**
|
||||
* Typecheck JS in `.svelte` and `.js` files by default.
|
||||
* Disable this if you'd like to use dynamic types.
|
||||
*/
|
||||
"checkJs": true
|
||||
},
|
||||
/**
|
||||
* Use global.d.ts instead of compilerOptions.types
|
||||
* to avoid limiting type declarations.
|
||||
*/
|
||||
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "playground",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "node --watch start.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rollup": "^3.20.2",
|
||||
"rollup-plugin-serve": "^2.0.2",
|
||||
"svelte": "workspace:*"
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
<div>
|
||||
Hello world!
|
||||
</div>
|
@ -0,0 +1,24 @@
|
||||
import App from './App.svelte';
|
||||
|
||||
new App({
|
||||
target: document.getElementById('app'),
|
||||
hydrate: true
|
||||
});
|
||||
|
||||
function get_version() {
|
||||
return fetch('/version.json').then((r) => r.json());
|
||||
}
|
||||
|
||||
let prev = await get_version();
|
||||
|
||||
// Mom: We have live reloading at home
|
||||
// Live reloading at home:
|
||||
while (true) {
|
||||
await new Promise((r) => setTimeout(r, 2500));
|
||||
try {
|
||||
const version = await get_version();
|
||||
if (prev !== version) {
|
||||
window.location.reload();
|
||||
}
|
||||
} catch {}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import App from './App.svelte';
|
||||
|
||||
export function render() {
|
||||
// @ts-ignore
|
||||
return App.render();
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<script>
|
||||
let count = 0
|
||||
const increment = () => {
|
||||
count += 1
|
||||
}
|
||||
</script>
|
||||
|
||||
<button on:click={increment}>
|
||||
count is {count}
|
||||
</button>
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title><!--app-title--></title>
|
||||
<!--app-head-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/entry-client.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,100 @@
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { watch } from 'rollup';
|
||||
import serve from 'rollup-plugin-serve';
|
||||
import * as svelte from '../svelte/src/compiler/index.js';
|
||||
|
||||
const __dirname = new URL('.', import.meta.url).pathname;
|
||||
|
||||
/** @returns {import('rollup').Plugin}*/
|
||||
function create_plugin(ssr = false) {
|
||||
return {
|
||||
name: 'custom-svelte-ssr-' + ssr,
|
||||
resolveId(id) {
|
||||
if (id === 'svelte') {
|
||||
return path.resolve(
|
||||
__dirname,
|
||||
ssr ? '../svelte/src/runtime/ssr.js' : '../svelte/src/runtime/index.js'
|
||||
);
|
||||
} else if (id.startsWith('svelte/')) {
|
||||
return path.resolve(__dirname, `../svelte/src/runtime/${id.slice(7)}/index.js`);
|
||||
}
|
||||
},
|
||||
transform(code, id) {
|
||||
code = code.replaceAll('import.meta.env.SSR', ssr);
|
||||
|
||||
if (!id.endsWith('.svelte')) {
|
||||
return {
|
||||
code,
|
||||
map: null
|
||||
};
|
||||
}
|
||||
|
||||
const compiled = svelte.compile(code, {
|
||||
filename: id,
|
||||
generate: ssr ? 'ssr' : 'dom',
|
||||
hydratable: true,
|
||||
css: 'injected'
|
||||
});
|
||||
|
||||
return compiled.js;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const client_plugin = create_plugin();
|
||||
const ssr_plugin = create_plugin(true);
|
||||
|
||||
const watcher = watch([
|
||||
{
|
||||
input: 'src/entry-client.js',
|
||||
output: {
|
||||
dir: 'dist',
|
||||
format: 'esm',
|
||||
sourcemap: true
|
||||
},
|
||||
plugins: [client_plugin, serve('dist')]
|
||||
},
|
||||
{
|
||||
input: 'src/entry-server.js',
|
||||
output: {
|
||||
dir: 'dist-ssr',
|
||||
format: 'iife',
|
||||
indent: false
|
||||
},
|
||||
plugins: [
|
||||
ssr_plugin,
|
||||
{
|
||||
async generateBundle(_, bundle) {
|
||||
const result = bundle['entry-server.js'];
|
||||
const mod = (0, eval)(result.code);
|
||||
const { html } = mod.render();
|
||||
|
||||
writeFileSync(
|
||||
'dist/index.html',
|
||||
readFileSync('src/template.html', 'utf-8')
|
||||
.replace('<!--app-html-->', html)
|
||||
.replace('<!--app-title-->', svelte.VERSION)
|
||||
);
|
||||
writeFileSync('dist/version.json', Date.now().toString());
|
||||
}
|
||||
}
|
||||
],
|
||||
onwarn(warning, handler) {
|
||||
if (warning.code === 'MISSING_NAME_OPTION_FOR_IIFE_EXPORT') return;
|
||||
handler(warning);
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
watcher
|
||||
.on('change', (id) => {
|
||||
console.log(`changed ${id}`);
|
||||
})
|
||||
.on('event', (event) => {
|
||||
if (event.code === 'ERROR') {
|
||||
console.error(event.error);
|
||||
} else if (event.code === 'BUNDLE_END') {
|
||||
console.log(`Generated ${event.output} in ${event.duration}ms`);
|
||||
}
|
||||
});
|
@ -1,162 +0,0 @@
|
||||
// This script generates the TypeScript definitions
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
import { readFileSync, writeFileSync, readdirSync, existsSync, copyFileSync, statSync } from 'fs';
|
||||
|
||||
execSync('tsc -p src/compiler --emitDeclarationOnly && tsc -p src/runtime --emitDeclarationOnly', { stdio: 'inherit' });
|
||||
|
||||
function modify(path, modifyFn) {
|
||||
const content = readFileSync(path, 'utf8');
|
||||
writeFileSync(path, modifyFn(content));
|
||||
}
|
||||
|
||||
function adjust(input) {
|
||||
// Remove typedef jsdoc (duplicated in the type definition)
|
||||
input = input.replace(/\/\*\*\n(\r)? \* @typedef .+?\*\//gs, '');
|
||||
input = input.replace(/\/\*\* @typedef .+?\*\//gs, '');
|
||||
|
||||
// Extract the import paths and types
|
||||
const import_regex = /import\(("|')(.+?)("|')\)\.(\w+)/g;
|
||||
let import_match;
|
||||
const import_map = new Map();
|
||||
|
||||
while ((import_match = import_regex.exec(input)) !== null) {
|
||||
const imports = import_map.get(import_match[2]) || new Map();
|
||||
let name = import_match[4];
|
||||
if ([...imports.keys()].includes(name)) continue;
|
||||
|
||||
let i = 1;
|
||||
if (name === 'default') {
|
||||
name = import_match[2].split('/').pop().split('.').shift().replace(/[^a-z0-9]/gi, '_');
|
||||
}
|
||||
while ([...import_map].some(([path, names]) => path !== import_match[2] && names.has(name))) {
|
||||
name = `${name}${i++}`;
|
||||
}
|
||||
|
||||
imports.set(import_match[4], name);
|
||||
import_map.set(import_match[2], imports);
|
||||
}
|
||||
|
||||
// Replace inline imports with their type names
|
||||
const transformed = input.replace(import_regex, (_match, _quote, path, _quote2, name) => {
|
||||
return import_map.get(path).get(name);
|
||||
});
|
||||
|
||||
// Remove/adjust @template, @param and @returns lines
|
||||
// TODO rethink if we really need to do this for @param and @returns, doesn't show up in hover so unnecessary
|
||||
const lines = transformed.split("\n");
|
||||
|
||||
let filtered_lines = [];
|
||||
let removing = null;
|
||||
let openCount = 1;
|
||||
let closedCount = 0;
|
||||
|
||||
for (let line of lines) {
|
||||
let start_removing = false;
|
||||
if (line.trim().startsWith("* @template")) {
|
||||
removing = "template";
|
||||
start_removing = true;
|
||||
}
|
||||
|
||||
if (line.trim().startsWith("* @param {")) {
|
||||
openCount = 1;
|
||||
closedCount = 0;
|
||||
removing = "param";
|
||||
start_removing = true;
|
||||
}
|
||||
|
||||
if (line.trim().startsWith("* @returns {")) {
|
||||
openCount = 1;
|
||||
closedCount = 0;
|
||||
removing = "returns";
|
||||
start_removing = true;
|
||||
}
|
||||
|
||||
if (removing === "returns" || removing === "param") {
|
||||
let i = start_removing ? line.indexOf('{') + 1 : 0;
|
||||
for (; i < line.length; i++) {
|
||||
if (line[i] === "{") openCount++;
|
||||
if (line[i] === "}") closedCount++;
|
||||
if (openCount === closedCount) break;
|
||||
}
|
||||
if (openCount === closedCount) {
|
||||
line = start_removing ? (line.slice(0, line.indexOf('{')) + line.slice(i + 1)) : (` * @${removing} ` + line.slice(i + 1));
|
||||
removing = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (removing && !start_removing && (line.trim().startsWith("* @") || line.trim().startsWith("*/"))) {
|
||||
removing = null;
|
||||
}
|
||||
|
||||
if (!removing) {
|
||||
filtered_lines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Replace generic type names with their plain versions
|
||||
const renamed_generics = filtered_lines.map(line => {
|
||||
return line.replace(/(\W|\s)([A-Z][\w\d$]*)_\d+(\W|\s)/g, "$1$2$3");
|
||||
});
|
||||
|
||||
// Generate the import statement for the types used
|
||||
const import_statements = Array.from(import_map.entries())
|
||||
.map(([path, names]) => {
|
||||
const default_name = names.get('default');
|
||||
names.delete('default');
|
||||
const default_import = default_name ? (default_name + (names.size ? ', ' : ' ')) : '';
|
||||
const named_imports = names.size ? `{ ${[...names.values()].join(', ')} } ` : '';
|
||||
return `import ${default_import}${named_imports}from '${path}';`
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
return [import_statements, ...renamed_generics].join("\n");
|
||||
}
|
||||
|
||||
let did_replace = false;
|
||||
|
||||
function walk(dir) {
|
||||
const files = readdirSync(dir);
|
||||
const _dir = dir.slice('types/'.length)
|
||||
|
||||
for (const file of files) {
|
||||
const path = `${dir}/${file}`;
|
||||
if (file.endsWith('.d.ts')) {
|
||||
modify(path, content => {
|
||||
content = adjust(content);
|
||||
|
||||
if (file === 'index.d.ts' && existsSync(`src/${_dir}/public.d.ts`)) {
|
||||
copyFileSync(`src/${_dir}/public.d.ts`, `${dir}/public.d.ts`);
|
||||
content = "export * from './public.js';\n" + content;
|
||||
}
|
||||
|
||||
if (file === 'Component.d.ts' && dir.includes('runtime')) {
|
||||
if (!content.includes('$set(props: Partial<Props>): void;\n}')) {
|
||||
throw new Error('Component.js was modified in a way that automatic patching of d.ts file no longer works. Please adjust it');
|
||||
} else {
|
||||
content = content.replace('$set(props: Partial<Props>): void;\n}', '$set(props: Partial<Props>): void;\n [accessor:string]: any;\n}');
|
||||
did_replace = true;
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
});
|
||||
} else if (statSync(path).isDirectory()) {
|
||||
if (existsSync(`src/${_dir}/${file}/private.d.ts`)) {
|
||||
copyFileSync(`src/${_dir}/${file}/private.d.ts`, `${path}/private.d.ts`);
|
||||
}
|
||||
if (existsSync(`src/${_dir}/${file}/interfaces.d.ts`)) {
|
||||
copyFileSync(`src/${_dir}/${file}/interfaces.d.ts`, `${path}/interfaces.d.ts`);
|
||||
}
|
||||
walk(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk('types');
|
||||
|
||||
if (!did_replace) {
|
||||
throw new Error('Component.js file in runtime does no longer exist so that automatic patching of the d.ts file no longer works. Please adjust it');
|
||||
}
|
||||
|
||||
copyFileSync(`src/runtime/ambient.d.ts`, `types/runtime/ambient.d.ts`);
|
@ -0,0 +1,16 @@
|
||||
import { createBundle } from 'dts-buddy';
|
||||
|
||||
await createBundle({
|
||||
output: 'types/index.d.ts',
|
||||
modules: {
|
||||
svelte: 'src/runtime/public.d.ts',
|
||||
'svelte/compiler': 'src/compiler/public.d.ts',
|
||||
'svelte/types/compiler/preprocess': 'src/compiler/preprocess/public.d.ts',
|
||||
'svelte/action': 'src/runtime/action/public.d.ts',
|
||||
'svelte/animate': 'src/runtime/animate/public.d.ts',
|
||||
'svelte/easing': 'src/runtime/easing/index.js',
|
||||
'svelte/motion': 'src/runtime/motion/public.d.ts',
|
||||
'svelte/store': 'src/runtime/store/public.d.ts',
|
||||
'svelte/transition': 'src/runtime/transition/public.d.ts'
|
||||
}
|
||||
});
|
@ -1,2 +1,3 @@
|
||||
export { CompileOptions, EnableSourcemap, CssHashGetter } from './interfaces';
|
||||
export * from './preprocess/public.js';
|
||||
export * from './index.js';
|
||||
|
@ -1 +0,0 @@
|
||||
export {};
|
@ -1,4 +1,4 @@
|
||||
// generated during release, do not modify
|
||||
|
||||
/** @type {string} */
|
||||
export const VERSION = '4.0.0-next.0';
|
||||
export const VERSION = '4.0.0-next.1';
|
||||
|
Loading…
Reference in new issue