First private release. Check updated README.md for details
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
831e607591
commit
5ae59102b5
92
CHANGELOG.md
92
CHANGELOG.md
@ -1,90 +1,2 @@
|
|||||||
# Remove me:
|
# 0.0.1
|
||||||
TODO: This started as a fork of, but is now something different entirely. Changelog is no longer relevant (neither is the [README.md](README.md))
|
Initial private release
|
||||||
rollup-plugin-css was used in the initial tests, but it hasnt been update in **7** years. Remove this
|
|
||||||
|
|
||||||
# @rollup/plugin-html ChangeLog
|
|
||||||
|
|
||||||
## v1.0.2
|
|
||||||
|
|
||||||
_2023-01-20_
|
|
||||||
|
|
||||||
### Bugfixes
|
|
||||||
|
|
||||||
- fix: types should come first in exports [#1403](https://github.com/rollup/plugins/pull/1403)
|
|
||||||
|
|
||||||
## v1.0.1
|
|
||||||
|
|
||||||
_2022-10-21_
|
|
||||||
|
|
||||||
### Updates
|
|
||||||
|
|
||||||
- chore: update rollup dependencies ([3038271](https://github.com/rollup/plugins/commit/303827191ede6b2e4eade96c6968ed16a587683f))
|
|
||||||
|
|
||||||
## v1.0.0
|
|
||||||
|
|
||||||
_2022-10-09_
|
|
||||||
|
|
||||||
### Breaking Changes
|
|
||||||
|
|
||||||
- fix: prepare for Rollup 3 [#1294](https://github.com/rollup/plugins/pull/1294)
|
|
||||||
|
|
||||||
### Bugfixes
|
|
||||||
|
|
||||||
- fix: function signature of html updated [#975](https://github.com/rollup/plugins/pull/975)
|
|
||||||
|
|
||||||
## v0.2.3
|
|
||||||
|
|
||||||
_2021-02-14_
|
|
||||||
|
|
||||||
### Bugfixes
|
|
||||||
|
|
||||||
- fix: package.json files (#802)
|
|
||||||
|
|
||||||
## v0.2.2
|
|
||||||
|
|
||||||
_2021-01-29_
|
|
||||||
|
|
||||||
### Updates
|
|
||||||
|
|
||||||
- chore: run build before publish (ce65c12)
|
|
||||||
- chore: upgrade TypeScript (#713)
|
|
||||||
- refactor: refactor to typescript (#634)
|
|
||||||
- chore: update dependencies (6c8614c)
|
|
||||||
|
|
||||||
## v0.2.1
|
|
||||||
|
|
||||||
_2021-01-29_
|
|
||||||
|
|
||||||
### Updates
|
|
||||||
|
|
||||||
- chore: run build before publish (ce65c12)
|
|
||||||
- chore: upgrade TypeScript (#713)
|
|
||||||
- refactor: refactor to typescript (#634)
|
|
||||||
- chore: update dependencies (6c8614c)
|
|
||||||
|
|
||||||
## v0.2.0
|
|
||||||
|
|
||||||
_2020-05-02_
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
- feat: support custom meta element creation (#308)
|
|
||||||
|
|
||||||
### Updates
|
|
||||||
|
|
||||||
- test: update snapshots for rollup v2 (c09509f)
|
|
||||||
|
|
||||||
## v0.1.1
|
|
||||||
|
|
||||||
_2020-01-04_
|
|
||||||
|
|
||||||
### Updates
|
|
||||||
|
|
||||||
- docs: fix <br> tag (#89)
|
|
||||||
- test: change tests to serial to avoid weird snapshot conflicts (a492ce7)
|
|
||||||
|
|
||||||
## 0.1.0
|
|
||||||
|
|
||||||
_2019-11-29_
|
|
||||||
|
|
||||||
- First Release
|
|
||||||
|
|||||||
184
README.md
184
README.md
@ -1,33 +1,41 @@
|
|||||||
# Work-in-progress changelog
|
[npm]: https://img.shields.io/npm/v/rollup-plugin-html-entry2
|
||||||
|
[npm-url]: https://www.npmjs.com/package/rollup-plugin-html-entry2
|
||||||
|
[size]: https://packagephobia.now.sh/badge?p=rollup-plugin-html-entry2
|
||||||
|
[size-url]: https://packagephobia.now.sh/result?p=rollup-plugin-html-entry2
|
||||||
|
[handlebars]: https://www.npmjs.com/package/handlebars
|
||||||
[npm]: https://img.shields.io/npm/v/@rollup/plugin-html
|
|
||||||
[npm-url]: https://www.npmjs.com/package/@rollup/plugin-html
|
|
||||||
[size]: https://packagephobia.now.sh/badge?p=@rollup/plugin-html
|
|
||||||
[size-url]: https://packagephobia.now.sh/result?p=@rollup/plugin-html
|
|
||||||
|
|
||||||
[![npm][npm]][npm-url]
|
[![npm][npm]][npm-url]
|
||||||
[![size][size]][size-url]
|
[![size][size]][size-url]
|
||||||
[](https://liberamanifesto.com)
|
[](https://liberamanifesto.com)
|
||||||
|
|
||||||
# @rollup/plugin-html
|
# rollup-plugin-html-entry2
|
||||||
|
| :warning: WARNING |
|
||||||
|
|:-------------------------------------------------------------------|
|
||||||
|
| **Experimental-stage** plugin. Expect bugs and missing features... |
|
||||||
|
|
||||||
🍣 A Rollup plugin which creates HTML files to serve Rollup bundles.
|
|
||||||
|
|
||||||
Please see [Supported Output Formats](#supported-output-formats) for information about using this plugin with output formats other than `esm` (`es`), `iife`, and `umd`.
|
A(nother) rollup plugin that tries to teach Rollup to start from an HTML entry, and the use of (multiple) HTML files in general.
|
||||||
|
The goal is to include assets referenced by the HTML file into the build-process as to copy/inline where appropriate and
|
||||||
|
optionally optimize them. Without having to seperatly copy them to the output directory.
|
||||||
|
|
||||||
|
When building web-applications a HTML-file is simply the logical entry point into your application. \
|
||||||
|
Inspired (and forked) by the original [@rollup/plugin-html](https://www.npmjs.com/package/@rollup/plugin-html),
|
||||||
|
this plugin will also allow you to transform the source files by any HTML-templating engine such as [handlebars].
|
||||||
|
|
||||||
|
|
||||||
|
Please see [Supported Output Formats](#supported-output-formats) for information about using this plugin with output formats other than `esm` (`es`).
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
This plugin requires an [LTS](https://github.com/nodejs/Release) Node version (v14.0.0+) and Rollup v1.20.0+.
|
This plugin requires an [LTS](https://github.com/nodejs/Release) Node version (v18.0.0+) and Rollup v3.?.?+.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Using npm:
|
Using npm:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
npm install @rollup/plugin-html --save-dev
|
npm install rollup-plugin-html-entry2 --save-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -35,131 +43,85 @@ npm install @rollup/plugin-html --save-dev
|
|||||||
Create a `rollup.config.js` [configuration file](https://www.rollupjs.org/guide/en/#configuration-files) and import the plugin:
|
Create a `rollup.config.js` [configuration file](https://www.rollupjs.org/guide/en/#configuration-files) and import the plugin:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const html = require('@rollup/plugin-html');
|
import html from 'rollup-plugin-html-entry2';
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
input: 'src/index.js',
|
input: 'src/index.html',
|
||||||
output: {
|
output: {
|
||||||
dir: 'output',
|
dir: 'output',
|
||||||
format: 'cjs'
|
|
||||||
},
|
},
|
||||||
plugins: [html()]
|
plugins: [html()]
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!! To use 'import x from y' syntax you might need to set `"type": "module"` in your `package.json`.
|
||||||
|
[Javascript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) are the _preferred_ way of writing modern Javascript.
|
||||||
|
Due to the early stage development of this plugin, old-style CommonJS modules are completely ignored for now.
|
||||||
|
|
||||||
Then call `rollup` either via the [CLI](https://www.rollupjs.org/guide/en/#command-line-reference) or the [API](https://www.rollupjs.org/guide/en/#javascript-api).
|
Then call `rollup` either via the [CLI](https://www.rollupjs.org/guide/en/#command-line-reference) or the [API](https://www.rollupjs.org/guide/en/#javascript-api).
|
||||||
|
|
||||||
Once run successfully, an HTML file should be written to the bundle output destination.
|
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
### `attributes`
|
|
||||||
|
|
||||||
Type: `Object`<br>
|
|
||||||
Default: `{ html: { lang: 'en' }, link: null, script: null }`
|
|
||||||
|
|
||||||
Specifies additional attributes for `html`, `link`, and `script` elements. For each property, provide an object with key-value pairs that represent an HTML element attribute name and value. By default, the `html` element is rendered with an attribute of `lang="en"`.
|
|
||||||
|
|
||||||
_Note: If using the `es` / `esm` output format, `{ type: 'module'}` is automatically added to `attributes.script`._
|
|
||||||
|
|
||||||
### `fileName`
|
|
||||||
|
|
||||||
Type: `String`<br>
|
|
||||||
Default: `'index.html'`
|
|
||||||
|
|
||||||
### `meta`
|
|
||||||
|
|
||||||
Type: `Array[...object]`<br>
|
|
||||||
Default: `[{ charset: 'utf-8' }]`
|
|
||||||
|
|
||||||
Specifies attributes used to create `<meta>` elements. For each array item, provide an object with key-value pairs that represent `<meta>` element attribute names and values.
|
|
||||||
|
|
||||||
Specifies the name of the HTML to emit.
|
|
||||||
|
|
||||||
### `publicPath`
|
|
||||||
|
|
||||||
Type: `String`<br>
|
|
||||||
Default: `''`
|
|
||||||
|
|
||||||
Specifies a path to prepend to all bundle assets (files) in the HTML output.
|
|
||||||
|
|
||||||
### `template`
|
### `template`
|
||||||
|
|
||||||
Type: `Function`<br>
|
Type: `Function`<br>
|
||||||
Default: `internal function`
|
Default: `undefined`\
|
||||||
Returns: `String`
|
Returns: `String`
|
||||||
|
|
||||||
Specifies a function that provides the rendered source for the HTML output. The function should be in the form of:
|
Specifies a transform to be applied before parsing the HTML, this allows you to transform the sourcefile with a templating engine such as [handlebars] first.
|
||||||
|
|
||||||
```js
|
```javascript
|
||||||
const template = ({ attributes, bundle, files, publicPath, title }) => { ... }
|
import {rollup} from "rollup";
|
||||||
```
|
import handlebars from "handlebars";
|
||||||
|
import html from "rollup-plugin-html-entry2";
|
||||||
|
|
||||||
- `attributes`: Corresponds to the `attributes` option passed to the plugin
|
async function build() {
|
||||||
- `bundle`: An `Object` containing key-value pairs of [`AssetInfo` or `ChunkInfo`](https://rollupjs.org/guide/en/#generatebundle)
|
await rollup({
|
||||||
- `files`: An `Array` of `AssetInfo` or `ChunkInfo` containing any entry (`isEntry: true`) files, and any asset (`isAsset: true`) files in the bundle that will be emitted
|
input: 'index.hbs',
|
||||||
- `publicPath`: Corresponds to the `publicPath` option passed to the plugin
|
plugins: [
|
||||||
- `title`: Corresponds to the `title` option passed to the plugin
|
html({
|
||||||
|
transform(src) {
|
||||||
By default this is handled internally and produces HTML in the following format:
|
return handlebars.compile(src)({a: 'a'})
|
||||||
|
}
|
||||||
```html
|
})
|
||||||
<!DOCTYPE html>
|
]
|
||||||
<html ${attributes}>
|
});
|
||||||
<head>
|
}
|
||||||
${metas}
|
|
||||||
<title>${title}</title>
|
|
||||||
${links}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
${scripts}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
Where `${links}` represents all `<link ..` tags for CSS and `${scripts}` represents all `<script...` tags for JavaScript files.
|
|
||||||
|
|
||||||
### `title`
|
|
||||||
|
|
||||||
Type: `String`<br>
|
|
||||||
Default: `'Rollup Bundle'`
|
|
||||||
|
|
||||||
Specifies the HTML document title.
|
|
||||||
|
|
||||||
## Exports
|
|
||||||
|
|
||||||
### `makeHtmlAttributes(attributes)`
|
|
||||||
|
|
||||||
Parameters: `attributes`, Type: `Object`<br>
|
|
||||||
Returns: `String`
|
|
||||||
|
|
||||||
Consumes an object with key-value pairs that represent an HTML element attribute name and value. The function returns all pairs as a space-separated string of valid HTML element attributes. e.g.
|
|
||||||
|
|
||||||
```js
|
|
||||||
const { makeHtmlAttributes } = require('@rollup/plugin-html');
|
|
||||||
|
|
||||||
makeHtmlAttributes({ lang: 'en', 'data-batcave': 'secret' });
|
|
||||||
// -> 'lang="en" data-batcave="secret"'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Supported Output Formats
|
## Supported Output Formats
|
||||||
|
|
||||||
By default, this plugin supports the `esm` (`es`), `iife`, and `umd` [output formats](https://rollupjs.org/guide/en/#outputformat), as those are most commonly used as browser bundles. Other formats can be used, but will require using the [`template`](#template) option to specify a custom template function which renders the unique requirements of other formats.
|
By default, this plugin supports the `esm` (`es`). Any other format is currently untested as this plugin is in an early state, see [#status](#status)
|
||||||
|
|
||||||
### `amd`
|
## Status
|
||||||
|
|
||||||
Will likely require use of RequireJS semantics, which allows only for a single entry `<script>` tag. If more entry chunks are emitted, these need to be loaded via a proxy file. RequireJS would also need to be a dependency and added to the build: https://requirejs.org/docs/start.html.
|
This plugin is in an early state. As such not everything that is supported yet, and the options may change.
|
||||||
|
|
||||||
### `system`
|
### (Rudimentarily) supported
|
||||||
|
- Importing JS via `<script src="..." type="module">` tags
|
||||||
|
- Importing assets using @rollup/plugin-url (which could use an update TBH)
|
||||||
|
- Compatibility with other plugins such as @rollup/plugin-node-resolve, @rollup/plugin-babel, @rollup/plugin-commonjs, @rollup/plugin-terser and rollup-plugin-livereload
|
||||||
|
|
||||||
Would require a separate `<script>` tag first that adds the `s.js` minimal loader. Loading modules might then resemble: `<script>System.import('./batman.js')</script>`.
|
|
||||||
|
|
||||||
## Attribution
|
### Not (yet) supported
|
||||||
|
- Inline scripts (i.e `<script>...</script>`)
|
||||||
|
- Plugins importing CSS files
|
||||||
|
- CommonJS (cjs) and IIFI output formats. (Is UMD actually ever used?)
|
||||||
|
- Overriding which tags to ignore/include
|
||||||
|
- Other (various) plugins such as those for HMR etc
|
||||||
|
- ...
|
||||||
|
|
||||||
This plugin was inspired by and is based upon [mini-html-webpack-plugin](https://github.com/styleguidist/mini-html-webpack-plugin) by Juho Vepsäläinen and Artem Sapegin, with permission.
|
# Contibuting
|
||||||
|
|
||||||
## Meta
|
You can be helpful by testing, proving helpful feedback, expanding the documentation, responding to issues/questions being reported, resolving the many ToDo`s in the code, implementating features...\
|
||||||
|
[Get in touch](mailto:rollup-plugin-html-entry2@cerxes.net) or just dive into [the code](https://git.cerxes.net/rollup-apps/plugin-html) or [issues](https://git.cerxes.net/rollup-apps/plugin-html/issues)
|
||||||
|
|
||||||
[CONTRIBUTING](/.github/CONTRIBUTING.md)
|
# Notes
|
||||||
|
## git.cerxes.net
|
||||||
[LICENSE (MIT)](/LICENSE)
|
Once publicly released, the intent is to move the GIT-repository to github. Until that day though, it exists privately on this gitea server and corresponding npm-registry [npm.cerxes.net](https://npm.cerxes.net).\
|
||||||
|
TODO: change the links once this happens
|
||||||
|
## Prior work
|
||||||
|
- [Vite](https://vitejs.dev) seems to have already [done work])(https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/html.ts) to handle HTML in rollup.
|
||||||
|
- [rollup-plugin-html-entry](https://www.npmjs.com/package/rollup-plugin-html-entry) seems to be **dead**. Last version from 2020, there have been many changes to rollup`s plugin capabilities since then
|
||||||
|
- [@rollup/plugin-html](https://www.npmjs.com/package/@rollup/plugin-html) is where this project was originally forked from. Its main focus was to generate an HTML to serve the resulting bundle. Which is different from supporting HTML as entry point since it did not resolve assets used in the HTML. Besides the project setup, not much of the original has been kept...
|
||||||
|
- [@web/rollup-plugin-html](https://www.npmjs.com/package/@web/rollup-plugin-html) a plugin with similar intentions as this one (in active development anno 2023).
|
||||||
|
|||||||
23
package.json
23
package.json
@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "@rollup-apps/plugin-html",
|
"name": "rollup-plugin-html-entry2",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "Creates HTML files to serve Rollup bundles",
|
"description": "Teaches rollup how to deal with HTML, allows to use HTML-files as entry-points.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "rollup/plugins",
|
"type": "git",
|
||||||
"directory": "packages/html"
|
"url": "https://git.cerxes.net/rollup-apps/plugin-html.git"
|
||||||
},
|
},
|
||||||
"author": "Andrew Powell <andrew@shellscape.org>",
|
"author": "Miel Truyen <miel.truyen@cerxes.net>",
|
||||||
"homepage": "https://github.com/rollup/plugins/tree/master/packages/html#readme",
|
"homepage": "https://git.cerxes.net/rollup-apps/plugin-html",
|
||||||
"bugs": "https://github.com/rollup/plugins/issues",
|
"bugs": "https://git.cerxes.net/rollup-apps/plugin-html/issues",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@ -27,11 +27,11 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
"prerelease": "pnpm build",
|
"prerelease": "pnpm build",
|
||||||
"test": "ava",
|
|
||||||
"ci:coverage": "nyc pnpm test && nyc report --reporter=text-lcov > coverage.lcov",
|
"ci:coverage": "nyc pnpm test && nyc report --reporter=text-lcov > coverage.lcov",
|
||||||
"ci:lint": "pnpm build && pnpm lint-staged",
|
"ci:lint": "pnpm build && pnpm lint-staged",
|
||||||
"ci:test": "pnpm test -- --verbose",
|
"ci:test": "pnpm test -- --verbose",
|
||||||
"dev-test": "ava --match='handlebars*' --update-snapshots"
|
"run-test": "ava",
|
||||||
|
"save-test": "ava --update-snapshots"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
@ -77,7 +77,10 @@
|
|||||||
"@babel/preset-typescript": "^7.21.4",
|
"@babel/preset-typescript": "^7.21.4",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"lint-staged": "^13.2.1",
|
"lint-staged": "^13.2.1",
|
||||||
"handlebars": "^4.7.7"
|
"handlebars": "^4.7.7",
|
||||||
|
"@rollup/plugin-url": "^8.0.1",
|
||||||
|
"chalk": "^5.2.0",
|
||||||
|
"rollup-plugin-livereload": "^2.0.5"
|
||||||
},
|
},
|
||||||
"types": "./types/index.d.ts",
|
"types": "./types/index.d.ts",
|
||||||
"ava": {
|
"ava": {
|
||||||
|
|||||||
75
pnpm-lock.yaml
generated
75
pnpm-lock.yaml
generated
@ -27,12 +27,18 @@ devDependencies:
|
|||||||
'@rollup/plugin-typescript':
|
'@rollup/plugin-typescript':
|
||||||
specifier: ^11.1.0
|
specifier: ^11.1.0
|
||||||
version: 11.1.0(rollup@3.20.3)(tslib@2.5.0)(typescript@5.0.4)
|
version: 11.1.0(rollup@3.20.3)(tslib@2.5.0)(typescript@5.0.4)
|
||||||
|
'@rollup/plugin-url':
|
||||||
|
specifier: ^8.0.1
|
||||||
|
version: 8.0.1(rollup@3.20.3)
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^18.15.11
|
specifier: ^18.15.11
|
||||||
version: 18.15.11
|
version: 18.15.11
|
||||||
ava:
|
ava:
|
||||||
specifier: ^5.2.0
|
specifier: ^5.2.0
|
||||||
version: 5.2.0
|
version: 5.2.0
|
||||||
|
chalk:
|
||||||
|
specifier: ^5.2.0
|
||||||
|
version: 5.2.0
|
||||||
del-cli:
|
del-cli:
|
||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.0.0
|
version: 5.0.0
|
||||||
@ -54,6 +60,9 @@ devDependencies:
|
|||||||
rollup-plugin-delete:
|
rollup-plugin-delete:
|
||||||
specifier: ^2.0.0
|
specifier: ^2.0.0
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
|
rollup-plugin-livereload:
|
||||||
|
specifier: ^2.0.5
|
||||||
|
version: 2.0.5
|
||||||
rollup-plugin-postcss:
|
rollup-plugin-postcss:
|
||||||
specifier: ^4.0.2
|
specifier: ^4.0.2
|
||||||
version: 4.0.2(postcss@8.4.22)(ts-node@10.9.1)
|
version: 4.0.2(postcss@8.4.22)(ts-node@10.9.1)
|
||||||
@ -560,6 +569,21 @@ packages:
|
|||||||
typescript: 5.0.4
|
typescript: 5.0.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@rollup/plugin-url@8.0.1(rollup@3.20.3):
|
||||||
|
resolution: {integrity: sha512-8ajztphXb5e19dk3Iwjtm2eSYJR8jFQubZ8pJ1GG2MBMM7/qUedLnZAN+Vt4jqbcT/m27jfjIBocvrzV0giNRw==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
rollup: ^1.20.0||^2.0.0||^3.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
rollup:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@rollup/pluginutils': 5.0.2(rollup@3.20.3)
|
||||||
|
make-dir: 3.1.0
|
||||||
|
mime: 3.0.0
|
||||||
|
rollup: 3.20.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@rollup/pluginutils@5.0.2(rollup@3.20.3):
|
/@rollup/pluginutils@5.0.2(rollup@3.20.3):
|
||||||
resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
|
resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@ -2023,6 +2047,24 @@ packages:
|
|||||||
wrap-ansi: 7.0.0
|
wrap-ansi: 7.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/livereload-js@3.4.1:
|
||||||
|
resolution: {integrity: sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/livereload@0.9.3:
|
||||||
|
resolution: {integrity: sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==}
|
||||||
|
engines: {node: '>=8.0.0'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
chokidar: 3.5.3
|
||||||
|
livereload-js: 3.4.1
|
||||||
|
opts: 2.0.2
|
||||||
|
ws: 7.5.9
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- bufferutil
|
||||||
|
- utf-8-validate
|
||||||
|
dev: true
|
||||||
|
|
||||||
/load-json-file@7.0.1:
|
/load-json-file@7.0.1:
|
||||||
resolution: {integrity: sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==}
|
resolution: {integrity: sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==}
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
@ -2186,6 +2228,12 @@ packages:
|
|||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/mime@3.0.0:
|
||||||
|
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
|
||||||
|
engines: {node: '>=10.0.0'}
|
||||||
|
hasBin: true
|
||||||
|
dev: true
|
||||||
|
|
||||||
/mimic-fn@2.1.0:
|
/mimic-fn@2.1.0:
|
||||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -2347,6 +2395,10 @@ packages:
|
|||||||
mimic-fn: 4.0.0
|
mimic-fn: 4.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/opts@2.0.2:
|
||||||
|
resolution: {integrity: sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/p-defer@1.0.0:
|
/p-defer@1.0.0:
|
||||||
resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==}
|
resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@ -3066,6 +3118,16 @@ packages:
|
|||||||
del: 5.1.0
|
del: 5.1.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/rollup-plugin-livereload@2.0.5:
|
||||||
|
resolution: {integrity: sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==}
|
||||||
|
engines: {node: '>=8.3'}
|
||||||
|
dependencies:
|
||||||
|
livereload: 0.9.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- bufferutil
|
||||||
|
- utf-8-validate
|
||||||
|
dev: true
|
||||||
|
|
||||||
/rollup-plugin-postcss@4.0.2(postcss@8.4.22)(ts-node@10.9.1):
|
/rollup-plugin-postcss@4.0.2(postcss@8.4.22)(ts-node@10.9.1):
|
||||||
resolution: {integrity: sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==}
|
resolution: {integrity: sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -3577,6 +3639,19 @@ packages:
|
|||||||
signal-exit: 3.0.7
|
signal-exit: 3.0.7
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/ws@7.5.9:
|
||||||
|
resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==}
|
||||||
|
engines: {node: '>=8.3.0'}
|
||||||
|
peerDependencies:
|
||||||
|
bufferutil: ^4.0.1
|
||||||
|
utf-8-validate: ^5.0.2
|
||||||
|
peerDependenciesMeta:
|
||||||
|
bufferutil:
|
||||||
|
optional: true
|
||||||
|
utf-8-validate:
|
||||||
|
optional: true
|
||||||
|
dev: true
|
||||||
|
|
||||||
/y18n@4.0.3:
|
/y18n@4.0.3:
|
||||||
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
|
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|||||||
@ -30,13 +30,14 @@ export function createConfig({ pkg, external = [] }) {
|
|||||||
},
|
},
|
||||||
strictDeprecations: true,
|
strictDeprecations: true,
|
||||||
output: [
|
output: [
|
||||||
{
|
// TODO: cjs output not supported for now
|
||||||
format: 'cjs',
|
// {
|
||||||
file: pkg.main,
|
// format: 'cjs',
|
||||||
exports: 'named',
|
// file: pkg.main,
|
||||||
footer: 'module.exports = Object.assign(exports.default, exports);',
|
// exports: 'named',
|
||||||
sourcemap: true
|
// footer: 'module.exports = Object.assign(exports.default, exports);',
|
||||||
},
|
// sourcemap: true
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
format: 'es',
|
format: 'es',
|
||||||
file: pkg.module,
|
file: pkg.module,
|
||||||
@ -57,7 +58,6 @@ export function createConfig({ pkg, external = [] }) {
|
|||||||
...commonOpts,
|
...commonOpts,
|
||||||
babelHelpers: "bundled",
|
babelHelpers: "bundled",
|
||||||
}),
|
}),
|
||||||
// typescript({ sourceMap: true })]
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
378
src/index.ts
378
src/index.ts
@ -20,7 +20,7 @@ import type {
|
|||||||
} from '../types/index.d.ts';
|
} from '../types/index.d.ts';
|
||||||
import {createFilter} from '@rollup/pluginutils';
|
import {createFilter} from '@rollup/pluginutils';
|
||||||
import {parse as parseHtml, serialize as serializeHtml, DefaultTreeAdapterMap} from "parse5";
|
import {parse as parseHtml, serialize as serializeHtml, DefaultTreeAdapterMap} from "parse5";
|
||||||
// import {Script, SourceTextModule, createContext} from "node:vm";
|
import {readFile} from "node:fs/promises"
|
||||||
|
|
||||||
const getFiles = (bundle: OutputBundle): Record<string, (OutputChunk | OutputAsset)[]> => {
|
const getFiles = (bundle: OutputBundle): Record<string, (OutputChunk | OutputAsset)[]> => {
|
||||||
const result = {} as ReturnType<typeof getFiles>;
|
const result = {} as ReturnType<typeof getFiles>;
|
||||||
@ -80,20 +80,26 @@ const defaults: RollupHtmlOptions = {
|
|||||||
|
|
||||||
// Internal type
|
// Internal type
|
||||||
type HtmlImport = {
|
type HtmlImport = {
|
||||||
id: string,
|
id: string;
|
||||||
rollupResolved: ResolvedId|null,
|
rollupResolved: ResolvedId|null;
|
||||||
node: DefaultTreeAdapterMap['element'],
|
node: DefaultTreeAdapterMap['element'];
|
||||||
reference: LoadReference,
|
reference: LoadReference;
|
||||||
referenceId: string|null,
|
referenceId: string|null;
|
||||||
index: number,
|
index: number;
|
||||||
}
|
}
|
||||||
type HtmlModule = {
|
type HtmlModule = {
|
||||||
// TODO might want to impose an own unique id, in case this changes after multiple builds
|
// TODO might want to impose an own unique id, in case this changes after multiple builds
|
||||||
id: string,
|
id: string;
|
||||||
|
name: string;
|
||||||
|
importers: Set<string|undefined>,
|
||||||
resolved: HtmlImport[];
|
resolved: HtmlImport[];
|
||||||
document: DefaultTreeAdapterMap['document'],
|
assetId?: string|null;
|
||||||
|
document?: DefaultTreeAdapterMap['document'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const modulePrefix = `// <html-module>`;
|
||||||
|
const moduleSuffix = `// </html-module>`;
|
||||||
|
|
||||||
export default function html(opts: RollupHtmlOptions = {}): Plugin {
|
export default function html(opts: RollupHtmlOptions = {}): Plugin {
|
||||||
const {
|
const {
|
||||||
publicPath,
|
publicPath,
|
||||||
@ -111,22 +117,167 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
|
|||||||
if(publicPath){ throw new Error("TODO, do something with the public path or throw it out of the options. this is just to stop typescript complaining")}
|
if(publicPath){ throw new Error("TODO, do something with the public path or throw it out of the options. this is just to stop typescript complaining")}
|
||||||
|
|
||||||
let filter = createFilter(include, exclude, {});
|
let filter = createFilter(include, exclude, {});
|
||||||
let handledHtmls = new Map<string, HtmlModule>();// todo clean this per new build?
|
let htmlModules = new Map<string, HtmlModule>();// todo clean this per new build?
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: 'html2',// TODO: Need a better name, original plugin was just named `html` and might still make sense to use in conjunction with this one
|
name: 'html2',// TODO: Need a better name, original plugin was just named `html` and might still make sense to use in conjunction with this one
|
||||||
|
|
||||||
|
resolveId: {
|
||||||
|
async handler(specifier: string,
|
||||||
|
importer: string | undefined,
|
||||||
|
options: { assertions: Record<string, string> }){
|
||||||
|
if(!filter(specifier)) return;
|
||||||
|
|
||||||
|
// Let it be resolved like others (node_modules, project aliases, ..)
|
||||||
|
const resolved = await this.resolve(specifier, importer, {
|
||||||
|
skipSelf: true,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
|
||||||
|
if(resolved){
|
||||||
|
const moduleId = resolved.id;
|
||||||
|
const moduleExt = extname(resolved.id);
|
||||||
|
const moduleName = specifier.replace(new RegExp(`${moduleExt}\$`),''); // strip extension of the name if any
|
||||||
|
const htmlModule : HtmlModule = htmlModules.get(moduleId) ?? {
|
||||||
|
id: resolved.id,
|
||||||
|
name: moduleName,
|
||||||
|
resolved: [],
|
||||||
|
assetId: null,
|
||||||
|
importers: new Set(),
|
||||||
|
};
|
||||||
|
htmlModule.importers.add(importer);
|
||||||
|
|
||||||
|
htmlModules.set(htmlModule.id, htmlModule);
|
||||||
|
// TODO: trigger special handling when imported from a JS file (in which case we want might want to export a module returning the HTML, instead of HTML directly)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
load: {
|
load: {
|
||||||
async handler(id: string) {
|
async handler(id: string) {
|
||||||
if(!filter(id)) return;
|
if(!filter(id)) return;
|
||||||
// We'll be transforming this, but it appears there is no need for us to load it. Rollup will do this
|
|
||||||
|
// Load
|
||||||
|
const htmlModule = htmlModules.get(id);
|
||||||
|
if(htmlModule) {
|
||||||
|
const contents = await readFile(id, {encoding: "utf-8"});
|
||||||
|
|
||||||
|
const htmlSrc = transform ? await transform(contents, {
|
||||||
|
id,
|
||||||
|
}) : contents;
|
||||||
|
|
||||||
|
// Parse document and store it (TODO: check for watch mode, we should check if it needs reparsing or not)
|
||||||
|
const document = htmlModule.document ?? parseHtml(htmlSrc);
|
||||||
|
if(!htmlModule.document){
|
||||||
|
htmlModule.document = document;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out which references to load from this HTML by iterating all nodes (looking for src or href attributes)
|
||||||
|
let loadResults: { reference: LoadReference, node: DefaultTreeAdapterMap['element'] }[] = [];
|
||||||
|
if (document.childNodes) {
|
||||||
|
let nodeQueue = document.childNodes;
|
||||||
|
do {
|
||||||
|
const nextQueue: DefaultTreeAdapterMap['childNode'][][] = [];
|
||||||
|
await Promise.all(nodeQueue.map(async (node) => {
|
||||||
|
const el = (<DefaultTreeAdapterMap['element']>node);
|
||||||
|
let toLoad: LoadResult | undefined = undefined;
|
||||||
|
if (el.attrs) {
|
||||||
|
toLoad = load ? await load({
|
||||||
|
node: el,
|
||||||
|
sourceId: id
|
||||||
|
}) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toLoad) {
|
||||||
|
const loadIds: LoadReference[] = (toLoad instanceof Array) ? toLoad : [toLoad];
|
||||||
|
for (const loadId of loadIds) {
|
||||||
|
loadResults.push({
|
||||||
|
reference: loadId,
|
||||||
|
node: el,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toLoad !== false) {
|
||||||
|
let asParent = (<DefaultTreeAdapterMap['parentNode']>node);
|
||||||
|
if (asParent.childNodes) {
|
||||||
|
nextQueue.push(asParent.childNodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
nodeQueue = nextQueue.flat();
|
||||||
|
} while (nodeQueue.length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out what to resolve (todo, an id can actually be loaded in multiple times, something we might want to keep in mind)
|
||||||
|
await Promise.all(loadResults.map(async ({reference, node}, index) => {
|
||||||
|
const refId = reference.get();
|
||||||
|
const selfResolvedId = resolve ? resolve(refId, {
|
||||||
|
sourceId: id,
|
||||||
|
node,
|
||||||
|
}) : refId;
|
||||||
|
const resolvedId: string = selfResolvedId === true ? refId : (<string>selfResolvedId);
|
||||||
|
if (resolvedId) {
|
||||||
|
const isEntry = !!/.*\.(js|jsx|ts|tsx)$/i.exec(resolvedId); // TODO: for scripts (via src-tag, not those inlined) entry=true. But it should not check via the id (rather how it is imported from html)
|
||||||
|
const rollupResolved = await this.resolve(resolvedId, id, {
|
||||||
|
skipSelf: true,
|
||||||
|
isEntry: isEntry,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: should we test/check if this is refused for resolving here. i.e. external?
|
||||||
|
const htmlImport: HtmlImport = {
|
||||||
|
id: resolvedId,
|
||||||
|
rollupResolved,
|
||||||
|
node,
|
||||||
|
reference,
|
||||||
|
referenceId:
|
||||||
|
// This was triggering resources being marked as entry, and thus their injected loader modules to be outputed to their own files (ie icon.js to load icon.svg)
|
||||||
|
// Should be able to resolve the final HTML from the exported module instead (which though would ideally mean interpreting it as a browser would... )
|
||||||
|
// TODO: however, probably need to uncomment this for <script src="..."> (as those really are entry...)
|
||||||
|
(rollupResolved && isEntry) ? this.emitFile({
|
||||||
|
type: 'chunk', // Might want to adapt, or make configurable,
|
||||||
|
id: rollupResolved.id,
|
||||||
|
importer: id,
|
||||||
|
// implicitlyLoadedAfterOneOf: [id],// TODO: this was triggering weird results, guess i don't fully understand its purpose... remove when certain
|
||||||
|
}) : null,
|
||||||
|
index,
|
||||||
|
};
|
||||||
|
|
||||||
|
htmlModule.resolved.push(htmlImport);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Rollup only understands JS, so we return matching JS module here that would export the html as the default export. And imports any resources through JS, expecting the inlineable value to be in the default export.
|
||||||
|
// Note: Not sure if it is safe to rely on this default-export 'convention' much.
|
||||||
|
// import the default export of all resources through JS and inject them in the resulting HTML
|
||||||
|
const htmlImports : string[] = [];
|
||||||
|
htmlModule.resolved.forEach((htmlImport, index)=>{
|
||||||
|
if(htmlImport.referenceId){
|
||||||
|
// Should only be triggered for <script src="...">
|
||||||
|
htmlImport.reference.set(`\${import.meta.ROLLUP_FILE_URL_${htmlImport.referenceId}\}`);
|
||||||
|
}else{
|
||||||
|
// Asset
|
||||||
|
const assetId = `asset${index}`;// TODO: This is just the easy & safe solution. Would prefer to have recognizable names, and reeuse when something is the exact same resource..
|
||||||
|
htmlImports.push(`import ${assetId} from "${htmlImport.id}";`);// TODO: Should we be worried about windows absolute URLs here?
|
||||||
|
htmlImport.reference.set(`\${${assetId}}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const htmlJSModule = [
|
||||||
|
...htmlImports,
|
||||||
|
``,
|
||||||
|
`export const html = \`${serializeHtml(htmlModule.document).replaceAll(/`/g,'\\\`')}\`;`,
|
||||||
|
`export default html;`,
|
||||||
|
].join('\n');
|
||||||
|
return {
|
||||||
|
code: htmlJSModule,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
outputOptions(options){
|
outputOptions(options){
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
entryFileNames: (chunkInfo)=>{
|
entryFileNames: (chunkInfo)=>{
|
||||||
const htmlModule = chunkInfo.facadeModuleId ? handledHtmls.get(chunkInfo.facadeModuleId!) : null;
|
const htmlModule = chunkInfo.facadeModuleId ? htmlModules.get(chunkInfo.facadeModuleId!) : null;
|
||||||
const defaultOption = options.entryFileNames ?? "[name]-[hash].js";// This default is copied from the docs. TODO: don't like overwrite it this way, can we remove the need for this or fetch the true default?
|
const defaultOption = options.entryFileNames ?? "[name]-[hash].js";// This default is copied from the docs. TODO: don't like overwrite it this way, can we remove the need for this or fetch the true default?
|
||||||
if(htmlModule){
|
if(htmlModule){
|
||||||
let fileName = typeof (htmlFileNames) === 'string' ? htmlFileNames : (<(chunkInfo:PreRenderedChunk)=>string>htmlFileNames)(chunkInfo);
|
let fileName = typeof (htmlFileNames) === 'string' ? htmlFileNames : (<(chunkInfo:PreRenderedChunk)=>string>htmlFileNames)(chunkInfo);
|
||||||
@ -139,126 +290,93 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
|
|||||||
// TODO do we need to do the same for chunks?? (what if they're dynamically imported?)
|
// TODO do we need to do the same for chunks?? (what if they're dynamically imported?)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
transform: {
|
resolveFileUrl(options){
|
||||||
async handler(code: string, id: string){
|
const htmlModule = htmlModules.get(options.moduleId);
|
||||||
if(!filter(id)) return;
|
|
||||||
|
|
||||||
const htmlSrc = transform? await transform(code, {
|
|
||||||
id,
|
|
||||||
}) : code;
|
|
||||||
|
|
||||||
const document = parseHtml(htmlSrc);
|
|
||||||
|
|
||||||
const handled : HtmlModule = {
|
|
||||||
id,
|
|
||||||
resolved: [],
|
|
||||||
document,
|
|
||||||
};
|
|
||||||
handledHtmls.set(id, handled);
|
|
||||||
|
|
||||||
// Figure out which references to load from this HTML by iterating all nodes (looking for src or href attributes)
|
|
||||||
let loadResults : { reference: LoadReference, node: DefaultTreeAdapterMap['element'] }[] = [];
|
|
||||||
if(document.childNodes){
|
|
||||||
let nodeQueue = document.childNodes;
|
|
||||||
do{
|
|
||||||
const nextQueue: DefaultTreeAdapterMap['childNode'][][] = [];
|
|
||||||
await Promise.all(nodeQueue.map(async (node)=>{
|
|
||||||
const el = (<DefaultTreeAdapterMap['element']>node);
|
|
||||||
let toLoad: LoadResult|undefined = undefined;
|
|
||||||
if(el.attrs) {
|
|
||||||
toLoad = load ? await load({
|
|
||||||
node: el,
|
|
||||||
sourceId: id
|
|
||||||
}): [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(toLoad){
|
|
||||||
const loadIds: LoadReference[] = (toLoad instanceof Array)? toLoad: [toLoad];
|
|
||||||
for(const loadId of loadIds){
|
|
||||||
loadResults.push({
|
|
||||||
reference: loadId,
|
|
||||||
node: el,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(toLoad !== false) {
|
|
||||||
let asParent = (<DefaultTreeAdapterMap['parentNode']>node);
|
|
||||||
if (asParent.childNodes) {
|
|
||||||
nextQueue.push(asParent.childNodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
nodeQueue = nextQueue.flat();
|
|
||||||
}while(nodeQueue.length > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out what to resolve (todo, an id can actually be loaded in multiple times, something we might want to keep in mind)
|
|
||||||
await Promise.all(loadResults.map(async ({reference, node}, index)=>{
|
|
||||||
const refId = reference.get();
|
|
||||||
const selfResolvedId = resolve? resolve(refId, {
|
|
||||||
sourceId: id,
|
|
||||||
node,
|
|
||||||
}) : refId;
|
|
||||||
const resolvedId : string = selfResolvedId===true?refId:(<string>selfResolvedId);
|
|
||||||
if(resolvedId){
|
|
||||||
const rollupResolved = await this.resolve(resolvedId, id, {
|
|
||||||
skipSelf: true,
|
|
||||||
isEntry: true, // TODO: for href/src tags, this is probably the right option. For anything that is to be inlined into the HTML... probably not
|
|
||||||
});
|
|
||||||
// TODO: should we check if this is refused for resolving here. i.e. external?
|
|
||||||
const htmlImport: HtmlImport = {
|
|
||||||
id: resolvedId,
|
|
||||||
rollupResolved,//rollupResolved,
|
|
||||||
node,
|
|
||||||
reference,
|
|
||||||
referenceId: rollupResolved? this.emitFile({
|
|
||||||
type: 'chunk', // Might want to adapt, or make configurable,
|
|
||||||
id: rollupResolved.id,
|
|
||||||
importer: id,
|
|
||||||
implicitlyLoadedAfterOneOf: [id],
|
|
||||||
}) : null,
|
|
||||||
index,
|
|
||||||
};
|
|
||||||
if(htmlImport.referenceId) {
|
|
||||||
// only used when importing from javascript
|
|
||||||
reference.set(`\${import.meta.ROLLUP_FILE_URL_${htmlImport.referenceId}\}`);
|
|
||||||
}
|
|
||||||
handled.resolved.push(htmlImport);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
// console.log(`TODO, add the following for further transformations:\n${resolveResults.map(x=>` ${x.id}`).join('\n')}`); //and figure out how other libraries later replace the import...
|
|
||||||
|
|
||||||
// Transform to JS
|
|
||||||
const serialized = serializeHtml(document);
|
|
||||||
const jsModule = [
|
|
||||||
// This will only make sense when importing from javascript
|
|
||||||
`export const html = \`${serialized.replaceAll(/`/g,'\\\`')}\`;`,
|
|
||||||
`export default html;`
|
|
||||||
].join('\n');
|
|
||||||
|
|
||||||
return {code: jsModule};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async renderChunk(
|
|
||||||
code: string,
|
|
||||||
chunk: RenderedChunk,
|
|
||||||
options: NormalizedOutputOptions,
|
|
||||||
meta: { chunks: Record<string, RenderedChunk> }
|
|
||||||
){
|
|
||||||
const htmlModule = chunk.facadeModuleId ? handledHtmls.get(chunk.facadeModuleId!) : null;
|
|
||||||
if(htmlModule){
|
if(htmlModule){
|
||||||
let html = '';
|
// Simply use the relative path in our HTML-fileURLs instead of the default `new URL('${fileName}', document.baseURI).href`)
|
||||||
for(const htmlImport of htmlModule.resolved){
|
return `"${options.relativePath}"`;
|
||||||
if(htmlImport.referenceId) {
|
|
||||||
const fileName = this.getFileName(htmlImport.referenceId);
|
|
||||||
htmlImport.reference.set(fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
html = serializeHtml(htmlModule.document);// This might contain temporary hashes, but it should be alright
|
|
||||||
return {code: html};
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
banner: {
|
||||||
|
// Injects a tag so we know where our bundle starts so we can safely ignore other stuff addded via a banner (ie. live-reload)
|
||||||
|
order:'post',
|
||||||
|
handler(chunk: RenderedChunk){
|
||||||
|
if(chunk.facadeModuleId) {
|
||||||
|
const htmlModule = htmlModules.get(chunk.facadeModuleId);
|
||||||
|
if (htmlModule) {
|
||||||
|
return modulePrefix; // Overwrite any added banner with our own
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async generateBundle(outputOptions, bundles){
|
||||||
|
const bundleItems = Object.entries(bundles);
|
||||||
|
for(let [bundlename, bundle] of bundleItems){
|
||||||
|
const chunk = (<OutputChunk>bundle);
|
||||||
|
if(chunk.facadeModuleId) {
|
||||||
|
const htmlModule = htmlModules.get(chunk.facadeModuleId);
|
||||||
|
if (htmlModule) {
|
||||||
|
|
||||||
|
if(htmlModule.document) {
|
||||||
|
// Delete the placeholder chunk from the bundle and emit an asset file for the HTML instead.
|
||||||
|
delete bundles[bundlename];
|
||||||
|
delete bundles[`${bundlename}.map`];// Also delete any generated map files because they don't make any sense. (TODO: there seems to be no better way to detect this?)
|
||||||
|
|
||||||
|
// Interpret the module and take its default export (TODO: if [NodeJS vm SourceTextModule](https://nodejs.org/api/vm.html#class-vmsourcetextmodule) ever lands, it would be cleaner to use that one instead of directly importing it)
|
||||||
|
let htmlContents: string;
|
||||||
|
|
||||||
|
// Take out the sourceMapUrl if any (it will not have been written yet and tends to cause a crash, we don't need it anyway))
|
||||||
|
let sanitizedCode = chunk.code;
|
||||||
|
|
||||||
|
// Use the modulePrefix to filter out prepended code that is not relevant for us (like live-reload)
|
||||||
|
const moduleStart = sanitizedCode.indexOf(modulePrefix);
|
||||||
|
if(moduleStart>=0){
|
||||||
|
sanitizedCode = sanitizedCode.slice(moduleStart+modulePrefix.length);
|
||||||
|
}
|
||||||
|
// Filter out any sourceMapping url that may have been added
|
||||||
|
const sourceMapRE = /\/\/# sourceMappingURL=(.+)/.exec(sanitizedCode);
|
||||||
|
if(sourceMapRE){
|
||||||
|
sanitizedCode = sanitizedCode.slice(0,sourceMapRE.index)+sanitizedCode.slice(sourceMapRE.index+sourceMapRE[0].length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode into a url that we can import(...)
|
||||||
|
// const importUrl = `data:text/javascript;base64,${Buffer.from(sanitizedCode).toString('base64')}`; // Safer, but unrecognizable if this throws an error
|
||||||
|
const importUrl = `data:text/javascript,${encodeURIComponent(sanitizedCode)}`; // Due to needed encoding still hard to read, but it might at least be recognizable by the user if it throws an error
|
||||||
|
|
||||||
|
try{
|
||||||
|
let htmlJsModule = await import(importUrl);
|
||||||
|
htmlContents = htmlJsModule.default;
|
||||||
|
}catch(err){
|
||||||
|
throw new Error([
|
||||||
|
`Failed to parse resulting HTML-module. Most likely this is due to a plugin that has altered the module in such a way that we cannot easely evaluate it in NodeJS.`,
|
||||||
|
`The code we tried to evaluate:`,
|
||||||
|
sanitizedCode.split('\n').map(x=>` ${x}`).join('\n'),
|
||||||
|
`The error we got:`,
|
||||||
|
err
|
||||||
|
].join('\n'))
|
||||||
|
// TODO: We could try to fallback as follows, but the issues are likely to persist in the end result
|
||||||
|
// for(const htmlImport of htmlModule.resolved){
|
||||||
|
// if(htmlImport.referenceId) {
|
||||||
|
// const fileName = this.getFileName(htmlImport.referenceId);
|
||||||
|
// htmlImport.reference.set(fileName);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// serialized = serializeHtml(htmlModule.document);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emitFile({
|
||||||
|
type: 'asset',
|
||||||
|
name: htmlModule.name,
|
||||||
|
fileName: chunk.fileName,
|
||||||
|
source: htmlContents,
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
throw new Error('something went wrong...');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
export const test = ()=>{
|
||||||
|
return `I'm "annoying" ${"in case we need to test \`string\` escaping."}. Hence this files \'tries\' to include all allowed forms of 'it'`;
|
||||||
|
}
|
||||||
|
console.log(test());
|
||||||
7
test/basic/fixtures/index.html
Normal file
7
test/basic/fixtures/index.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="./batman.js" type="module"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,2 +0,0 @@
|
|||||||
// eslint-disable-next-line
|
|
||||||
import style from './joker.css';
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
// eslint-disable-next-line
|
|
||||||
import * as batman from './batman.js';
|
|
||||||
@ -1,357 +1,58 @@
|
|||||||
# Snapshot report for `test/test.js`
|
# Snapshot report for `test/basic/test.js`
|
||||||
|
|
||||||
The actual snapshot is saved in `test.js.snap`.
|
The actual snapshot is saved in `test.js.snap`.
|
||||||
|
|
||||||
Generated by [AVA](https://avajs.dev).
|
Generated by [AVA](https://avajs.dev).
|
||||||
|
|
||||||
## default options
|
## simple
|
||||||
|
|
||||||
> Snapshot 1
|
> Snapshot 1
|
||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
code: `(function (factory) {␊
|
code: `const test = ()=>{␊
|
||||||
typeof define === 'function' && define.amd ? define(factory) :␊
|
return \`I'm "annoying" ${"in case we need to test \\\`string\\\` escaping."}. Hence this files \\'tries\\' to include all allowed forms of 'it'\`;␊
|
||||||
factory();␊
|
};␊
|
||||||
})((function () { 'use strict';␊
|
console.log(test());␊
|
||||||
␊
|
␊
|
||||||
␊
|
export { test };␊
|
||||||
␊
|
//# sourceMappingURL=batman-9dbe0e1d.js.map␊
|
||||||
}));␊
|
|
||||||
`,
|
`,
|
||||||
fileName: 'batman.js',
|
fileName: 'batman-9dbe0e1d.js',
|
||||||
map: null,
|
map: SourceMap {
|
||||||
|
file: 'batman-9dbe0e1d.js',
|
||||||
|
mappings: 'AAAY,MAAC,IAAI,GAAG,IAAI;AACxB,IAAI,OAAO,CAAC,eAAe,EAAE,8CAA8C,CAAC,iEAAiE,CAAC,CAAC;AAC/I,EAAC;AACD,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;;',
|
||||||
|
names: [],
|
||||||
|
sources: [
|
||||||
|
'../batman.js',
|
||||||
|
],
|
||||||
|
sourcesContent: [
|
||||||
|
`export const test = ()=>{␊
|
||||||
|
return \`I'm "annoying" ${"in case we need to test \\\`string\\\` escaping."}. Hence this files \\'tries\\' to include all allowed forms of 'it'\`;␊
|
||||||
|
}␊
|
||||||
|
console.log(test());␊
|
||||||
|
`,
|
||||||
|
],
|
||||||
|
version: 3,
|
||||||
|
},
|
||||||
source: undefined,
|
source: undefined,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
code: undefined,
|
||||||
|
fileName: 'batman-9dbe0e1d.js.map',
|
||||||
|
map: undefined,
|
||||||
|
source: '{"version":3,"file":"batman-9dbe0e1d.js","sources":["../batman.js"],"sourcesContent":["export const test = ()=>{\\n return `I\'m \\"annoying\\" ${\\"in case we need to test \\\\`string\\\\` escaping.\\"}. Hence this files \\\\\'tries\\\\\' to include all allowed forms of \'it\'`;\\n}\\nconsole.log(test());\\n"],"names":[],"mappings":"AAAY,MAAC,IAAI,GAAG,IAAI;AACxB,IAAI,OAAO,CAAC,eAAe,EAAE,8CAA8C,CAAC,iEAAiE,CAAC,CAAC;AAC/I,EAAC;AACD,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;;"}',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
code: undefined,
|
code: undefined,
|
||||||
fileName: 'index.html',
|
fileName: 'index.html',
|
||||||
map: undefined,
|
map: undefined,
|
||||||
source: `␊
|
source: `<html><head>␊
|
||||||
<!doctype html>␊
|
</head>␊
|
||||||
<html lang="en">␊
|
<body>␊
|
||||||
<head>␊
|
<script src="batman-9dbe0e1d.js" type="module"></script>␊
|
||||||
<meta charset="utf-8">␊
|
|
||||||
<title>Rollup Bundle</title>␊
|
|
||||||
␊
|
␊
|
||||||
</head>␊
|
␊
|
||||||
<body>␊
|
</body></html>`,
|
||||||
<script src="batman.js"></script>␊
|
|
||||||
</body>␊
|
|
||||||
</html>`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
## options
|
|
||||||
|
|
||||||
> Snapshot 1
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: `(function (factory) {␊
|
|
||||||
typeof define === 'function' && define.amd ? define(factory) :␊
|
|
||||||
factory();␊
|
|
||||||
})((function () { 'use strict';␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
}));␊
|
|
||||||
`,
|
|
||||||
fileName: 'batman.js',
|
|
||||||
map: null,
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'batman.html',
|
|
||||||
map: undefined,
|
|
||||||
source: `␊
|
|
||||||
<!doctype html>␊
|
|
||||||
<html lang="en">␊
|
|
||||||
<head>␊
|
|
||||||
<meta charset="utf-8">␊
|
|
||||||
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width">␊
|
|
||||||
<title>Batcave</title>␊
|
|
||||||
␊
|
|
||||||
</head>␊
|
|
||||||
<body>␊
|
|
||||||
<script src="batcave/batman.js"></script>␊
|
|
||||||
</body>␊
|
|
||||||
</html>`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
## iife
|
|
||||||
|
|
||||||
> Snapshot 1
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: `(function () {␊
|
|
||||||
'use strict';␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
})();␊
|
|
||||||
`,
|
|
||||||
fileName: 'batman.js',
|
|
||||||
map: null,
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'index.html',
|
|
||||||
map: undefined,
|
|
||||||
source: `␊
|
|
||||||
<!doctype html>␊
|
|
||||||
<html lang="en">␊
|
|
||||||
<head>␊
|
|
||||||
<meta charset="utf-8">␊
|
|
||||||
<title>Rollup Bundle</title>␊
|
|
||||||
␊
|
|
||||||
</head>␊
|
|
||||||
<body>␊
|
|
||||||
<script src="batman.js"></script>␊
|
|
||||||
</body>␊
|
|
||||||
</html>`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
## esm
|
|
||||||
|
|
||||||
> Snapshot 1
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: `␊
|
|
||||||
`,
|
|
||||||
fileName: 'batman.js',
|
|
||||||
map: null,
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'index.html',
|
|
||||||
map: undefined,
|
|
||||||
source: `␊
|
|
||||||
<!doctype html>␊
|
|
||||||
<html lang="en">␊
|
|
||||||
<head>␊
|
|
||||||
<meta charset="utf-8">␊
|
|
||||||
<title>Rollup Bundle</title>␊
|
|
||||||
␊
|
|
||||||
</head>␊
|
|
||||||
<body>␊
|
|
||||||
<script src="batman.js" type="module"></script>␊
|
|
||||||
</body>␊
|
|
||||||
</html>`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
## unsupported output format
|
|
||||||
|
|
||||||
> Snapshot 1
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: `'use strict';␊
|
|
||||||
␊
|
|
||||||
`,
|
|
||||||
fileName: 'batman.js',
|
|
||||||
map: null,
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'index.html',
|
|
||||||
map: undefined,
|
|
||||||
source: `␊
|
|
||||||
<!doctype html>␊
|
|
||||||
<html lang="en">␊
|
|
||||||
<head>␊
|
|
||||||
<meta charset="utf-8">␊
|
|
||||||
<title>Rollup Bundle</title>␊
|
|
||||||
␊
|
|
||||||
</head>␊
|
|
||||||
<body>␊
|
|
||||||
<script src="batman.js" type="module"></script>␊
|
|
||||||
</body>␊
|
|
||||||
</html>`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
> Snapshot 2
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: 'EMPTY_BUNDLE',
|
|
||||||
message: 'Generated an empty chunk: "batman".',
|
|
||||||
names: [
|
|
||||||
'batman',
|
|
||||||
],
|
|
||||||
toString: Function {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'PLUGIN_WARNING',
|
|
||||||
message: 'plugin-html: The output format \'cjs\' is not directly supported. A custom `template` is probably required. Supported formats include: es, esm, iife, umd',
|
|
||||||
plugin: 'html',
|
|
||||||
toString: Function {},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
## css
|
|
||||||
|
|
||||||
> Snapshot 1
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: `(function (factory) {␊
|
|
||||||
typeof define === 'function' && define.amd ? define(factory) :␊
|
|
||||||
factory();␊
|
|
||||||
})((function () { 'use strict';␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
}));␊
|
|
||||||
`,
|
|
||||||
fileName: 'joker.js',
|
|
||||||
map: null,
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'joker.css',
|
|
||||||
map: undefined,
|
|
||||||
source: Buffer @Uint8Array [
|
|
||||||
2a207b20 77696474 683a2031 3030253b 207d0a
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'index.html',
|
|
||||||
map: undefined,
|
|
||||||
source: `␊
|
|
||||||
<!doctype html>␊
|
|
||||||
<html lang="en">␊
|
|
||||||
<head>␊
|
|
||||||
<meta charset="utf-8">␊
|
|
||||||
<title>Rollup Bundle</title>␊
|
|
||||||
<link href="joker.css" rel="stylesheet">␊
|
|
||||||
</head>␊
|
|
||||||
<body>␊
|
|
||||||
<script src="joker.js" type="module"></script>␊
|
|
||||||
</body>␊
|
|
||||||
</html>`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
## attributes
|
|
||||||
|
|
||||||
> Snapshot 1
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: `(function (factory) {␊
|
|
||||||
typeof define === 'function' && define.amd ? define(factory) :␊
|
|
||||||
factory();␊
|
|
||||||
})((function () { 'use strict';␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
}));␊
|
|
||||||
`,
|
|
||||||
fileName: 'joker.js',
|
|
||||||
map: null,
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'joker.css',
|
|
||||||
map: undefined,
|
|
||||||
source: Buffer @Uint8Array [
|
|
||||||
2a207b20 77696474 683a2031 3030253b 207d0a
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'index.html',
|
|
||||||
map: undefined,
|
|
||||||
source: `␊
|
|
||||||
<!doctype html>␊
|
|
||||||
<html batsignal="on" lang="bat">␊
|
|
||||||
<head>␊
|
|
||||||
<meta charset="utf-8">␊
|
|
||||||
<title>Rollup Bundle</title>␊
|
|
||||||
<link href="joker.css" rel="stylesheet" data-vilian="joker">␊
|
|
||||||
</head>␊
|
|
||||||
<body>␊
|
|
||||||
<script src="joker.js" defer="true"></script>␊
|
|
||||||
</body>␊
|
|
||||||
</html>`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
## imports
|
|
||||||
|
|
||||||
> Snapshot 1
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: `(function (factory) {␊
|
|
||||||
typeof define === 'function' && define.amd ? define(factory) :␊
|
|
||||||
factory();␊
|
|
||||||
})((function () { 'use strict';␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
}));␊
|
|
||||||
`,
|
|
||||||
fileName: 'robin.js',
|
|
||||||
map: null,
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'index.html',
|
|
||||||
map: undefined,
|
|
||||||
source: `␊
|
|
||||||
<!doctype html>␊
|
|
||||||
<html lang="en">␊
|
|
||||||
<head>␊
|
|
||||||
<meta charset="utf-8">␊
|
|
||||||
<title>Rollup Bundle</title>␊
|
|
||||||
␊
|
|
||||||
</head>␊
|
|
||||||
<body>␊
|
|
||||||
<script src="robin.js" type="module"></script>␊
|
|
||||||
</body>␊
|
|
||||||
</html>`,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
## template
|
|
||||||
|
|
||||||
> Snapshot 1
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: `(function (factory) {␊
|
|
||||||
typeof define === 'function' && define.amd ? define(factory) :␊
|
|
||||||
factory();␊
|
|
||||||
})((function () { 'use strict';␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
}));␊
|
|
||||||
`,
|
|
||||||
fileName: 'batman.js',
|
|
||||||
map: null,
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'index.html',
|
|
||||||
map: undefined,
|
|
||||||
source: '<html><body><main></main></body></html>',
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
Binary file not shown.
@ -2,123 +2,36 @@ import {join, dirname} from "node:path";
|
|||||||
|
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
import { rollup } from "rollup";
|
import { rollup } from "rollup";
|
||||||
import css from "rollup-plugin-postcss";
|
import {debugPrintOutput, getCode} from "../util/test.js";
|
||||||
|
|
||||||
import { getCode } from "../util/test.js";
|
|
||||||
|
|
||||||
import html from "../../src/index.ts";
|
import html from "../../src/index.ts";
|
||||||
|
|
||||||
// const read = (file = 'index.html') => readFileSync(join('output/', file), 'utf-8');
|
const output = {
|
||||||
|
dir: 'output', // Output all files
|
||||||
const output = { dir: 'output', format: 'umd' };
|
format: 'es', // iifi and cjs should be added to tests
|
||||||
|
sourcemap: true,// Test if #sourcemapUrl is not accidentally included in the html-output
|
||||||
|
};
|
||||||
|
|
||||||
import {fileURLToPath} from "node:url";
|
import {fileURLToPath} from "node:url";
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
process.chdir(join(__dirname, 'fixtures'));
|
process.chdir(join(__dirname, 'fixtures'));
|
||||||
|
|
||||||
test.serial('default options', async (t) => {
|
|
||||||
const bundle = await rollup({
|
|
||||||
input: 'batman.js',
|
|
||||||
plugins: [html()]
|
|
||||||
});
|
|
||||||
const code = await getCode(bundle, output, true);
|
|
||||||
t.snapshot(code);
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('options', async (t) => {
|
test.serial('simple', async (t) => {
|
||||||
const bundle = await rollup({
|
const bundle = await rollup({
|
||||||
input: 'batman.js',
|
input: 'index.html',
|
||||||
plugins: [
|
plugins: [
|
||||||
html({
|
html({
|
||||||
fileName: 'batman.html',
|
}),
|
||||||
publicPath: 'batcave/',
|
|
||||||
title: 'Batcave',
|
|
||||||
meta: [
|
|
||||||
{ charset: 'utf-8' },
|
|
||||||
{ name: 'viewport', content: 'minimum-scale=1, initial-scale=1, width=device-width' }
|
|
||||||
]
|
|
||||||
})
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
const code = await getCode(bundle, output, true);
|
const code = await getCode(bundle, output, true);
|
||||||
|
debugPrintOutput('simple',code);
|
||||||
t.snapshot(code);
|
t.snapshot(code);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.serial('iife', async (t) => {
|
// TODO various parameters
|
||||||
const bundle = await rollup({
|
// - format: cjs, iifi, ...
|
||||||
input: 'batman.js',
|
// - sourcemap: inline, false, (and the various exotic sourcemap options)
|
||||||
plugins: [html()]
|
// Watch mode tests would be its own dir
|
||||||
});
|
// ...
|
||||||
const code = await getCode(bundle, { dir: 'output', format: 'iife' }, true);
|
|
||||||
t.snapshot(code);
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('esm', async (t) => {
|
|
||||||
const bundle = await rollup({
|
|
||||||
input: 'batman.js',
|
|
||||||
plugins: [html()]
|
|
||||||
});
|
|
||||||
const code = await getCode(bundle, { dir: 'output', format: 'es' }, true);
|
|
||||||
t.snapshot(code);
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('unsupported output format', async (t) => {
|
|
||||||
const warnings = [];
|
|
||||||
const bundle = await rollup({
|
|
||||||
input: 'batman.js',
|
|
||||||
onwarn: (warning) => warnings.push(warning),
|
|
||||||
plugins: [html()]
|
|
||||||
});
|
|
||||||
const code = await getCode(bundle, { dir: 'output', format: 'cjs' }, true);
|
|
||||||
t.snapshot(code);
|
|
||||||
t.snapshot(warnings);
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('css', async (t) => {
|
|
||||||
const bundle = await rollup({
|
|
||||||
input: 'joker.js',
|
|
||||||
plugins: [css({ extract: true }), html()]
|
|
||||||
});
|
|
||||||
const code = await getCode(bundle, output, true);
|
|
||||||
t.snapshot(code);
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('attributes', async (t) => {
|
|
||||||
const bundle = await rollup({
|
|
||||||
input: 'joker.js',
|
|
||||||
plugins: [
|
|
||||||
css({ extract: true }),
|
|
||||||
html({
|
|
||||||
attributes: {
|
|
||||||
html: { batsignal: 'on', lang: 'bat' },
|
|
||||||
link: { 'data-vilian': 'joker' },
|
|
||||||
script: { defer: true }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
});
|
|
||||||
const code = await getCode(bundle, output, true);
|
|
||||||
t.snapshot(code);
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('imports', async (t) => {
|
|
||||||
const bundle = await rollup({
|
|
||||||
input: 'robin.js',
|
|
||||||
plugins: [html()]
|
|
||||||
});
|
|
||||||
const code = await getCode(bundle, output, true);
|
|
||||||
t.snapshot(code);
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('template', async (t) => {
|
|
||||||
const bundle = await rollup({
|
|
||||||
input: 'batman.js',
|
|
||||||
plugins: [
|
|
||||||
html({
|
|
||||||
transform: () => '<html><body><main></main></body></html>'
|
|
||||||
})
|
|
||||||
]
|
|
||||||
});
|
|
||||||
const code = await getCode(bundle, output, true);
|
|
||||||
t.snapshot(code);
|
|
||||||
});
|
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
export const notSoIifi = ()=>{
|
|
||||||
return `I'm "annoying" ${"in case we need to test \`string\` escaping.''"}`;
|
|
||||||
}
|
|
||||||
console.log(notSoIifi());
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
# Snapshot report for `test/hbs/test.js`
|
|
||||||
|
|
||||||
The actual snapshot is saved in `test.js.snap`.
|
|
||||||
|
|
||||||
Generated by [AVA](https://avajs.dev).
|
|
||||||
|
|
||||||
## handlebars
|
|
||||||
|
|
||||||
> Snapshot 1
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
code: `<html><head>␊
|
|
||||||
<meta data-test="a">␊
|
|
||||||
</head>␊
|
|
||||||
<body>␊
|
|
||||||
<script src="batman-f8ac73ff.js" type="module"></script>␊
|
|
||||||
␊
|
|
||||||
␊
|
|
||||||
</body></html>␊
|
|
||||||
//# sourceMappingURL=index.html.map␊
|
|
||||||
`,
|
|
||||||
fileName: 'index.html',
|
|
||||||
map: SourceMap {
|
|
||||||
file: 'index.html',
|
|
||||||
mappings: '',
|
|
||||||
names: [],
|
|
||||||
sources: [],
|
|
||||||
sourcesContent: [],
|
|
||||||
version: 3,
|
|
||||||
},
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: `const notSoIifi = ()=>{␊
|
|
||||||
return \`I'm "annoying" ${"in case we need to test \\\`string\\\` escaping.''"}\`;␊
|
|
||||||
};␊
|
|
||||||
console.log(notSoIifi());␊
|
|
||||||
␊
|
|
||||||
export { notSoIifi };␊
|
|
||||||
//# sourceMappingURL=batman-f8ac73ff.js.map␊
|
|
||||||
`,
|
|
||||||
fileName: 'batman-f8ac73ff.js',
|
|
||||||
map: SourceMap {
|
|
||||||
file: 'batman-f8ac73ff.js',
|
|
||||||
mappings: 'AAAY,MAAC,SAAS,GAAG,IAAI;AAC7B,IAAI,OAAO,CAAC,eAAe,EAAE,gDAAgD,CAAC,CAAC,CAAC;AAChF,EAAC;AACD,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;;;;',
|
|
||||||
names: [],
|
|
||||||
sources: [
|
|
||||||
'../batman.js',
|
|
||||||
],
|
|
||||||
sourcesContent: [
|
|
||||||
`export const notSoIifi = ()=>{␊
|
|
||||||
return \`I'm "annoying" ${"in case we need to test \\\`string\\\` escaping.''"}\`;␊
|
|
||||||
}␊
|
|
||||||
console.log(notSoIifi());␊
|
|
||||||
`,
|
|
||||||
],
|
|
||||||
version: 3,
|
|
||||||
},
|
|
||||||
source: undefined,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'batman-f8ac73ff.js.map',
|
|
||||||
map: undefined,
|
|
||||||
source: '{"version":3,"file":"batman-f8ac73ff.js","sources":["../batman.js"],"sourcesContent":["export const notSoIifi = ()=>{\\n return `I\'m \\"annoying\\" ${\\"in case we need to test \\\\`string\\\\` escaping.\'\'\\"}`;\\n}\\nconsole.log(notSoIifi());\\n"],"names":[],"mappings":"AAAY,MAAC,SAAS,GAAG,IAAI;AAC7B,IAAI,OAAO,CAAC,eAAe,EAAE,gDAAgD,CAAC,CAAC,CAAC;AAChF,EAAC;AACD,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;;;;"}',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: undefined,
|
|
||||||
fileName: 'index.html.map',
|
|
||||||
map: undefined,
|
|
||||||
source: '{"version":3,"file":"index.html","sources":[],"sourcesContent":[],"names":[],"mappings":""}',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
Binary file not shown.
4
test/live-reload/fixtures/batman.js
Normal file
4
test/live-reload/fixtures/batman.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const test = ()=>{
|
||||||
|
return `I'm "annoying" ${"in case we need to test \`string\` escaping."}. Hence this files \'tries\' to include all allowed forms of 'it'`;
|
||||||
|
}
|
||||||
|
console.log(test());
|
||||||
7
test/live-reload/fixtures/index.html
Normal file
7
test/live-reload/fixtures/index.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="./batman.js" type="module"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
60
test/live-reload/snapshots/test.js.md
Normal file
60
test/live-reload/snapshots/test.js.md
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Snapshot report for `test/live-reload/test.js`
|
||||||
|
|
||||||
|
The actual snapshot is saved in `test.js.snap`.
|
||||||
|
|
||||||
|
Generated by [AVA](https://avajs.dev).
|
||||||
|
|
||||||
|
## live-reload
|
||||||
|
|
||||||
|
> Snapshot 1
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
code: `␊
|
||||||
|
(function(l, r) { if (!l || l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (self.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(self.document);␊
|
||||||
|
const test = ()=>{␊
|
||||||
|
return \`I'm "annoying" ${"in case we need to test \\\`string\\\` escaping."}. Hence this files \\'tries\\' to include all allowed forms of 'it'\`;␊
|
||||||
|
};␊
|
||||||
|
console.log(test());␊
|
||||||
|
␊
|
||||||
|
export { test };␊
|
||||||
|
//# sourceMappingURL=batman-1a5fc364.js.map␊
|
||||||
|
`,
|
||||||
|
fileName: 'batman-1a5fc364.js',
|
||||||
|
map: SourceMap {
|
||||||
|
file: 'batman-1a5fc364.js',
|
||||||
|
mappings: ';;AAAY,MAAC,IAAI,GAAG,IAAI;AACxB,IAAI,OAAO,CAAC,eAAe,EAAE,8CAA8C,CAAC,iEAAiE,CAAC,CAAC;AAC/I,EAAC;AACD,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;;',
|
||||||
|
names: [],
|
||||||
|
sources: [
|
||||||
|
'../batman.js',
|
||||||
|
],
|
||||||
|
sourcesContent: [
|
||||||
|
`export const test = ()=>{␊
|
||||||
|
return \`I'm "annoying" ${"in case we need to test \\\`string\\\` escaping."}. Hence this files \\'tries\\' to include all allowed forms of 'it'\`;␊
|
||||||
|
}␊
|
||||||
|
console.log(test());␊
|
||||||
|
`,
|
||||||
|
],
|
||||||
|
version: 3,
|
||||||
|
},
|
||||||
|
source: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: undefined,
|
||||||
|
fileName: 'batman-1a5fc364.js.map',
|
||||||
|
map: undefined,
|
||||||
|
source: '{"version":3,"file":"batman-1a5fc364.js","sources":["../batman.js"],"sourcesContent":["export const test = ()=>{\\n return `I\'m \\"annoying\\" ${\\"in case we need to test \\\\`string\\\\` escaping.\\"}. Hence this files \\\\\'tries\\\\\' to include all allowed forms of \'it\'`;\\n}\\nconsole.log(test());\\n"],"names":[],"mappings":";;AAAY,MAAC,IAAI,GAAG,IAAI;AACxB,IAAI,OAAO,CAAC,eAAe,EAAE,8CAA8C,CAAC,iEAAiE,CAAC,CAAC;AAC/I,EAAC;AACD,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;;"}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: undefined,
|
||||||
|
fileName: 'index.html',
|
||||||
|
map: undefined,
|
||||||
|
source: `<html><head>␊
|
||||||
|
</head>␊
|
||||||
|
<body>␊
|
||||||
|
<script src="batman-1a5fc364.js" type="module"></script>␊
|
||||||
|
␊
|
||||||
|
␊
|
||||||
|
</body></html>`,
|
||||||
|
},
|
||||||
|
]
|
||||||
BIN
test/live-reload/snapshots/test.js.snap
Normal file
BIN
test/live-reload/snapshots/test.js.snap
Normal file
Binary file not shown.
42
test/live-reload/test.js
Normal file
42
test/live-reload/test.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import {join, dirname} from "node:path";
|
||||||
|
|
||||||
|
import test from "ava";
|
||||||
|
import {rollup} from "rollup";
|
||||||
|
import liveReload from "rollup-plugin-livereload";
|
||||||
|
import {debugPrintOutput, getCode} from "../util/test.js";
|
||||||
|
|
||||||
|
import html from "../../src/index.ts";
|
||||||
|
|
||||||
|
const output = {
|
||||||
|
dir: 'output', // Output all files
|
||||||
|
format: 'es', // iifi and cjs should be added to tests
|
||||||
|
sourcemap: true,// Test if #sourcemapUrl is not accidentally included in the html-output
|
||||||
|
};
|
||||||
|
|
||||||
|
import {fileURLToPath} from "node:url";
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
process.chdir(join(__dirname, 'fixtures'));
|
||||||
|
|
||||||
|
|
||||||
|
test.serial('live-reload', async (t) => {
|
||||||
|
const bundle = await rollup({
|
||||||
|
input: 'index.html',
|
||||||
|
plugins: [
|
||||||
|
html({
|
||||||
|
}),
|
||||||
|
liveReload({
|
||||||
|
verbose: false// this oddly enough prevents it from actually starting the liveserver, which would've left the test to wait indefinatly to close
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const code = await getCode(bundle, output, true);
|
||||||
|
await bundle.close();// Make sure live-reload closes itself
|
||||||
|
debugPrintOutput('live-reload',code);
|
||||||
|
t.snapshot(code);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO various parameters
|
||||||
|
// - format: cjs, iifi, ...
|
||||||
|
// - sourcemap: inline, false, (and the various exotic sourcemap options)
|
||||||
|
// Watch mode tests would be its own dir
|
||||||
|
// ...
|
||||||
2
test/templating/fixtures/batman.js
Normal file
2
test/templating/fixtures/batman.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const b = ()=>'batman';
|
||||||
|
console.log(b());
|
||||||
3
test/templating/fixtures/icon.svg
Normal file
3
test/templating/fixtures/icon.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path style="fill:none;stroke:#00ff0d;stroke-width:5;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" d="M4.1 14.72 16 26.31 28.38 5.09"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 244 B |
8
test/templating/fixtures/index.html
Normal file
8
test/templating/fixtures/index.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="icon" href="./icon.svg">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="./batman.js" type="module"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
55
test/templating/snapshots/test.js.md
Normal file
55
test/templating/snapshots/test.js.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Snapshot report for `test/templating/test.js`
|
||||||
|
|
||||||
|
The actual snapshot is saved in `test.js.snap`.
|
||||||
|
|
||||||
|
Generated by [AVA](https://avajs.dev).
|
||||||
|
|
||||||
|
## handlebars
|
||||||
|
|
||||||
|
> Snapshot 1
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
code: `const b = ()=>'batman';␊
|
||||||
|
console.log(b());␊
|
||||||
|
␊
|
||||||
|
export { b };␊
|
||||||
|
//# sourceMappingURL=batman-c7fa228c.js.map␊
|
||||||
|
`,
|
||||||
|
fileName: 'batman-c7fa228c.js',
|
||||||
|
map: SourceMap {
|
||||||
|
file: 'batman-c7fa228c.js',
|
||||||
|
mappings: 'AAAY,MAAC,CAAC,GAAG,IAAI,SAAS;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;;;',
|
||||||
|
names: [],
|
||||||
|
sources: [
|
||||||
|
'../batman.js',
|
||||||
|
],
|
||||||
|
sourcesContent: [
|
||||||
|
`export const b = ()=>'batman';␊
|
||||||
|
console.log(b());␊
|
||||||
|
`,
|
||||||
|
],
|
||||||
|
version: 3,
|
||||||
|
},
|
||||||
|
source: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: undefined,
|
||||||
|
fileName: 'batman-c7fa228c.js.map',
|
||||||
|
map: undefined,
|
||||||
|
source: '{"version":3,"file":"batman-c7fa228c.js","sources":["../batman.js"],"sourcesContent":["export const b = ()=>\'batman\';\\nconsole.log(b());\\n"],"names":[],"mappings":"AAAY,MAAC,CAAC,GAAG,IAAI,SAAS;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;;;"}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: undefined,
|
||||||
|
fileName: 'index.html',
|
||||||
|
map: undefined,
|
||||||
|
source: `<html><head>␊
|
||||||
|
<meta data-test="a">␊
|
||||||
|
</head>␊
|
||||||
|
<body>␊
|
||||||
|
<script src="batman-c7fa228c.js" type="module"></script>␊
|
||||||
|
␊
|
||||||
|
␊
|
||||||
|
</body></html>`,
|
||||||
|
},
|
||||||
|
]
|
||||||
BIN
test/templating/snapshots/test.js.snap
Normal file
BIN
test/templating/snapshots/test.js.snap
Normal file
Binary file not shown.
@ -3,7 +3,7 @@ import {join, dirname} from "node:path";
|
|||||||
import test from "ava";
|
import test from "ava";
|
||||||
import { rollup } from "rollup";
|
import { rollup } from "rollup";
|
||||||
|
|
||||||
import { getCode } from "../util/test.js";
|
import {debugPrintOutput, getCode} from "../util/test.js";
|
||||||
|
|
||||||
import html from "../../src/index.ts";
|
import html from "../../src/index.ts";
|
||||||
import handlebars from "handlebars";
|
import handlebars from "handlebars";
|
||||||
@ -14,24 +14,30 @@ const output = {
|
|||||||
sourcemap: true,// Test if #sourcemapUrl is not accidentally included in the html-output
|
sourcemap: true,// Test if #sourcemapUrl is not accidentally included in the html-output
|
||||||
};
|
};
|
||||||
|
|
||||||
import {readFile} from "node:fs/promises";
|
|
||||||
import {fileURLToPath} from "node:url";
|
import {fileURLToPath} from "node:url";
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
process.chdir(join(__dirname, 'fixtures'));
|
process.chdir(join(__dirname, 'fixtures'));
|
||||||
|
|
||||||
|
|
||||||
test.serial('handlebars', async (t) => {
|
test.serial('handlebars', async (t) => {
|
||||||
const template = await readFile('index.hbs', {encoding: "utf-8"});
|
|
||||||
const bundle = await rollup({
|
const bundle = await rollup({
|
||||||
input: 'index.hbs',
|
input: 'index.hbs',
|
||||||
plugins: [
|
plugins: [
|
||||||
html({
|
html({
|
||||||
// Should we define an output template here?!
|
transform(src){
|
||||||
transform(ctx){
|
return handlebars.compile(src)({a:'a'})
|
||||||
return handlebars.compile(template)({a:'a'})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
const code = await getCode(bundle, output, true);
|
const code = await getCode(bundle, output, true);
|
||||||
|
debugPrintOutput('handlebars',code);
|
||||||
t.snapshot(code);
|
t.snapshot(code);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// TODO various parameters
|
||||||
|
// - format: cjs, iifi, ...
|
||||||
|
// - sourcemap: inline, false, (and the various exotic sourcemap options)
|
||||||
|
// Watch mode tests would be its own dir
|
||||||
|
// ...
|
||||||
2
test/url-plugin/fixtures/batman.js
Normal file
2
test/url-plugin/fixtures/batman.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const b = ()=>'batman';
|
||||||
|
console.log(b());
|
||||||
3
test/url-plugin/fixtures/icon.svg
Normal file
3
test/url-plugin/fixtures/icon.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path style="fill:none;stroke:#00ff0d;stroke-width:5;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" d="M4.1 14.72 16 26.31 28.38 5.09"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 244 B |
8
test/url-plugin/fixtures/index.html
Normal file
8
test/url-plugin/fixtures/index.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="icon" href="./icon.svg">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="./batman.js" type="module"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
105
test/url-plugin/snapshots/test.js.md
Normal file
105
test/url-plugin/snapshots/test.js.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# Snapshot report for `test/url-plugin/test.js`
|
||||||
|
|
||||||
|
The actual snapshot is saved in `test.js.snap`.
|
||||||
|
|
||||||
|
Generated by [AVA](https://avajs.dev).
|
||||||
|
|
||||||
|
## copied-assets
|
||||||
|
|
||||||
|
> Snapshot 1
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
code: `const b = ()=>'batman';␊
|
||||||
|
console.log(b());␊
|
||||||
|
␊
|
||||||
|
export { b };␊
|
||||||
|
//# sourceMappingURL=batman-c7fa228c.js.map␊
|
||||||
|
`,
|
||||||
|
fileName: 'batman-c7fa228c.js',
|
||||||
|
map: SourceMap {
|
||||||
|
file: 'batman-c7fa228c.js',
|
||||||
|
mappings: 'AAAY,MAAC,CAAC,GAAG,IAAI,SAAS;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;;;',
|
||||||
|
names: [],
|
||||||
|
sources: [
|
||||||
|
'../batman.js',
|
||||||
|
],
|
||||||
|
sourcesContent: [
|
||||||
|
`export const b = ()=>'batman';␊
|
||||||
|
console.log(b());␊
|
||||||
|
`,
|
||||||
|
],
|
||||||
|
version: 3,
|
||||||
|
},
|
||||||
|
source: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: undefined,
|
||||||
|
fileName: 'batman-c7fa228c.js.map',
|
||||||
|
map: undefined,
|
||||||
|
source: '{"version":3,"file":"batman-c7fa228c.js","sources":["../batman.js"],"sourcesContent":["export const b = ()=>\'batman\';\\nconsole.log(b());\\n"],"names":[],"mappings":"AAAY,MAAC,CAAC,GAAG,IAAI,SAAS;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;;;"}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: undefined,
|
||||||
|
fileName: 'index.html',
|
||||||
|
map: undefined,
|
||||||
|
source: `<html><head>␊
|
||||||
|
<link rel="icon" href="fb585fdb6db313c9.svg">␊
|
||||||
|
</head>␊
|
||||||
|
<body>␊
|
||||||
|
<script src="batman-c7fa228c.js" type="module"></script>␊
|
||||||
|
␊
|
||||||
|
␊
|
||||||
|
</body></html>`,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
## inlined-assets
|
||||||
|
|
||||||
|
> Snapshot 1
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
code: `const b = ()=>'batman';␊
|
||||||
|
console.log(b());␊
|
||||||
|
␊
|
||||||
|
export { b };␊
|
||||||
|
//# sourceMappingURL=batman-c7fa228c.js.map␊
|
||||||
|
`,
|
||||||
|
fileName: 'batman-c7fa228c.js',
|
||||||
|
map: SourceMap {
|
||||||
|
file: 'batman-c7fa228c.js',
|
||||||
|
mappings: 'AAAY,MAAC,CAAC,GAAG,IAAI,SAAS;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;;;',
|
||||||
|
names: [],
|
||||||
|
sources: [
|
||||||
|
'../batman.js',
|
||||||
|
],
|
||||||
|
sourcesContent: [
|
||||||
|
`export const b = ()=>'batman';␊
|
||||||
|
console.log(b());␊
|
||||||
|
`,
|
||||||
|
],
|
||||||
|
version: 3,
|
||||||
|
},
|
||||||
|
source: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: undefined,
|
||||||
|
fileName: 'batman-c7fa228c.js.map',
|
||||||
|
map: undefined,
|
||||||
|
source: '{"version":3,"file":"batman-c7fa228c.js","sources":["../batman.js"],"sourcesContent":["export const b = ()=>\'batman\';\\nconsole.log(b());\\n"],"names":[],"mappings":"AAAY,MAAC,CAAC,GAAG,IAAI,SAAS;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;;;"}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: undefined,
|
||||||
|
fileName: 'index.html',
|
||||||
|
map: undefined,
|
||||||
|
source: `<html><head>␊
|
||||||
|
<link rel="icon" href="data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2032%2032%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20style%3D%22fill%3Anone%3Bstroke%3A%2300ff0d%3Bstroke-width%3A5%3Bstroke-linecap%3Asquare%3Bstroke-linejoin%3Amiter%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M4.1%2014.72%2016%2026.31%2028.38%205.09%22%2F%3E%3C%2Fsvg%3E">␊
|
||||||
|
</head>␊
|
||||||
|
<body>␊
|
||||||
|
<script src="batman-c7fa228c.js" type="module"></script>␊
|
||||||
|
␊
|
||||||
|
␊
|
||||||
|
</body></html>`,
|
||||||
|
},
|
||||||
|
]
|
||||||
BIN
test/url-plugin/snapshots/test.js.snap
Normal file
BIN
test/url-plugin/snapshots/test.js.snap
Normal file
Binary file not shown.
67
test/url-plugin/test.js
Normal file
67
test/url-plugin/test.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import {join, dirname} from "node:path";
|
||||||
|
|
||||||
|
import test from "ava";
|
||||||
|
import { rollup } from "rollup";
|
||||||
|
import urlPlugin from "@rollup/plugin-url";
|
||||||
|
|
||||||
|
import {debugPrintOutput, getCode} from "../util/test.js";
|
||||||
|
|
||||||
|
import html from "../../src/index.ts";
|
||||||
|
|
||||||
|
const output = {
|
||||||
|
dir: 'output', // Output all files
|
||||||
|
format: 'es', // iifi and cjs should be added to tests
|
||||||
|
sourcemap: true,// Test if #sourcemapUrl is not accidentally included in the html-output
|
||||||
|
};
|
||||||
|
|
||||||
|
import {fileURLToPath} from "node:url";
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
process.chdir(join(__dirname, 'fixtures'));
|
||||||
|
|
||||||
|
|
||||||
|
const defaultAssetInclude = [
|
||||||
|
'**/*.(png|jpg|jpeg|gif|ico|svg)',// images, svg
|
||||||
|
'**/*.(woff|woff2|eot|ttf|otf)',// fonts
|
||||||
|
'**/*.(webm|mp4)',// video
|
||||||
|
];
|
||||||
|
|
||||||
|
test.serial('copied-assets', async (t) => {
|
||||||
|
const bundle = await rollup({
|
||||||
|
input: 'index.html',
|
||||||
|
plugins: [
|
||||||
|
html({
|
||||||
|
}),
|
||||||
|
urlPlugin({
|
||||||
|
include: defaultAssetInclude,
|
||||||
|
limit: 0,// Never inline something
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const code = await getCode(bundle, output, true);
|
||||||
|
debugPrintOutput('copied-assets',code);
|
||||||
|
t.snapshot(code);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test.serial('inlined-assets', async (t) => {
|
||||||
|
const bundle = await rollup({
|
||||||
|
input: 'index.html',
|
||||||
|
plugins: [
|
||||||
|
html({
|
||||||
|
}),
|
||||||
|
urlPlugin({
|
||||||
|
include: defaultAssetInclude,
|
||||||
|
limit: Number.MAX_SAFE_INTEGER,// Always inline things
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const code = await getCode(bundle, output, true);
|
||||||
|
debugPrintOutput('inlined-assets',code);
|
||||||
|
t.snapshot(code);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO various parameters
|
||||||
|
// - format: cjs, iifi, ...
|
||||||
|
// - sourcemap: inline, false, (and the various exotic sourcemap options)
|
||||||
|
// Watch mode tests would be its own dir
|
||||||
|
// ...
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import process from "node:process";
|
import process from "node:process";
|
||||||
|
import chalk from "chalk";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import('rollup').RollupBuild} bundle
|
* @param {import('rollup').RollupBuild} bundle
|
||||||
@ -22,6 +23,35 @@ export const getCode = async (bundle, outputOptions, allFiles = false) => {
|
|||||||
return code;
|
return code;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const debugPrintOutput = async (header, files) => {
|
||||||
|
const out = [];
|
||||||
|
|
||||||
|
const headFn = chalk.bgCyan;
|
||||||
|
const headPadding = header.split('').map(x=>'#').join('');
|
||||||
|
out.push(...[
|
||||||
|
headFn(`##${headPadding}##`),
|
||||||
|
headFn(`# ${header} #`),
|
||||||
|
headFn(`##${headPadding}##`),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const fileHeadFn = chalk.blue;
|
||||||
|
const fileContentFn = chalk.blackBright;
|
||||||
|
out.push(...(files.map(file=>{
|
||||||
|
return [
|
||||||
|
fileHeadFn(`${file.fileName}:`),
|
||||||
|
fileContentFn(`${file.code??file.source}`),
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
}).flat()));
|
||||||
|
|
||||||
|
out.push(...[
|
||||||
|
headFn(`##${headPadding}##`),
|
||||||
|
]);
|
||||||
|
|
||||||
|
process.env.DEBUG? console.log(out.join('\n')) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import('rollup').RollupBuild} bundle
|
* @param {import('rollup').RollupBuild} bundle
|
||||||
* @param {import('rollup').OutputOptions} [outputOptions]
|
* @param {import('rollup').OutputOptions} [outputOptions]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user