diff --git a/.gitignore b/.gitignore index 5d57fa4..8ea62f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store node_modules /dist/ -.vscode/ \ No newline at end of file +.vscode/ +storybook-static/ \ No newline at end of file diff --git a/.storybook/main.js b/.storybook/main.js index f27ed8c..ef8f9c8 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,14 +1,14 @@ module.exports = { - "stories": [ - "../src/**/*.stories.mdx", - "../src/**/*.stories.@(js|jsx|ts|tsx|svelte)" + stories: [ + "../stories/**/*.stories.mdx", + "../stories/**/*.stories.@(js|jsx|ts|tsx|svelte)", ], - "addons": [ + addons: [ "@storybook/addon-links", "@storybook/addon-essentials", - "@storybook/addon-svelte-csf" + "@storybook/addon-svelte-csf", ], - "svelteOptions": { - "preprocess": require("svelte-preprocess")() - } -} \ No newline at end of file + svelteOptions: { + preprocess: require("svelte-preprocess")(), + }, +}; diff --git a/package-lock.json b/package-lock.json index b958615..48c076a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1868,9 +1868,9 @@ } }, "@storybook/addon-svelte-csf": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@storybook/addon-svelte-csf/-/addon-svelte-csf-1.0.0.tgz", - "integrity": "sha512-y6isfsG0AYLdKVDcOw9kxj77QY5W9tjTXYQ/mObdULOuzpmGLzSmmKTVLcmmPwBLnGLTZEBRMZ0RcxLwZ0G57Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-svelte-csf/-/addon-svelte-csf-1.1.0.tgz", + "integrity": "sha512-AjP9kxVbbAyucB8vy889WERafjNM020vWel+psCuDJ2vLU+uObqbCLSGKRIznXjeL0BYR73l9ZF+niJfw6QSlg==", "dev": true, "requires": { "ts-dedent": "^2.0.0" @@ -2118,6 +2118,28 @@ } } }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2455,6 +2477,18 @@ "yaml": "^1.7.2" } }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -2466,6 +2500,16 @@ } } }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2647,6 +2691,28 @@ } } }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -7179,12 +7245,11 @@ } }, "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "dev": true, "requires": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" @@ -11356,6 +11421,12 @@ "fsevents": "~2.3.1" } }, + "rollup-plugin-execute": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-execute/-/rollup-plugin-execute-1.1.1.tgz", + "integrity": "sha512-isCNR/VrwlEfWJMwsnmt5TBRod8dW1IjVRxcXCBrxDmVTeA1IXjzeLSS3inFBmRD7KDPlo38KSb2mh5v5BoWgA==", + "dev": true + }, "rollup-plugin-svelte": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-6.1.1.tgz", diff --git a/package.json b/package.json index f782687..851eb1b 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,19 @@ { "name": "svelte-easy-popover", "version": "0.1.0", + "svelte": "dist/index.js", "module": "dist/index.mjs", - "main": "dist/index.js", + "main": "dist/index.umd.js", + "types": "dist/ts/index.d.ts", "author": "Justin Guze", "repository": { "type": "git", "url": "git+https://github.com/jguze/svelte-easy-popover.git" }, "scripts": { + "prebuild": "rm -rf ./dist", + "dev": "rollup -c -w", + "validate": "svelte-check", "build": "rollup -c", "prepublishOnly": "npm run build", "storybook": "start-storybook -p 6006", @@ -23,12 +28,15 @@ "@storybook/addon-actions": "^6.2.9", "@storybook/addon-essentials": "^6.2.9", "@storybook/addon-links": "^6.2.9", - "@storybook/addon-svelte-csf": "^1.0.0", + "@storybook/addon-svelte-csf": "^1.1.0", "@storybook/storybook-deployer": "^2.8.8", "@storybook/svelte": "^6.2.9", "@tsconfig/svelte": "^2.0.1", "babel-loader": "^8.2.2", + "fs-extra": "^10.0.0", + "glob": "^7.1.7", "rollup": "^2.0.0", + "rollup-plugin-execute": "^1.1.1", "rollup-plugin-svelte": "^6.0.0", "rollup-plugin-terser": "^7.0.2", "svelte": "^3.38.2", diff --git a/rollup.config.js b/rollup.config.js index b1a1094..abcb348 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,34 +1,42 @@ -import svelte from 'rollup-plugin-svelte'; -import resolve from '@rollup/plugin-node-resolve'; -import pkg from './package.json'; -import autoPreprocess from 'svelte-preprocess'; -import typescript from '@rollup/plugin-typescript'; -import replace from '@rollup/plugin-replace'; +import svelte from "rollup-plugin-svelte"; +import resolve from "@rollup/plugin-node-resolve"; +import pkg from "./package.json"; +import autoPreprocess from "svelte-preprocess"; +import execute from "rollup-plugin-execute"; +import typescript from "@rollup/plugin-typescript"; import { terser } from "rollup-plugin-terser"; const production = !process.env.ROLLUP_WATCH; const name = pkg.name - .replace(/^(@\S+\/)?(svelte-)?(\S+)/, '$3') - .replace(/^\w/, m => m.toUpperCase()) - .replace(/-\w/g, m => m[1].toUpperCase()); + .replace(/^(@\S+\/)?(svelte-)?(\S+)/, "$3") + .replace(/^\w/, (m) => m.toUpperCase()) + .replace(/-\w/g, (m) => m[1].toUpperCase()); export default { - input: 'src/index.ts', - output: [ - { file: pkg.module, 'format': 'es' }, - { file: pkg.main, 'format': 'umd', name } - ], - plugins: [ - svelte({ - preprocess: autoPreprocess(), - }), - typescript({ sourceMap: !production }), - resolve(), - replace({ - 'process.env.NODE_ENV': production ? '"production"' : '"development"', - preventAssignment: true, - }), - production && terser() - ] + input: "src/index.ts", + output: [ + { file: pkg.module, format: "es" }, + { + file: pkg.main, + format: "umd", + name, + sourcemap: !production, + plugins: [ + // we only want to run this once, so we'll just make it part of this output's plugins + execute([ + "tsc --outDir ./dist --declaration", + "node scripts/preprocess.js", + ]), + ], + }, + ], + plugins: [ + svelte({ + preprocess: autoPreprocess(), + }), + typescript({ sourceMap: !production }), + resolve(), + production && terser(), + ], }; diff --git a/scripts/preprocess.js b/scripts/preprocess.js new file mode 100644 index 0000000..6a81cde --- /dev/null +++ b/scripts/preprocess.js @@ -0,0 +1,85 @@ +const fs = require("fs-extra"); +const glob = require("glob"); +const path = require("path"); +const svelte = require("svelte/compiler"); +const sveltePreprocess = require("svelte-preprocess"); + +const basePath = path.resolve(__dirname, "../"); +const srcPath = path.resolve(basePath, "src"); +const distPath = path.resolve(basePath, "dist"); + +/** + * This will process .svelte files into plain javascript so consumers do not have to setup Typescript to use this library + * + * Additionally, it will move the .d.ts files into /dist/ts + */ +async function main() { + // get all .svelte files + glob(path.join(srcPath, "**/*.svelte"), null, async function (err, files) { + if (err) throw err; + // process them + await Promise.all( + files.map((filePath) => preprocessSvelte(path.resolve(filePath))) + ); + }); + + // move .d.ts files into /dist/ts + glob(path.join(distPath, "**/*.d.ts"), null, async function (err, files) { + if (err) throw err; + const tsPath = path.join(distPath, "ts"); + + await Promise.all( + files.map(async (filePath) => { + filePath = path.resolve(filePath); + // ignore anything in /dist/ts (could probably make a better glob pattern) + if (!filePath.includes(tsPath)) { + await fs.move(filePath, filePath.replace(distPath, tsPath), { + overwrite: true, + }); + } + }) + ); + }); +} + +/** + * Processes .svelte file and write it to /dist, also copies the original .svelte file to /dist/ts + */ +async function preprocessSvelte(filePath) { + const srcCode = await fs.readFile(filePath, { encoding: "utf-8" }); + let { code } = await svelte.preprocess( + srcCode, + sveltePreprocess({ + // unfortunately, sourcemap on .svelte files sometimes comments out the tag + // so we need to disable sourcemapping for them + sourceMap: false, + typescript: { + compilerOptions: { + sourceMap: false, + }, + }, + }), + { + filename: filePath, + } + ); + + // remove lang=ts from processed .svelte files + code = code.replace(/script lang="ts"/g, "script"); + + const relativePath = filePath.split(srcPath)[1]; + const destination = path.join(distPath, filePath.split(srcPath)[1]); + + // write preprocessed svelte file to /dist + await fs.ensureFile(destination); + await fs.writeFile(destination, code, { encoding: "utf-8" }); + + // write the unprocessed svelte component to /dist/ts/ so we can have correct types for ts users + const tsDest = path.join(distPath, "ts", relativePath); + await fs.ensureFile(tsDest); + await fs.writeFile(tsDest, srcCode, { + encoding: "utf-8", + }); +} + +main(); diff --git a/src/Popover.svelte b/src/Popover.svelte index b27da71..a7fdad5 100644 --- a/src/Popover.svelte +++ b/src/Popover.svelte @@ -25,7 +25,9 @@