diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..b0fc978 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +dist/* +public/* +test/*.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..6d62dc3 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,46 @@ +{ + "parser": "@typescript-eslint/parser", + "ignorePatterns": ["lib.es5.d.ts"], + "parserOptions": { + "requireConfigFile": false + }, + "extends": [ + "standard", + "plugin:@typescript-eslint/recommended" + ], + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + "caughtErrorsIgnorePattern": "^_" + } + ], + "operator-linebreak": ["off"], + "multiline-ternary": "off", + "@typescript-eslint/consistent-type-imports": [ + "error", + { + "prefer": "type-imports" + } + ], + "no-multiple-empty-lines": [ + "error", + { + "max": 1, + "maxEOF": 1 + } + ], + "indent": ["error", 4, { + "SwitchCase": 1, + "ignoredNodes": ["TemplateLiteral *"] + }], + "comma-dangle": "off", + "no-multi-spaces": ["error", { "ignoreEOLComments": true }] + } +} diff --git a/.gitignore b/.gitignore index a1ed9c0..b0bb26f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,8 @@ -example/drag-drop.js +node_modules +bundle.js +.DS_Store +.env +*.js +dist +public + diff --git a/.npmignore b/.npmignore index 957b209..f4cd498 100644 --- a/.npmignore +++ b/.npmignore @@ -1,3 +1,4 @@ .github/ example/ test/ +.env diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..43c97e7 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/README.md b/README.md index e646d22..20e7f19 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,33 @@ [standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg [standard-url]: https://standardjs.com -### HTML5 drag & drop for humans +

Contents

+ + + +- [fork](#fork) + * [HTML5 drag & drop for humans](#html5-drag--drop-for-humans) + * [live demo](#live-demo) + * [features](#features) + * [install](#install) + * [usage](#usage) + * [complete example](#complete-example) + * [get files as buffers](#get-files-as-buffers) + * [detect drag-and-dropped text](#detect-drag-and-dropped-text) + * [detect `dragenter`, `dragover` and `dragleave` events](#detect-dragenter-dragover-and-dragleave-events) + * [remove listeners](#remove-listeners) + * [support pasting files from the clipboard](#support-pasting-files-from-the-clipboard) + * [a note about `file://` urls](#a-note-about-file-urls) + * [license](#license) + + + +
+ +## fork +This is a fork of [feross/drag-drop](https://github.com/feross/drag-drop). + +## HTML5 drag & drop for humans In case you didn't know, the [HTML5 drag and drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API) @@ -17,11 +43,17 @@ is a [total disaster](http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html)! This is an attempt to make the API usable by mere mortals. -### live demo +## install + +```sh +npm i -S drag-drop +``` + +## live demo See [https://instant.io](https://instant.io). -### features +## features - simple API - supports files and directories @@ -29,11 +61,7 @@ See [https://instant.io](https://instant.io). - adds a `drag` class to the drop target on hover, for easy styling! - optionally, get the file(s) as a Buffer (see [buffer](https://github.com/feross/buffer)) -### install - -``` -npm install drag-drop -``` +This package works in the browser via [native ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) + the [exports field](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#exports) in `package.json`. This package works in the browser with [browserify](https://browserify.org). If you do not use a bundler, you can use the [standalone script](https://bundle.run/drag-drop) directly in a ` - diff --git a/index.js b/index.js deleted file mode 100644 index b461f63..0000000 --- a/index.js +++ /dev/null @@ -1,270 +0,0 @@ -/*! drag-drop. MIT License. Feross Aboukhadijeh */ -module.exports = dragDrop -module.exports.processItems = processItems - -const parallel = require('run-parallel') - -function dragDrop (elem, listeners) { - if (typeof elem === 'string') { - const selector = elem - elem = window.document.querySelector(elem) - if (!elem) { - throw new Error(`"${selector}" does not match any HTML elements`) - } - } - - if (!elem) { - throw new Error(`"${elem}" is not a valid HTML element`) - } - - if (typeof listeners === 'function') { - listeners = { onDrop: listeners } - } - - elem.addEventListener('dragenter', onDragEnter, false) - elem.addEventListener('dragover', onDragOver, false) - elem.addEventListener('dragleave', onDragLeave, false) - elem.addEventListener('drop', onDrop, false) - - let isEntered = false - let numIgnoredEnters = 0 - - // Function to remove drag-drop listeners - return function cleanup () { - removeDragClass() - elem.removeEventListener('dragenter', onDragEnter, false) - elem.removeEventListener('dragover', onDragOver, false) - elem.removeEventListener('dragleave', onDragLeave, false) - elem.removeEventListener('drop', onDrop, false) - } - - function isEventHandleable (event) { - if (event.dataTransfer.items || event.dataTransfer.types) { - // Only add "drag" class when `items` contains items that are able to be - // handled by the registered listeners (files vs. text) - const items = Array.from(event.dataTransfer.items) - const types = Array.from(event.dataTransfer.types) - - let fileItems - let textItems - if (items.length) { - fileItems = items.filter(item => { return item.kind === 'file' }) - textItems = items.filter(item => { return item.kind === 'string' }) - } else if (types.length) { - // event.dataTransfer.items is empty during 'dragover' in Safari, so use - // event.dataTransfer.types as a fallback - fileItems = types.filter(item => item === 'Files') - textItems = types.filter(item => item.startsWith('text/')) - } else { - return false - } - - if (fileItems.length === 0 && !listeners.onDropText) return false - if (textItems.length === 0 && !listeners.onDrop) return false - if (fileItems.length === 0 && textItems.length === 0) return false - - return true - } - return false - } - - function onDragEnter (event) { - event.stopPropagation() - event.preventDefault() - - if (!isEventHandleable(event)) return - - if (isEntered) { - numIgnoredEnters += 1 - return false // early return - } - - isEntered = true - - if (listeners.onDragEnter) { - listeners.onDragEnter(event) - } - - addDragClass() - - return false - } - - function onDragOver (event) { - event.stopPropagation() - event.preventDefault() - - if (!isEventHandleable(event)) return - - if (listeners.onDragOver) { - listeners.onDragOver(event) - } - - event.dataTransfer.dropEffect = 'copy' - - return false - } - - function onDragLeave (event) { - event.stopPropagation() - event.preventDefault() - - if (!isEventHandleable(event)) return - - if (numIgnoredEnters > 0) { - numIgnoredEnters -= 1 - return false - } - - isEntered = false - - if (listeners.onDragLeave) { - listeners.onDragLeave(event) - } - - removeDragClass() - - return false - } - - function onDrop (event) { - event.stopPropagation() - event.preventDefault() - - if (listeners.onDragLeave) { - listeners.onDragLeave(event) - } - - removeDragClass() - - isEntered = false - numIgnoredEnters = 0 - - const pos = { - x: event.clientX, - y: event.clientY - } - - // text drop support - const text = event.dataTransfer.getData('text') - if (text && listeners.onDropText) { - listeners.onDropText(text, pos) - } - - // File drop support. The `dataTransfer.items` API supports directories, so we - // use it instead of `dataTransfer.files`, even though it's much more - // complicated to use. - // See: https://github.com/feross/drag-drop/issues/39 - if (listeners.onDrop && event.dataTransfer.items) { - processItems(event.dataTransfer.items, (err, files, directories) => { - if (err) { - // TODO: A future version of this library might expose this somehow - console.error(err) - return - } - - if (files.length === 0) return - - const fileList = event.dataTransfer.files - - // TODO: This callback has too many arguments, and the order is too - // arbitrary. In next major version, it should be cleaned up. - listeners.onDrop(files, pos, fileList, directories) - }) - } - - return false - } - - function addDragClass () { - elem.classList.add('drag') - } - - function removeDragClass () { - elem.classList.remove('drag') - } -} - -function processItems (items, cb) { - // Handle directories in Chrome using the proprietary FileSystem API - items = Array.from(items).filter(item => { - return item.kind === 'file' - }) - - if (items.length === 0) { - cb(null, [], []) - } - - parallel(items.map(item => { - return cb => { - processEntry(item.webkitGetAsEntry(), cb) - } - }), (err, results) => { - // This catches permission errors with file:// in Chrome - if (err) { - cb(err) - return - } - - const entries = results.flat(Infinity) - - const files = entries.filter(item => { - return item.isFile - }) - - const directories = entries.filter(item => { - return item.isDirectory - }) - - cb(null, files, directories) - }) -} - -function processEntry (entry, cb) { - let entries = [] - - if (entry.isFile) { - entry.file(file => { - file.fullPath = entry.fullPath // preserve path for consumer - file.isFile = true - file.isDirectory = false - cb(null, file) - }, err => { - cb(err) - }) - } else if (entry.isDirectory) { - const reader = entry.createReader() - readEntries(reader) - } - - function readEntries (reader) { - reader.readEntries(currentEntries => { - if (currentEntries.length > 0) { - entries = entries.concat(Array.from(currentEntries)) - readEntries(reader) // continue reading entries until `readEntries` returns no more - } else { - doneEntries() - } - }) - } - - function doneEntries () { - parallel(entries.map(entry => { - return cb => { - processEntry(entry, cb) - } - }), (err, results) => { - if (err) { - cb(err) - } else { - results.push({ - fullPath: entry.fullPath, - name: entry.name, - isFile: false, - isDirectory: true - }) - cb(null, results) - } - }) - } -} diff --git a/lib.es5.d.ts b/lib.es5.d.ts new file mode 100644 index 0000000..a2b2ce5 --- /dev/null +++ b/lib.es5.d.ts @@ -0,0 +1,19 @@ +/** See https://stackoverflow.com/a/51390763/1470607 */ +type Falsy = false | 0 | '' | null | undefined; + +/** + * see https://www.karltarvas.com/typescript-array-filter-boolean.html + */ +interface Array { + /** + * Returns the elements of an array that meet the condition specified in a + * callback function. + * @param predicate A function that accepts up to three arguments. The filter + * method calls the predicate function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the + * predicate function. If thisArg is omitted, undefined is used as the + * this value. + */ + filter(predicate: BooleanConstructor, thisArg?: any) + : Exclude[]; +} diff --git a/package.json b/package.json index 7be5348..3ecddc0 100644 --- a/package.json +++ b/package.json @@ -2,26 +2,64 @@ "name": "drag-drop", "description": "HTML5 drag & drop for humans", "version": "7.2.0", - "author": { - "name": "Feross Aboukhadijeh", - "email": "feross@feross.org", - "url": "https://feross.org" + "type": "module", + "files": [ + "./dist/*" + ], + "exports": { + ".": { + "import": [ + "./dist/index.js" + ], + "require": [ + "./dist/index.cjs" + ] + }, + "./buffer": { + "import": [ + "./dist/buffer.js" + ], + "require": [ + "./dist/buffer.cjs" + ] + } }, - "bugs": { - "url": "https://github.com/feross/drag-drop/issues" + "scripts": { + "start": "vite", + "lint": "eslint \"./**/*.{ts,js}\"", + "toc": "markdown-toc --maxdepth 3 -i README.md", + "build": "mkdir -p ./dist && rm -rf ./dist/* && npm run build-cjs && npm run build-esm && npm run build-esm:min && npm run build-cjs:min", + "build-cjs": "esbuild src/*.ts --format=cjs --keep-names --tsconfig=tsconfig.build.json --outdir=./dist --out-extension:.js=.cjs --sourcemap", + "build-cjs:min": "esbuild src/*.ts --format=cjs --minify --keep-names --tsconfig=tsconfig.build.json --outdir=./dist --out-extension:.js=.min.cjs --sourcemap", + "build-esm": "esbuild src/*.ts --format=esm --metafile=dist/meta.json --keep-names --tsconfig=tsconfig.build.json --outdir=./dist --sourcemap && tsc --emitDeclarationOnly --project tsconfig.build.json --outDir dist", + "build-esm:min": "esbuild ./src/*.ts --format=esm --keep-names --bundle --tsconfig=tsconfig.build.json --minify --out-extension:.js=.min.js --outdir=./dist --sourcemap", + "build-example": "mkdir -p ./public && rm -rf ./public/* && VITE_DEBUG_MODE=staging vite --mode staging --base=\"/drag-drop\" build", + "build-tests": "esbuild test/index.ts --target=es2020 --bundle --keep-names > test/test-bundle.js", + "test": "npm run build && npm run build-tests && cat test/index.html | tape-run --input=html --static=test | tap-spec", + "preversion": "npm run lint", + "version": "npm run toc && auto-changelog -p --template keepachangelog --breaking-pattern 'BREAKING CHANGE:' && git add CHANGELOG.md README.md", + "postversion": "git push --follow-tags && npm publish", + "prepublishOnly": "npm run build" }, "dependencies": { "blob-to-buffer": "^1.2.9", "run-parallel": "^1.2.0" }, "devDependencies": { - "babel-minify": "^0.5.1", - "browserify": "^17.0.0", - "ecstatic": "^4.1.4", - "standard": "*", - "tape": "^5.2.2" + "@bicycle-codes/debug": "^0.6.16", + "@bicycle-codes/tapzero": "^0.10.5", + "@typescript-eslint/eslint-plugin": "^8.12.2", + "esbuild": "^0.24.0", + "eslint": "^8.57.1", + "eslint-config-standard": "^17.1.0", + "markdown-toc": "^1.2.0", + "postcss-nesting": "^13.0.1", + "tap-spec": "^5.0.0", + "tape-run": "^11.0.0", + "typescript": "^5.6.3", + "vite": "^5.4.10" }, - "homepage": "https://github.com/feross/drag-drop", + "homepage": "https://github.com/bicycle-codes/drag-drop", "keywords": [ "drag", "drop", @@ -30,8 +68,7 @@ "drag drop", "html5", "drag & drop", - "frontend", - "browserify" + "frontend" ], "license": "MIT", "main": "index.js", @@ -39,10 +76,16 @@ "type": "git", "url": "git://github.com/feross/drag-drop.git" }, - "scripts": { - "example": "browserify -s DragDrop -r . > example/drag-drop.js && ecstatic example --port 4000", - "size": "browserify -s DragDrop -r . | minify | gzip | wc -c", - "test": "standard && tape test/*.js" + "author": { + "name": "Feross Aboukhadijeh", + "email": "feross@feross.org", + "url": "https://feross.org" + }, + "contributors": [ + "Nick Thomas (https://nichoth./com)" + ], + "bugs": { + "url": "https://github.com/bicycle-codes/drag-drop/issues" }, "funding": [ { diff --git a/src/buffer.ts b/src/buffer.ts new file mode 100644 index 0000000..288d1ff --- /dev/null +++ b/src/buffer.ts @@ -0,0 +1,26 @@ +import { dragDrop } from './index.js' +import parallel from 'run-parallel' +import blobToBuffer from 'blob-to-buffer' + +export function dragDropAsBuffer (elem:Element, cb) { + return dragDrop(elem, function (files, pos, fileList) { + const tasks = files.map(function (file) { + return function (cb) { + blobToBuffer(file, function (err, buffer) { + if (err) return cb(err) + buffer.name = file.name + buffer.fullPath = file.fullPath + buffer.size = file.size + buffer.type = file.type + buffer.lastModifiedDate = file.lastModifiedDate + cb(null, buffer) + }) + } + }) + + parallel(tasks, function (err, results) { + if (err) throw err + cb(results, pos, fileList) + }) + }) +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..dd58953 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,294 @@ +/*! drag-drop. MIT License. Feross Aboukhadijeh */ +import parallel from 'run-parallel' +export default dragDrop + +// type Listener = ((ev:DragEvent)=>any) +type Listener = ((files, pos?, fileList?, directories?)=>any) + +type ListenerObject = { + onDrop:(files:FileList, pos, fileList, directories)=>any; + onDropText?:(text, pos)=>any; + onDragEnter?:(event)=>any; + onDragOver?:(event)=>any; + onDragLeave?:(event)=>any; +} + +export function dragDrop (_elem:Element|string, _listeners:Listener|ListenerObject) { + let elem:Element|null + if (typeof _elem === 'string') { + const selector = _elem + elem = document.querySelector(_elem) + if (!elem) { + throw new Error(`"${selector}" does not match any HTML elements`) + } + } else { + elem = _elem + } + + if (!elem) { + throw new Error(`"${elem}" is not a valid HTML element`) + } + + let listeners:ListenerObject + if (typeof _listeners === 'function') { + listeners = { onDrop: _listeners } + } else { + listeners = _listeners + } + + elem.addEventListener('dragenter', onDragEnter, false) + elem.addEventListener('dragover', onDragOver, false) + elem.addEventListener('dragleave', onDragLeave, false) + elem.addEventListener('drop', onDrop, false) + + let isEntered = false + let numIgnoredEnters = 0 + + // Function to remove drag-drop listeners + return function cleanup () { + removeDragClass() + elem.removeEventListener('dragenter', onDragEnter, false) + elem.removeEventListener('dragover', onDragOver, false) + elem.removeEventListener('dragleave', onDragLeave, false) + elem.removeEventListener('drop', onDrop, false) + } + + function isEventHandleable (event:DragEvent):boolean { + if (!event.dataTransfer) return false + + if (event.dataTransfer.items || event.dataTransfer.types) { + // Only add "drag" class when `items` contains items that are able to be + // handled by the registered listeners (files vs. text) + const items = Array.from(event.dataTransfer.items) + const types = Array.from(event.dataTransfer.types) + + let fileItems + let textItems + if (items.length) { + fileItems = items.filter(item => { return item.kind === 'file' }) + textItems = items.filter(item => { return item.kind === 'string' }) + } else if (types.length) { + // event.dataTransfer.items is empty during 'dragover' in Safari, + // so use event.dataTransfer.types as a fallback + fileItems = types.filter(item => item === 'Files') + textItems = types.filter(item => item.startsWith('text/')) + } else { + return false + } + + if (!('onDropText' in listeners)) { + return false + } + + if (fileItems.length === 0 && !listeners.onDropText) return false + if (textItems.length === 0 && !listeners.onDrop) return false + if (fileItems.length === 0 && textItems.length === 0) return false + + return true + } + return false + } + + function onDragEnter (event) { + event.stopPropagation() + event.preventDefault() + + if (!isEventHandleable(event)) return + + if (isEntered) { + numIgnoredEnters += 1 + return false // early return + } + + isEntered = true + + if (listeners.onDragEnter) { + listeners.onDragEnter(event) + } + + addDragClass() + + return false + } + + function onDragOver (event) { + event.stopPropagation() + event.preventDefault() + + if (!isEventHandleable(event)) return + + if (listeners.onDragOver) { + listeners.onDragOver(event) + } + + event.dataTransfer.dropEffect = 'copy' + + return false + } + + function onDragLeave (event) { + event.stopPropagation() + event.preventDefault() + + if (!isEventHandleable(event)) return + + if (numIgnoredEnters > 0) { + numIgnoredEnters -= 1 + return false + } + + isEntered = false + + if (listeners.onDragLeave) { + listeners.onDragLeave(event) + } + + removeDragClass() + + return false + } + + function onDrop (event) { + event.stopPropagation() + event.preventDefault() + if (!event.dataTransfer) throw new Error('not dataTransfer') + + if (listeners.onDragLeave) { + listeners.onDragLeave(event) + } + + removeDragClass() + + isEntered = false + numIgnoredEnters = 0 + + const pos = { + x: event.clientX, + y: event.clientY + } + + // text drop support + const text = event.dataTransfer.getData('text') + if (text && listeners.onDropText) { + listeners.onDropText(text, pos) + } + + // File drop support. The `dataTransfer.items` API supports directories, so we + // use it instead of `dataTransfer.files`, even though it's much more + // complicated to use. + // See: https://github.com/feross/drag-drop/issues/39 + if (listeners.onDrop && event.dataTransfer.items) { + processItems(event.dataTransfer.items, (err, files, directories) => { + if (err) { + // TODO: A future version of this library might expose this somehow + console.error(err) + return + } + + if (files.length === 0) return + + // for TS + if (!event.dataTransfer) throw new Error('not dataTransfer') + const fileList = event.dataTransfer.files + + // TODO: This callback has too many arguments, and the order is too + // arbitrary. In next major version, it should be cleaned up. + listeners.onDrop(files, pos, fileList, directories) + }) + } + + return false + } + + function addDragClass () { + elem!.classList.add('drag') + } + + function removeDragClass () { + elem!.classList.remove('drag') + } +} + +export function processItems (_items:DataTransferItemList, cb) { + // Handle directories in Chrome using the proprietary FileSystem API + const items = Array.from(_items).filter(item => { + return item.kind === 'file' + }) + + if (items.length === 0) { + cb(null, [], []) + } + + parallel(items.map(item => { + return cb => { + processEntry(item.webkitGetAsEntry(), cb) + } + }), (err, results) => { + // This catches permission errors with file:// in Chrome + if (err) { + cb(err) + return + } + + const entries = results.flat(Infinity) + + const files = entries.filter(item => { + return item.isFile + }) + + const directories = entries.filter(item => { + return item.isDirectory + }) + + cb(null, files, directories) + }) +} + +function processEntry (entry, cb) { + let entries = [] + + if (entry.isFile) { + entry.file(file => { + file.fullPath = entry.fullPath // preserve path for consumer + file.isFile = true + file.isDirectory = false + cb(null, file) + }, err => { + cb(err) + }) + } else if (entry.isDirectory) { + const reader = entry.createReader() + readEntries(reader) + } + + function readEntries (reader) { + reader.readEntries(currentEntries => { + if (currentEntries.length > 0) { + entries = entries.concat(Array.from(currentEntries)) + readEntries(reader) // continue reading entries until `readEntries` returns no more + } else { + doneEntries() + } + }) + } + + function doneEntries () { + parallel(entries.map(entry => { + return cb => { + processEntry(entry, cb) + } + }), (err, results) => { + if (err) { + cb(err) + } else { + results.push({ + fullPath: entry.fullPath, + name: entry.name, + isFile: false, + isDirectory: true + }) + cb(null, results) + } + }) + } +} diff --git a/test/basic.js b/test/basic.js deleted file mode 100644 index 57a43d0..0000000 --- a/test/basic.js +++ /dev/null @@ -1,11 +0,0 @@ -const test = require('tape') - -// writing tests for this would be hard, so let's just check that requiring the module -// doesn't throw - -test('requiring drag-drop does not throw', t => { - t.doesNotThrow(() => { - require('../') - }) - t.end() -}) diff --git a/test/index.html b/test/index.html new file mode 100644 index 0000000..cb0f0d4 --- /dev/null +++ b/test/index.html @@ -0,0 +1,13 @@ + + + + + tests + + + + +
+ + + diff --git a/test/index.ts b/test/index.ts new file mode 100644 index 0000000..fbabe59 --- /dev/null +++ b/test/index.ts @@ -0,0 +1,9 @@ +import { test } from '@bicycle-codes/tapzero' +import { dragDrop } from '../src/index.js' + +// writing tests for this would be hard, see the example for interactive testing + +test('Basics', t => { + dragDrop('#drop-target', () => null) + t.ok("Doesn't throw") +}) diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..1d7d702 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "exclude": [ + "example", + "test" + ] +} + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1b1ebd5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "listFiles": true, + "module": "ES2022", + "target": "ES2022", + "moduleResolution": "Bundler", + "esModuleInterop": false, + "lib": ["ES2022", "DOM", "WebWorker"], + "types": ["vite/client"], + "allowJs": false, + "skipLibCheck": true, + "outDir": "dist", + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "strict": true, + "sourceMap": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noImplicitAny": false, + "declaration": true, + "declarationDir": "dist", + "declarationMap": true + }, + "include": [ + "example", + "src/**/*", + "test", + "lib.es5.d.ts" + ] +} diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..1f53db3 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,35 @@ +import { defineConfig } from 'vite' +import postcssNesting from 'postcss-nesting' + +// https://vitejs.dev/config/ +export default defineConfig({ + define: { + global: 'globalThis' + }, + root: 'example', + plugins: [ + ], + // https://github.com/vitejs/vite/issues/8644#issuecomment-1159308803 + esbuild: { + logOverride: { 'this-is-undefined-in-esm': 'silent' } + }, + publicDir: '_public', + css: { + postcss: { + plugins: [ + postcssNesting + ], + }, + }, + server: { + port: 8888, + host: true, + open: true, + }, + build: { + minify: false, + outDir: '../public', + emptyOutDir: true, + sourcemap: 'inline' + } +})