Compare commits

...

31 Commits

Author SHA1 Message Date
github-actions[bot]
c009801164 Version Packages 2022-03-08 14:41:55 +01:00
Thomas Allmer
60310ab3dd fix: improve performance by loading sax-wasm only once 2022-03-08 14:37:31 +01:00
github-actions[bot]
db03f69210 Version Packages 2022-03-07 19:27:03 +01:00
Thomas Allmer
e6c3d274cf feat(mdjs-core): support js client as an alias to js script 2022-03-07 19:19:24 +01:00
github-actions[bot]
f9014c15a6 Version Packages 2022-03-07 18:42:20 +01:00
Thomas Allmer
7e277cd88f feat(plugins-manager): support a wrapPlugin property for adding 2022-03-07 18:35:41 +01:00
Thomas Allmer
bc6106381c chore: lock file maintainance 2022-03-06 21:05:23 +01:00
dependabot[bot]
00bf3882f6 chore(deps-dev): bump node-fetch from 2.6.1 to 2.6.7
Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.1 to 2.6.7.
- [Release notes](https://github.com/node-fetch/node-fetch/releases)
- [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.1...v2.6.7)

---
updated-dependencies:
- dependency-name: node-fetch
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-06 20:51:33 +01:00
dependabot[bot]
543e297c5b chore(deps): bump pathval from 1.1.0 to 1.1.1
Bumps [pathval](https://github.com/chaijs/pathval) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/chaijs/pathval/releases)
- [Changelog](https://github.com/chaijs/pathval/blob/master/CHANGELOG.md)
- [Commits](https://github.com/chaijs/pathval/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: pathval
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-06 20:50:48 +01:00
dependabot[bot]
70b0ce8e1c chore(deps): bump simple-get from 3.1.0 to 3.1.1
Bumps [simple-get](https://github.com/feross/simple-get) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/feross/simple-get/releases)
- [Commits](https://github.com/feross/simple-get/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: simple-get
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-06 20:50:31 +01:00
github-actions[bot]
9f8785a885 Version Packages 2022-03-06 20:46:44 +01:00
Thomas Allmer
62637a829e chore: add changeset 2022-03-06 20:44:17 +01:00
Westbrook Johnson
81c4d7bf3c Use a more recently published prism converter for rehype 2022-03-06 20:44:17 +01:00
github-actions[bot]
08181194e2 Version Packages 2022-01-31 13:45:06 +01:00
Thomas Allmer
97cb38ccb8 fix(mdjs-core): add missing slash dependency 2022-01-31 13:43:36 +01:00
github-actions[bot]
26d3de1444 Version Packages 2022-01-30 11:48:03 +01:00
Thomas Allmer
1f141058c1 fix(drawer): add export map with /define side effect import 2022-01-30 11:45:47 +01:00
github-actions[bot]
08574c9b31 Version Packages 2022-01-05 09:34:58 +01:00
gvangeest
e81b77f236 fix(mdjs-preview): separate preview and viewer theme styling 2022-01-03 18:36:09 +01:00
qa46hx
456b8e78f0 fix(mdjs-preview): add css variable to border-color of viewer 2021-12-05 13:30:28 +01:00
github-actions[bot]
0d7ea015af Version Packages 2021-11-16 18:48:20 +01:00
Thomas Allmer
445b02872f fix: update to latest lit, @open-wc, @lion packages 2021-11-16 17:07:53 +01:00
Thomas Allmer
1a599db3ed chore: lock file maintainance 2021-11-16 08:05:37 +01:00
Thomas Allmer
6b6bed5391 chore: update remark-html 2021-11-16 08:05:37 +01:00
github-actions[bot]
30eb822151 Version Packages 2021-11-11 10:11:42 +01:00
Thomas Allmer
15a82c0e4d fix: improve mdjs preview iframe security 2021-11-11 10:05:51 +01:00
github-actions[bot]
0197bee621 Version Packages 2021-10-15 19:25:11 +02:00
Thomas Allmer
5c6b9c91eb feat(mdjs-preview): Move platform and sizes settings above preview 2021-10-15 12:33:30 +02:00
Thomas Allmer
6221e5f9ea feat: mdjs support for story-code blocks 2021-10-15 12:33:30 +02:00
Jorge del Casar
06741ed729 chore: update playwright 2021-10-11 19:23:33 +02:00
Thomas Allmer
23c164c822 chore: reduce test output noise 2021-10-03 22:06:22 +02:00
59 changed files with 1743 additions and 1237 deletions

View File

@@ -8,25 +8,25 @@ First, create a fork of the [modernweb-dev/rocket](https://github.com/modernweb-
Next, clone our repository onto your computer. Next, clone our repository onto your computer.
```sh ```shell
git clone git@github.com:modernweb-dev/rocket.git git clone git@github.com:modernweb-dev/rocket.git
``` ```
Once cloning is complete, change directory to the repository. Once cloning is complete, change directory to the repository.
```sh ```shell
cd rocket cd rocket
``` ```
Now add your fork as a remote (replacing YOUR_USERNAME with your GitHub username). Now add your fork as a remote (replacing YOUR_USERNAME with your GitHub username).
```sh ```shell
git remote add fork git@github.com:<YOUR_USERNAME>/rocket.git git remote add fork git@github.com:<YOUR_USERNAME>/rocket.git
``` ```
Create a new local branch. Create a new local branch.
```sh ```shell
git checkout -b my-awesome-fix git checkout -b my-awesome-fix
``` ```
@@ -34,7 +34,7 @@ git checkout -b my-awesome-fix
Now that you have cloned the repository, ensure you have [yarn](https://classic.yarnpkg.com/lang/en/) installed, then run the following commands to set up the development environment. Now that you have cloned the repository, ensure you have [yarn](https://classic.yarnpkg.com/lang/en/) installed, then run the following commands to set up the development environment.
```sh ```shell
yarn install yarn install
``` ```
@@ -69,7 +69,7 @@ This documents your intent to release, and allows you to specify a message that
Run Run
```sh ```shell
yarn changeset yarn changeset
``` ```
@@ -92,7 +92,7 @@ Exceptions:
Commit messages must follow the [conventional commit format](https://www.conventionalcommits.org/en/v1.0.0/) Commit messages must follow the [conventional commit format](https://www.conventionalcommits.org/en/v1.0.0/)
Modern-web uses package name as scope. So for example if you fix a _terrible bug_ in the package `@web/test-runner`, the commit message should look like this: Modern-web uses package name as scope. So for example if you fix a _terrible bug_ in the package `@web/test-runner`, the commit message should look like this:
```sh ```shell
fix(test-runner): fix terrible bug fix(test-runner): fix terrible bug
``` ```
@@ -100,7 +100,7 @@ fix(test-runner): fix terrible bug
Now it's time to push your branch that contains your committed changes to your fork. Now it's time to push your branch that contains your committed changes to your fork.
```sh ```shell
git push -u fork my-awesome-fix git push -u fork my-awesome-fix
``` ```

View File

@@ -140,7 +140,7 @@ The features so far are:
It checks your final HTML output so you need to execute it after your Static Site Generator. It checks your final HTML output so you need to execute it after your Static Site Generator.
``` ```shell
npx check-html-links _site npx check-html-links _site
``` ```

View File

@@ -4,7 +4,7 @@ Use mdjs in your Eleventy site.
## Setup ## Setup
``` ```shell
npm install @rocket/eleventy-plugin-mdjs npm install @rocket/eleventy-plugin-mdjs
``` ```

View File

@@ -123,6 +123,68 @@ export const header = () => {
}; };
``` ```
```js story-code
// not defined for android
```
```js story-code
// not defined for ios
```
#### Story Code
If your preview is followed by a code blocks marked as `story-code` then those will be shown when switching between multiple platforms
````md
```js preview-story
// will be visible when platform web is selected
export const JsPreviewStory = () => html` <demo-wc-card>JS Preview Story</demo-wc-card> `;
```
```xml story-code
<!-- will be visible when platform android is selected -->
<Button
android:id="@+id/demoWcCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android Code"
style="@style/Widget.FooComponents.Demo.Wc.Card"
/>
```
```swift story-code
// will be visible when platform ios is selected
import DemoWc.Card
let card = DemoWcButton()
```
````
See it in action by opening up the code block and switching platforms
```js preview-story
// will be visible when platform web is selected
export const JsPreviewStory = () => html` <demo-wc-card>JS Preview Story</demo-wc-card> `;
```
```xml story-code
<!-- will be visible when platform android is selected -->
<Button
android:id="@+id/demoWcCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android Code"
style="@style/Widget.FooComponents.Demo.Wc.Card"
/>
```
```swift story-code
// will be visible when platform ios is selected
import DemoWc.Card
let card = DemoWcButton()
```
## Supported Systems ## Supported Systems
### Storybook ### Storybook

View File

@@ -40,6 +40,68 @@ will result in
export const foo = () => html` <demo-element></demo-element> `; export const foo = () => html` <demo-element></demo-element> `;
``` ```
```js story-code
// not defined for android
```
```js story-code
// not defined for ios
```
#### Story Code
If your preview is followed by a code blocks marked as `story-code` then those will be shown when switching between multiple platforms
````md
```js preview-story
// will be visible when platform web is selected
export const JsPreviewStory = () => html` <demo-element></demo-element> `;
```
```xml story-code
<!-- will be visible when platform android is selected -->
<Button
android:id="@+id/demoElement"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android Code"
style="@style/Widget.Demo.Element"
/>
```
```swift story-code
// will be visible when platform ios is selected
import Demo.Element
let card = DemoElement()
```
````
See it in action by opening up the code block and switching platforms
```js preview-story
// will be visible when platform web is selected
export const JsPreviewStory = () => html` <demo-element></demo-element> `;
```
```xml story-code
<!-- will be visible when platform android is selected -->
<Button
android:id="@+id/demoElement"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android Code"
style="@style/Widget.Demo.Element"
/>
```
```swift story-code
// will be visible when platform ios is selected
import Demo.Element
let card = DemoElement()
```
## HTML Story ## HTML Story
````md ````md

View File

@@ -22,7 +22,7 @@ Read the [Introducing Check HTMl Links - no more bad links](../../blog/introduci
## Installation ## Installation
``` ```shell
npm i -D check-html-links npm i -D check-html-links
``` ```

View File

@@ -112,16 +112,13 @@ addPlugin(MyClass, { otherProp: 'new name' }); // ts error
Many plugin systems require you to either execute a plugin function like in `rollup`. Many plugin systems require you to either execute a plugin function like in `rollup`.
<!-- prettier-ignore-start -->
```js ```js
import json from '@rollup/plugin-json'; import json from '@rollup/plugin-json';
/** @type {import('rocket/cli').RocketCliConfig} */ export default /** @type {import('rocket/cli').RocketCliConfig} */ ({
export default ({
plugins: [json({ preferConst: true })], plugins: [json({ preferConst: true })],
}); });
``` ```
<!-- prettier-ignore-end -->
or add it in a special way like in `eleventy` or add it in a special way like in `eleventy`
@@ -254,6 +251,18 @@ addPlugin(myPlugin, { myFlag: true }); // ts ok
addPlugin(myPlugin, { notExisting: true }); // ts error addPlugin(myPlugin, { notExisting: true }); // ts error
``` ```
Note: There is a "hidden" feature in addPlugin that if you attach a `wrapPlugin` property to the returning function it will call `wrapPlugin` on the plugin before adding it.
```js
// example auto wrap rollup plugins for @web/dev-server
import { fromRollup } from '@web/dev-server-rollup';
const userSetupFunctions = [addPlugin(json)].map(mod => {
mod.wrapPlugin = fromRollup;
return mod;
});
```
## Adjusting Plugin Options ## Adjusting Plugin Options
Adjusting options means to either Adjusting options means to either

View File

@@ -23,7 +23,7 @@ Will be ordered as `First`, `Second`,
Internally `# Foo >> Bar >> Baz ||20` gets converted to. Internally `# Foo >> Bar >> Baz ||20` gets converted to.
``` ```yml
--- ---
title: Bar: Baz title: Bar: Baz
eleventyNavigation: eleventyNavigation:

4
netlify.toml Normal file
View File

@@ -0,0 +1,4 @@
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = "default-src 'self'; script-src 'self' www.googletagmanager.com 'sha256-W6Gq+BvrdAAMbF8E7WHA7UPQxuUOfJM8E9mpKD0oihA=' 'sha256-vFU+IJ5dUUukI5Varwy49dN2d89DmFj7UNewqQv88sw='; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src 'self' data: fonts.gstatic.com;"

View File

@@ -47,7 +47,7 @@
"update-package-configs": "node scripts/update-package-configs.mjs && yarn format" "update-package-configs": "node scripts/update-package-configs.mjs && yarn format"
}, },
"devDependencies": { "devDependencies": {
"@changesets/cli": "^2.12.0", "@changesets/cli": "^2.20.0",
"@custom-elements-manifest/analyzer": "^0.4.12", "@custom-elements-manifest/analyzer": "^0.4.12",
"@open-wc/testing": "^3.0.0-next.1", "@open-wc/testing": "^3.0.0-next.1",
"@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-commonjs": "^17.0.0",
@@ -62,7 +62,7 @@
"@typescript-eslint/parser": "^4.13.0", "@typescript-eslint/parser": "^4.13.0",
"@web/test-runner": "^0.12.2", "@web/test-runner": "^0.12.2",
"@web/test-runner-commands": "^0.4.0", "@web/test-runner-commands": "^0.4.0",
"@web/test-runner-playwright": "^0.8.0", "@web/test-runner-playwright": "^0.8.8",
"cem-plugin-readme": "^0.1.3", "cem-plugin-readme": "^0.1.3",
"chai": "^4.2.0", "chai": "^4.2.0",
"concurrently": "^5.3.0", "concurrently": "^5.3.0",
@@ -75,7 +75,7 @@
"husky": "^4.3.7", "husky": "^4.3.7",
"lint-staged": "^10.5.3", "lint-staged": "^10.5.3",
"mocha": "^8.2.1", "mocha": "^8.2.1",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.7",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"onchange": "^7.1.0", "onchange": "^7.1.0",
"prettier": "^2.2.1", "prettier": "^2.2.1",
@@ -84,8 +84,6 @@
"puppeteer": "^9.0.0", "puppeteer": "^9.0.0",
"remark-emoji": "^2.1.0", "remark-emoji": "^2.1.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"rocket-preset-code-tabs": "^0.2.6",
"rocket-preset-custom-elements-manifest": "^0.1.7",
"rollup": "^2.36.1", "rollup": "^2.36.1",
"rollup-plugin-terser": "^7.0.2", "rollup-plugin-terser": "^7.0.2",
"sinon": "^9.2.3", "sinon": "^9.2.3",

View File

@@ -42,6 +42,7 @@ export function createServiceWorkerMetaConfig(userConfig = { output: {} }) {
plugin: replace, plugin: replace,
options: { options: {
'process.env.NODE_ENV': JSON.stringify(developmentMode ? 'development' : 'production'), 'process.env.NODE_ENV': JSON.stringify(developmentMode ? 'development' : 'production'),
preventAssignment: true,
}, },
}, },
{ {

View File

@@ -4,13 +4,13 @@ A fast checker for broken links/references in HTML.
## Installation ## Installation
``` ```shell
npm i -D check-html-links npm i -D check-html-links
``` ```
## Usage ## Usage
``` ```bash
npx check-html-links _site npx check-html-links _site
``` ```

View File

@@ -1,5 +1,24 @@
# @rocket/cli # @rocket/cli
## 0.10.2
### Patch Changes
- 60310ab: Improve performance by initializing sax-wasm only once even when it is running in parallel
- Updated dependencies [60310ab]
- @rocket/eleventy-rocket-nav@0.3.1
## 0.10.1
### Patch Changes
- 15a82c0: Enable including script files into the simulator via `<script src=".." mdjs-use>`
- 15a82c0: Allow only a limited set of characters for simulator includes `[a-zA-Z0-9\/\-_]`.
Notably, there is no:
- `:` to prevent `http://...` includes
- `.` so filenames as `this.is.my.js` are not supported. Also includes will be without file endings which will be added automatically
## 0.10.0 ## 0.10.0
### Minor Changes ### Minor Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@rocket/cli", "name": "@rocket/cli",
"version": "0.10.0", "version": "0.10.2",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -60,7 +60,7 @@
"@rocket/building-rollup": "^0.4.0", "@rocket/building-rollup": "^0.4.0",
"@rocket/core": "^0.1.2", "@rocket/core": "^0.1.2",
"@rocket/eleventy-plugin-mdjs-unified": "^0.6.0", "@rocket/eleventy-plugin-mdjs-unified": "^0.6.0",
"@rocket/eleventy-rocket-nav": "^0.3.0", "@rocket/eleventy-rocket-nav": "^0.3.1",
"@rollup/plugin-babel": "^5.2.2", "@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-node-resolve": "^11.0.1", "@rollup/plugin-node-resolve": "^11.0.1",
"@web/config-loader": "^0.1.3", "@web/config-loader": "^0.1.3",

View File

@@ -14,19 +14,37 @@
<script type="module"> <script type="module">
import { render } from '@mdjs/mdjs-story'; import { render } from '@mdjs/mdjs-story';
function sanitize(input, type) {
return `${document.location.origin}/${input.match(/[a-zA-Z0-9\/\-_]*/)[0]}.${type}`;
}
async function onHashChange() { async function onHashChange() {
const urlParts = new URLSearchParams(document.location.hash.substr(1)); const urlParts = new URLSearchParams(document.location.hash.substr(1));
if (urlParts.get('stylesheets')) { if (urlParts.get('stylesheets')) {
for (const stylesheet of urlParts.getAll('stylesheets')) { for (const stylesheet of urlParts.getAll('stylesheets')) {
if (!document.querySelector(`link[rel="stylesheet"][href="${stylesheet}"]`)) { const safeStylesheetUrl = sanitize(stylesheet, 'css');
if (!document.querySelector(`link[rel="stylesheet"][href="${safeStylesheetUrl}"]`)) {
const link = document.createElement('link'); const link = document.createElement('link');
link.rel = 'stylesheet'; link.rel = 'stylesheet';
link.href = stylesheet; link.href = safeStylesheetUrl;
document.head.appendChild(link); document.head.appendChild(link);
} }
} }
} }
if (urlParts.get('moduleUrls')) {
for (const moduleUrl of urlParts.getAll('moduleUrls')) {
const safeModuleUrl = sanitize(moduleUrl, 'js');
if (!document.querySelector(`script[type=module][src="${safeModuleUrl}"]`)) {
const script = document.createElement('script');
script.type = 'module';
script.src = safeModuleUrl;
document.head.appendChild(script);
}
}
}
if (urlParts.get('theme')) { if (urlParts.get('theme')) {
document.documentElement.setAttribute('theme', urlParts.get('theme')); document.documentElement.setAttribute('theme', urlParts.get('theme'));
} }
@@ -46,7 +64,8 @@
document.documentElement.removeAttribute('edge-distance'); document.documentElement.removeAttribute('edge-distance');
} }
const mod = await import(urlParts.get('story-file')); const safeStoryUrl = sanitize(urlParts.get('story-file'), 'js');
const mod = await import(safeStoryUrl);
render(mod[urlParts.get('story-key')]({ shadowRoot: document }), document.body); render(mod[urlParts.get('story-key')]({ shadowRoot: document }), document.body);
} }

View File

@@ -298,7 +298,7 @@ export class RocketCli {
async cleanup() { async cleanup() {
setComputedConfig({}); setComputedConfig({});
if (this.eleventy) { if (this.eleventy) {
this.eleventy.finish(); // this.eleventy.finish();
// await this.eleventy.stopWatch(); // await this.eleventy.stopWatch();
} }
this.stop(); this.stop();

View File

@@ -243,9 +243,9 @@ async function insertResponsiveImages(html) {
const config = getComputedConfig(); const config = getComputedConfig();
if (!isSetup) { if (!isSetup) {
await parser.prepareWasm(saxWasmBuffer); isSetup = parser.prepareWasm(saxWasmBuffer);
isSetup = true;
} }
await isSetup;
const options = { const options = {
inputPath: this.inputPath, inputPath: this.inputPath,

View File

@@ -91,86 +91,78 @@ export async function readOutput(
return text; return text;
} }
export function startOutputExist(cli, fileName) {
const outputDir = cli.config.outputDevDir;
return fs.existsSync(path.join(outputDir, fileName));
}
export function buildOutputExist(cli, fileName) {
const outputDir = cli.config.outputDir;
return fs.existsSync(path.join(outputDir, fileName));
}
/**
* @param {*} cli
* @param {string} fileName
* @param {readOutputOptions} options
*/
export async function readStartOutput(cli, fileName, options = {}) {
options.type = 'start';
return readOutput(cli, fileName, options);
}
/**
* @param {*} cli
* @param {string} fileName
* @param {readOutputOptions} options
*/
export async function readBuildOutput(cli, fileName, options = {}) {
options.type = 'build';
return readOutput(cli, fileName, options);
}
export async function getfixtureExpectedFiles(pathToDir) { export async function getfixtureExpectedFiles(pathToDir) {
const cwd = path.join(fixtureDir, pathToDir); const cwd = path.join(fixtureDir, pathToDir);
const paths = await globby('**/*', { cwd, absolute: true, dot: true }); const paths = await globby('**/*', { cwd, absolute: true, dot: true });
return paths; return paths;
} }
export async function execute(cli, configFileDir) { export async function execute(pathToConfig, { type = 'start', captureLog = false } = {}) {
let log = [];
const origLog = console.log;
if (captureLog) {
console.log = (...args) => {
log = [...log, ...args];
};
}
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
const configFileDir = path.dirname(configFile);
const cli = new RocketCli({
argv: [type, '--config-file', configFile],
});
await cli.setup(); await cli.setup();
cli.config.outputDevDir = path.join(configFileDir, '__output-dev'); cli.config.outputDevDir = path.join(configFileDir, '__output-dev');
cli.config.devServer.open = false; cli.config.devServer.open = false;
cli.config.devServer.port = 8080; cli.config.devServer.port = 8080;
cli.config.watch = false; cli.config.watch = false;
cli.config.outputDir = path.join(configFileDir, '__output'); cli.config.outputDir = path.join(configFileDir, '__output');
await fs.emptyDir(cli.config.outputDevDir);
await fs.emptyDir(cli.config.outputDir);
await cli.run(); await cli.run();
return cli;
/**
* @param {*} cli
* @param {string} fileName
* @param {readOutputOptions} options
*/
async function readOutput2(fileName, options = {}) {
options.type = type;
return readOutput(cli, fileName, options);
}
function outputExists(fileName) {
const outputDir = type === 'build' ? cli.config.outputDir : cli.config.outputDevDir;
const filePath = path.join(outputDir, fileName);
return fs.existsSync(filePath);
}
if (captureLog) {
console.log = origLog;
}
return { log, readOutput: readOutput2, cli, outputExists };
} }
export async function executeBootstrap(pathToDir) { export async function executeBootstrap(pathToDir) {
const configFileDir = path.join(fixtureDir, pathToDir.split('/').join(path.sep)); const configFileDir = path.join(fixtureDir, pathToDir.split('/').join(path.sep));
const cli = new RocketCli({ argv: ['bootstrap'] }); const cli = new RocketCli({ argv: ['bootstrap'] });
await cli.setup();
cli.config.outputDevDir = path.join(configFileDir, '__output-dev');
cli.config.devServer.open = false;
cli.config.devServer.port = 8080;
cli.config.watch = false;
cli.config.outputDir = path.join(configFileDir, '__output');
await fs.emptyDir(configFileDir); await fs.emptyDir(configFileDir);
await execute(cli, configFileDir); await cli.run();
return cli;
}
export async function executeStart(pathToConfig) { return { cli };
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
const cli = new RocketCli({
argv: ['start', '--config-file', configFile],
});
await execute(cli, path.dirname(configFile));
return cli;
}
export async function executeBuild(pathToConfig) {
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
const cli = new RocketCli({
argv: ['build', '--config-file', configFile],
});
await execute(cli, path.dirname(configFile));
return cli;
}
export async function executeLint(pathToConfig) {
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
const cli = new RocketCli({
argv: ['lint', '--config-file', configFile],
});
await execute(cli, path.dirname(configFile));
return cli;
} }
export function trimWhiteSpace(inString) { export function trimWhiteSpace(inString) {

View File

@@ -1,17 +1,11 @@
import chai from 'chai'; import chai from 'chai';
import chalk from 'chalk'; import chalk from 'chalk';
import { import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
executeBuild,
executeStart,
readBuildOutput,
readStartOutput,
setFixtureDir,
} from '@rocket/cli/test-helpers';
const { expect } = chai; const { expect } = chai;
describe('RocketCli computedConfig', () => { describe('RocketCli computedConfig', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -20,90 +14,117 @@ describe('RocketCli computedConfig', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
it('will extract a title from markdown and set first folder as section', async () => { it('will extract a title from markdown and set first folder as section', async () => {
cli = await executeStart('computed-config-fixtures/headlines/rocket.config.js'); const { cli, readOutput } = await execute(
'computed-config-fixtures/headlines/rocket.config.js',
{ captureLog: true },
);
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
const [indexTitle, indexSection] = indexHtml.split('\n'); const [indexTitle, indexSection] = indexHtml.split('\n');
expect(indexTitle).to.equal('Root'); expect(indexTitle).to.equal('Root');
expect(indexSection).to.be.undefined; expect(indexSection).to.be.undefined;
const subHtml = await readStartOutput(cli, 'sub/index.html'); const subHtml = await readOutput('sub/index.html');
const [subTitle, subSection] = subHtml.split('\n'); const [subTitle, subSection] = subHtml.split('\n');
expect(subTitle).to.equal('Root: Sub'); expect(subTitle).to.equal('Root: Sub');
expect(subSection).to.equal('sub'); expect(subSection).to.equal('sub');
const subSubHtml = await readStartOutput(cli, 'sub/subsub/index.html'); const subSubHtml = await readOutput('sub/subsub/index.html');
const [subSubTitle, subSubSection] = subSubHtml.split('\n'); const [subSubTitle, subSubSection] = subSubHtml.split('\n');
expect(subSubTitle).to.equal('Sub: SubSub'); expect(subSubTitle).to.equal('Sub: SubSub');
expect(subSubSection).to.equal('sub'); expect(subSubSection).to.equal('sub');
const sub2Html = await readStartOutput(cli, 'sub2/index.html'); const sub2Html = await readOutput('sub2/index.html');
const [sub2Title, sub2Section] = sub2Html.split('\n'); const [sub2Title, sub2Section] = sub2Html.split('\n');
expect(sub2Title).to.equal('Root: Sub2'); expect(sub2Title).to.equal('Root: Sub2');
expect(sub2Section).to.equal('sub2'); expect(sub2Section).to.equal('sub2');
const withDataHtml = await readStartOutput(cli, 'with-data/index.html'); const withDataHtml = await readOutput('with-data/index.html');
const [withDataTitle, withDataSection] = withDataHtml.split('\n'); const [withDataTitle, withDataSection] = withDataHtml.split('\n');
expect(withDataTitle).to.equal('Set via data'); expect(withDataTitle).to.equal('Set via data');
expect(withDataSection).be.undefined; expect(withDataSection).be.undefined;
}); });
it('will note create a social media image in "start"', async () => { it('will note create a social media image in "start"', async () => {
cli = await executeStart('computed-config-fixtures/social-images-only-build/rocket.config.js'); const { cli, readOutput } = await execute(
'computed-config-fixtures/social-images-only-build/rocket.config.js',
{
captureLog: true,
},
);
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal(''); expect(indexHtml).to.equal('');
}); });
it('will create a social media image in "build"', async () => { it('will create a social media image in "build"', async () => {
cli = await executeBuild('computed-config-fixtures/social-images-only-build/rocket.config.js'); const { cli, readOutput } = await execute(
'computed-config-fixtures/social-images-only-build/rocket.config.js',
{
captureLog: true,
type: 'build',
},
);
cleanupCli = cli;
const indexHtml = await readBuildOutput(cli, 'index.html', { const indexHtml = await readOutput('index.html', {
stripToBody: true, stripToBody: true,
}); });
expect(indexHtml).to.equal('/_merged_assets/11ty-img/5893749-1200.png'); expect(indexHtml).to.equal('/_merged_assets/11ty-img/5893749-1200.png');
}); });
it('will create a social media image for every page', async () => { it('will create a social media image for every page', async () => {
cli = await executeStart('computed-config-fixtures/social-images/rocket.config.js'); const { cli, readOutput } = await execute(
'computed-config-fixtures/social-images/rocket.config.js',
{
captureLog: true,
},
);
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal('/_merged_assets/11ty-img/c4c29ec7-1200.png'); expect(indexHtml).to.equal('/_merged_assets/11ty-img/c4c29ec7-1200.png');
const guidesHtml = await readStartOutput(cli, 'guides/index.html'); const guidesHtml = await readOutput('guides/index.html');
expect(guidesHtml).to.equal('/_merged_assets/11ty-img/c593a8cd-1200.png'); expect(guidesHtml).to.equal('/_merged_assets/11ty-img/c593a8cd-1200.png');
const gettingStartedHtml = await readStartOutput( const gettingStartedHtml = await readOutput('guides/first-pages/getting-started/index.html');
cli,
'guides/first-pages/getting-started/index.html',
);
expect(gettingStartedHtml).to.equal('/_merged_assets/11ty-img/d989ab1a-1200.png'); expect(gettingStartedHtml).to.equal('/_merged_assets/11ty-img/d989ab1a-1200.png');
}); });
it('can override the svg function globally to adjust all social media image', async () => { it('can override the svg function globally to adjust all social media image', async () => {
cli = await executeStart('computed-config-fixtures/social-images-override/rocket.config.js'); const { cli, readOutput } = await execute(
'computed-config-fixtures/social-images-override/rocket.config.js',
{
captureLog: true,
},
);
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal('/_merged_assets/11ty-img/d76265ed-1200.png'); expect(indexHtml).to.equal('/_merged_assets/11ty-img/d76265ed-1200.png');
const guidesHtml = await readStartOutput(cli, 'guides/index.html'); const guidesHtml = await readOutput('guides/index.html');
expect(guidesHtml).to.equal('/_merged_assets/11ty-img/d76265ed-1200.png'); expect(guidesHtml).to.equal('/_merged_assets/11ty-img/d76265ed-1200.png');
const gettingStartedHtml = await readStartOutput( const gettingStartedHtml = await readOutput('guides/first-pages/getting-started/index.html');
cli,
'guides/first-pages/getting-started/index.html',
);
expect(gettingStartedHtml).to.equal('/_merged_assets/11ty-img/d76265ed-1200.png'); expect(gettingStartedHtml).to.equal('/_merged_assets/11ty-img/d76265ed-1200.png');
}); });
it('will add "../" for links and image urls only within named template files', async () => { it('will add "../" for links and image urls only within named template files', async () => {
cli = await executeStart('computed-config-fixtures/image-link/rocket.config.js'); const {
cli,
readOutput,
} = await execute('computed-config-fixtures/image-link/rocket.config.js', { captureLog: true });
cleanupCli = cli;
const namedMdContent = [ const namedMdContent = [
'<p>', '<p>',
@@ -127,22 +148,22 @@ describe('RocketCli computedConfig', () => {
'</div>', '</div>',
]; ];
const templateHtml = await readStartOutput(cli, 'template/index.html', { formatHtml: true }); const templateHtml = await readOutput('template/index.html', { formatHtml: true });
expect(templateHtml, 'template/index.html does not match').to.equal( expect(templateHtml, 'template/index.html does not match').to.equal(
namedHtmlContent.join('\n'), namedHtmlContent.join('\n'),
); );
const guidesHtml = await readStartOutput(cli, 'guides/index.html', { formatHtml: true }); const guidesHtml = await readOutput('guides/index.html', { formatHtml: true });
expect(guidesHtml, 'guides/index.html does not match').to.equal( expect(guidesHtml, 'guides/index.html does not match').to.equal(
[...namedMdContent, ...namedHtmlContent].join('\n'), [...namedMdContent, ...namedHtmlContent].join('\n'),
); );
const noAdjustHtml = await readStartOutput(cli, 'no-adjust/index.html'); const noAdjustHtml = await readOutput('no-adjust/index.html');
expect(noAdjustHtml, 'no-adjust/index.html does not match').to.equal( expect(noAdjustHtml, 'no-adjust/index.html does not match').to.equal(
'<p>Nothing to adjust in here</p>', '<p>Nothing to adjust in here</p>',
); );
const rawHtml = await readStartOutput(cli, 'one-level/raw/index.html'); const rawHtml = await readOutput('one-level/raw/index.html');
expect(rawHtml, 'raw/index.html does not match').to.equal( expect(rawHtml, 'raw/index.html does not match').to.equal(
[ [
'<div>', '<div>',
@@ -159,7 +180,7 @@ describe('RocketCli computedConfig', () => {
); );
// for index files no '../' will be added // for index files no '../' will be added
const indexHtml = await readStartOutput(cli, 'index.html', { formatHtml: true }); const indexHtml = await readOutput('index.html', { formatHtml: true });
expect(indexHtml, 'index.html does not match').to.equal( expect(indexHtml, 'index.html does not match').to.equal(
[ [
'<p>', '<p>',
@@ -188,19 +209,28 @@ describe('RocketCli computedConfig', () => {
}); });
it('can be configured via setupEleventyComputedConfig', async () => { it('can be configured via setupEleventyComputedConfig', async () => {
cli = await executeStart('computed-config-fixtures/setup/addPlugin.rocket.config.js'); const { cli, readOutput } = await execute(
'computed-config-fixtures/setup/addPlugin.rocket.config.js',
{
captureLog: true,
},
);
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal('test-value'); expect(indexHtml).to.equal('test-value');
}); });
it('always assigns layout-default exept for index.* files who get layout-index', async () => { it('always assigns layout-default exept for index.* files who get layout-index', async () => {
cli = await executeStart('computed-config-fixtures/layout/rocket.config.js'); const { cli, readOutput } = await execute('computed-config-fixtures/layout/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.include('<body layout="layout-index">'); expect(indexHtml).to.include('<body layout="layout-index">');
const pageHtml = await readStartOutput(cli, 'page/index.html'); const pageHtml = await readOutput('page/index.html');
expect(pageHtml).to.include('<body layout="layout-default">'); expect(pageHtml).to.include('<body layout="layout-default">');
}); });
}); });

View File

@@ -2,13 +2,9 @@ import chai from 'chai';
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import chalk from 'chalk'; import chalk from 'chalk';
import { import {
execute,
executeBootstrap, executeBootstrap,
executeBuild,
executeLint,
executeStart,
expectThrowsAsync, expectThrowsAsync,
readBuildOutput,
readStartOutput,
getfixtureExpectedFiles, getfixtureExpectedFiles,
setFixtureDir, setFixtureDir,
} from '@rocket/cli/test-helpers'; } from '@rocket/cli/test-helpers';
@@ -17,7 +13,7 @@ import fs from 'fs-extra';
const { expect } = chai; const { expect } = chai;
describe('RocketCli e2e', () => { describe('RocketCli e2e', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -26,20 +22,24 @@ describe('RocketCli e2e', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
it('can add a unified plugin via the config', async () => { it('can add a unified plugin via the config', async () => {
cli = await executeStart('e2e-fixtures/unified-plugin/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/unified-plugin/rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'index.html'); captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal(`<p>See a 🐶</p>`); expect(indexHtml).to.equal(`<p>See a 🐶</p>`);
}); });
describe('bootstrap command', () => { describe('bootstrap command', () => {
it('can bootstrap a project', async () => { it('can bootstrap a project', async () => {
cli = await executeBootstrap('e2e-fixtures/bootstrap/__output'); const { cli } = await executeBootstrap('e2e-fixtures/bootstrap/__output');
cleanupCli = cli;
for (const p of await getfixtureExpectedFiles('e2e-fixtures/bootstrap/expected')) { for (const p of await getfixtureExpectedFiles('e2e-fixtures/bootstrap/expected')) {
const actual = await fs.readFile( const actual = await fs.readFile(
@@ -54,8 +54,11 @@ describe('RocketCli e2e', () => {
describe('eleventy in config', () => { describe('eleventy in config', () => {
it('can modify eleventy via an elventy function in the config', async () => { it('can modify eleventy via an elventy function in the config', async () => {
cli = await executeStart('e2e-fixtures/content/eleventy.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/content/eleventy.rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'index.html'); captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal( expect(indexHtml).to.equal(
['# BEFORE #', '<p>Content inside <code>docs/index.md</code></p>'].join('\n'), ['# BEFORE #', '<p>Content inside <code>docs/index.md</code></p>'].join('\n'),
); );
@@ -63,7 +66,8 @@ describe('RocketCli e2e', () => {
it('will throw if you try to set options by returning an object', async () => { it('will throw if you try to set options by returning an object', async () => {
await expectThrowsAsync( await expectThrowsAsync(
() => executeStart('e2e-fixtures/content/eleventy-return.rocket.config.js'), () =>
execute('e2e-fixtures/content/eleventy-return.rocket.config.js', { captureLog: true }),
{ {
errorMatch: /Error in your Eleventy config file.*/, errorMatch: /Error in your Eleventy config file.*/,
}, },
@@ -73,13 +77,23 @@ describe('RocketCli e2e', () => {
describe('setupDevAndBuildPlugins in config', () => { describe('setupDevAndBuildPlugins in config', () => {
it('can add a rollup plugin via setupDevAndBuildPlugins for build command', async () => { it('can add a rollup plugin via setupDevAndBuildPlugins for build command', async () => {
cli = await executeBuild('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js'); const { cli, readOutput } = await execute(
const inlineModule = await readBuildOutput(cli, 'e97af63d.js'); 'e2e-fixtures/rollup-plugin/devbuild.rocket.config.js',
{
captureLog: true,
type: 'build',
},
);
cleanupCli = cli;
const inlineModule = await readOutput('e97af63d.js');
expect(inlineModule).to.equal('var a={test:"data"};console.log(a);'); expect(inlineModule).to.equal('var a={test:"data"};console.log(a);');
}); });
it('can add a rollup plugin via setupDevAndBuildPlugins for start command', async () => { it('can add a rollup plugin via setupDevAndBuildPlugins for start command', async () => {
cli = await executeStart('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js'); const { cli } = await execute('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const response = await fetch('http://localhost:8080/test-data.json'); const response = await fetch('http://localhost:8080/test-data.json');
expect(response.ok).to.be.true; // no server error expect(response.ok).to.be.true; // no server error
@@ -90,37 +104,56 @@ describe('RocketCli e2e', () => {
}); });
it('can add a rollup plugin for dev & build and modify a build only plugin via the config', async () => { it('can add a rollup plugin for dev & build and modify a build only plugin via the config', async () => {
cli = await executeBuild('e2e-fixtures/rollup-plugin/devbuild-build.rocket.config.js'); const { cli, readOutput } = await execute(
const inlineModule = await readBuildOutput(cli, 'e97af63d.js'); 'e2e-fixtures/rollup-plugin/devbuild-build.rocket.config.js',
{
captureLog: true,
type: 'build',
},
);
cleanupCli = cli;
const inlineModule = await readOutput('e97af63d.js');
expect(inlineModule).to.equal('var a={test:"data"};console.log(a);'); expect(inlineModule).to.equal('var a={test:"data"};console.log(a);');
}); });
it('can adjust the inputDir', async () => { it('can adjust the inputDir', async () => {
cli = await executeStart('e2e-fixtures/change-input-dir/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/change-input-dir/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal('<p>Markdown in <code>docs/page/index.md</code></p>'); expect(indexHtml).to.equal('<p>Markdown in <code>docs/page/index.md</code></p>');
}); });
it('can access main rocket config values via {{rocketConfig.value}}', async () => { it('can access main rocket config values via {{rocketConfig.value}}', async () => {
cli = await executeStart('e2e-fixtures/rocket-config-in-template/rocket.config.js'); const { cli, readOutput } = await execute(
'e2e-fixtures/rocket-config-in-template/rocket.config.js',
{
captureLog: true,
},
);
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal( expect(indexHtml).to.equal(
'<p>You can show Rocket config data like rocketConfig.absoluteBaseUrl = <a href="http://test-domain.com/">http://test-domain.com/</a></p>', '<p>You can show Rocket config data like rocketConfig.absoluteBaseUrl = <a href="http://test-domain.com/">http://test-domain.com/</a></p>',
); );
}); });
it('can add a pathPrefix that will not influence the start command', async () => { it('can add a pathPrefix that will not influence the start command', async () => {
cli = await executeStart('e2e-fixtures/content/pathPrefix.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/content/pathPrefix.rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const linkHtml = await readStartOutput(cli, 'link/index.html'); const linkHtml = await readOutput('link/index.html');
expect(linkHtml).to.equal( expect(linkHtml).to.equal(
['<p><a href="../">home</a></p>', '<p><a href="/">absolute home</a></p>'].join('\n'), ['<p><a href="../">home</a></p>', '<p><a href="/">absolute home</a></p>'].join('\n'),
); );
const assetHtml = await readStartOutput(cli, 'use-assets/index.html'); const assetHtml = await readOutput('use-assets/index.html');
expect(assetHtml).to.equal('<link rel="stylesheet" href="/_merged_assets/some.css">'); expect(assetHtml).to.equal('<link rel="stylesheet" href="/_merged_assets/some.css">');
const imageHtml = await readStartOutput(cli, 'image/index.html', { replaceImageHashes: true }); const imageHtml = await readOutput('image/index.html', { replaceImageHashes: true });
expect(imageHtml).to.equal( expect(imageHtml).to.equal(
[ [
'<p>', '<p>',
@@ -147,9 +180,13 @@ describe('RocketCli e2e', () => {
}); });
it('can add a pathPrefix that will be used in the build command', async () => { it('can add a pathPrefix that will be used in the build command', async () => {
cli = await executeBuild('e2e-fixtures/content/pathPrefix.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/content/pathPrefix.rocket.config.js', {
captureLog: true,
type: 'build',
});
cleanupCli = cli;
const linkHtml = await readBuildOutput(cli, 'link/index.html', { const linkHtml = await readOutput('link/index.html', {
stripToBody: true, stripToBody: true,
}); });
expect(linkHtml).to.equal( expect(linkHtml).to.equal(
@@ -157,11 +194,11 @@ describe('RocketCli e2e', () => {
'\n', '\n',
), ),
); );
const assetHtml = await readBuildOutput(cli, 'use-assets/index.html'); const assetHtml = await readOutput('use-assets/index.html');
expect(assetHtml).to.equal( expect(assetHtml).to.equal(
'<html><head><link rel="stylesheet" href="../41297ffa.css">\n\n</head><body>\n\n</body></html>', '<html><head><link rel="stylesheet" href="../41297ffa.css">\n\n</head><body>\n\n</body></html>',
); );
let imageHtml = await readBuildOutput(cli, 'image/index.html'); let imageHtml = await readOutput('image/index.html');
imageHtml = imageHtml.replace(/\.\.\/([a-z0-9]+)\./g, '../__HASH__.'); imageHtml = imageHtml.replace(/\.\.\/([a-z0-9]+)\./g, '../__HASH__.');
expect(imageHtml).to.equal( expect(imageHtml).to.equal(
[ [
@@ -184,15 +221,22 @@ describe('RocketCli e2e', () => {
}); });
it('smoke test for link checking', async () => { it('smoke test for link checking', async () => {
await expectThrowsAsync(() => executeLint('e2e-fixtures/lint-links/rocket.config.js'), { await expectThrowsAsync(
errorMatch: /Found 1 missing reference targets/, () => execute('e2e-fixtures/lint-links/rocket.config.js', { captureLog: true, type: 'lint' }),
}); {
errorMatch: /Found 1 missing reference targets/,
},
);
}); });
it('can completely take over the rollup config', async () => { it('can completely take over the rollup config', async () => {
cli = await executeBuild('e2e-fixtures/rollup-override/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/rollup-override/rocket.config.js', {
captureLog: true,
type: 'build',
});
cleanupCli = cli;
const indexHtml = await readBuildOutput(cli, 'index.html', { const indexHtml = await readOutput('index.html', {
stripToBody: true, stripToBody: true,
formatHtml: true, formatHtml: true,
}); });
@@ -210,14 +254,27 @@ describe('RocketCli e2e', () => {
describe('can adjust the eleventy config while having access to the rocketConfig', () => { describe('can adjust the eleventy config while having access to the rocketConfig', () => {
it('testing start', async () => { it('testing start', async () => {
cli = await executeStart('e2e-fixtures/adjust-eleventy-config/rocket.config.js'); const { cli, readOutput } = await execute(
const indexHtml = await readStartOutput(cli, 'index.html'); 'e2e-fixtures/adjust-eleventy-config/rocket.config.js',
{
captureLog: true,
},
);
cleanupCli = cli;
const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal('<p><a href="start:/path/to/page/">link</a></p>'); expect(indexHtml).to.equal('<p><a href="start:/path/to/page/">link</a></p>');
}); });
it('testing build', async () => { it('testing build', async () => {
cli = await executeBuild('e2e-fixtures/adjust-eleventy-config/rocket.config.js'); const { cli, readOutput } = await execute(
const indexBuildHtml = await readBuildOutput(cli, 'index.html', { 'e2e-fixtures/adjust-eleventy-config/rocket.config.js',
{
captureLog: true,
type: 'build',
},
);
cleanupCli = cli;
const indexBuildHtml = await readOutput('index.html', {
stripToBody: true, stripToBody: true,
}); });
expect(indexBuildHtml).to.equal('<p><a href="build:/path/to/page/">link</a></p>'); expect(indexBuildHtml).to.equal('<p><a href="build:/path/to/page/">link</a></p>');

View File

@@ -1,11 +1,11 @@
import chai from 'chai'; import chai from 'chai';
import chalk from 'chalk'; import chalk from 'chalk';
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers'; import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai; const { expect } = chai;
describe('RocketCli images', () => { describe('RocketCli images', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -14,15 +14,18 @@ describe('RocketCli images', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
describe('Images', () => { describe('Images', () => {
it('does render content images responsive', async () => { it('does render content images responsive', async () => {
cli = await executeStart('e2e-fixtures/images/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/images/rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'index.html', { captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -57,7 +60,7 @@ describe('RocketCli images', () => {
].join('\n'), ].join('\n'),
); );
const keepSvgHtml = await readStartOutput(cli, 'ignores/index.html', { const keepSvgHtml = await readOutput('ignores/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -102,7 +105,7 @@ describe('RocketCli images', () => {
].join('\n'), ].join('\n'),
); );
const tableHtml = await readStartOutput(cli, 'table/index.html', { const tableHtml = await readOutput('table/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -150,8 +153,12 @@ describe('RocketCli images', () => {
}); });
it('can configure more patterns to ignore', async () => { it('can configure more patterns to ignore', async () => {
cli = await executeStart('e2e-fixtures/images/ignore-more.rocket.config.js'); const { cli, readOutput } = await execute(
const keepSvgHtml = await readStartOutput(cli, 'ignores/index.html', { 'e2e-fixtures/images/ignore-more.rocket.config.js',
{ captureLog: true },
);
cleanupCli = cli;
const keepSvgHtml = await readOutput('ignores/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -178,8 +185,11 @@ describe('RocketCli images', () => {
}); });
it('renders multiple images in the correct order', async () => { it('renders multiple images in the correct order', async () => {
cli = await executeStart('e2e-fixtures/images/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/images/rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'two-images/index.html', { captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('two-images/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -242,8 +252,11 @@ describe('RocketCli images', () => {
}); });
it('can configure those responsive images', async () => { it('can configure those responsive images', async () => {
cli = await executeStart('e2e-fixtures/images/small.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/images/small.rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'index.html', { captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -280,8 +293,11 @@ describe('RocketCli images', () => {
}); });
it('will only render a figure & figcaption if there is a caption/title', async () => { it('will only render a figure & figcaption if there is a caption/title', async () => {
cli = await executeStart('e2e-fixtures/images/small.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/images/small.rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'no-title/index.html', { captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('no-title/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -315,8 +331,12 @@ describe('RocketCli images', () => {
}); });
it('will render an img with srcset and sizes if there is only one image format', async () => { it('will render an img with srcset and sizes if there is only one image format', async () => {
cli = await executeStart('e2e-fixtures/images/single-format.rocket.config.js'); const {
const indexHtml = await readStartOutput(cli, 'no-title/index.html', { cli,
readOutput,
} = await execute('e2e-fixtures/images/single-format.rocket.config.js', { captureLog: true });
cleanupCli = cli;
const indexHtml = await readOutput('no-title/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });

View File

@@ -1,16 +1,11 @@
import chai from 'chai'; import chai from 'chai';
import chalk from 'chalk'; import chalk from 'chalk';
import { import { execute, trimWhiteSpace, setFixtureDir } from '@rocket/cli/test-helpers';
executeStart,
readStartOutput,
trimWhiteSpace,
setFixtureDir,
} from '@rocket/cli/test-helpers';
const { expect } = chai; const { expect } = chai;
describe('RocketCli mergeTemplates', () => { describe('RocketCli mergeTemplates', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -19,15 +14,18 @@ describe('RocketCli mergeTemplates', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
it('merges it in the defined order', async () => { it('merges it in the defined order', async () => {
cli = await executeStart('merge-templates-fixtures/order/rocket.config.js'); const { cli, readOutput } = await execute('merge-templates-fixtures/order/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(trimWhiteSpace(indexHtml)).to.equal( expect(trimWhiteSpace(indexHtml)).to.equal(
[ [
'<p>30-first</p>', '<p>30-first</p>',
@@ -40,9 +38,13 @@ describe('RocketCli mergeTemplates', () => {
}); });
it('presets can overwrite in order', async () => { it('presets can overwrite in order', async () => {
cli = await executeStart('merge-templates-fixtures/overwrite/rocket.config.js'); const { cli, readOutput } = await execute(
'merge-templates-fixtures/overwrite/rocket.config.js',
{ captureLog: true },
);
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(trimWhiteSpace(indexHtml)).to.equal( expect(trimWhiteSpace(indexHtml)).to.equal(
['<p>overwritten second</p>', '<p>third</p>', '<p>overwritten first to be last</p>'].join( ['<p>overwritten second</p>', '<p>third</p>', '<p>overwritten first to be last</p>'].join(
'\n', '\n',
@@ -51,9 +53,12 @@ describe('RocketCli mergeTemplates', () => {
}); });
it('presets can add inbetween', async () => { it('presets can add inbetween', async () => {
cli = await executeStart('merge-templates-fixtures/add/rocket.config.js'); const { cli, readOutput } = await execute('merge-templates-fixtures/add/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(trimWhiteSpace(indexHtml)).to.equal( expect(trimWhiteSpace(indexHtml)).to.equal(
[ [
'<p>first</p>', '<p>first</p>',

View File

@@ -1,11 +1,11 @@
import chai from 'chai'; import chai from 'chai';
import chalk from 'chalk'; import chalk from 'chalk';
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers'; import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai; const { expect } = chai;
describe('RocketCli preset', () => { describe('RocketCli preset', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -14,21 +14,24 @@ describe('RocketCli preset', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
it('offers a default layout (with head, header, content, footer, bottom) and raw layout', async () => { it('offers a default layout (with head, header, content, footer, bottom) and raw layout', async () => {
cli = await executeStart('preset-fixtures/default/rocket.config.js'); const { cli, readOutput } = await execute('preset-fixtures/default/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const rawHtml = await readStartOutput(cli, 'raw/index.html'); const rawHtml = await readOutput('raw/index.html');
expect(rawHtml).to.equal('<p>Just raw</p>'); expect(rawHtml).to.equal('<p>Just raw</p>');
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.include('<body layout="layout-index">'); expect(indexHtml).to.include('<body layout="layout-index">');
const pageHtml = await readStartOutput(cli, 'page/index.html', { const pageHtml = await readOutput('page/index.html', {
stripScripts: true, stripScripts: true,
formatHtml: true, formatHtml: true,
}); });
@@ -93,16 +96,22 @@ describe('RocketCli preset', () => {
}); });
it('allows to add content to the head without overriding', async () => { it('allows to add content to the head without overriding', async () => {
cli = await executeStart('preset-fixtures/add-to-head/rocket.config.js'); const { cli, readOutput } = await execute('preset-fixtures/add-to-head/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.include('<meta name="added" content="at the top" />'); expect(indexHtml).to.include('<meta name="added" content="at the top" />');
}); });
it('a preset can provide an adjustImagePresets() function', async () => { it('a preset can provide an adjustImagePresets() function', async () => {
cli = await executeStart('preset-fixtures/use-preset/rocket.config.js'); const { cli, readOutput } = await execute('preset-fixtures/use-preset/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html', { const indexHtml = await readOutput('index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });

View File

@@ -1,6 +1,6 @@
import chai from 'chai'; import chai from 'chai';
import chalk from 'chalk'; import chalk from 'chalk';
import { executeBuild, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers'; import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai; const { expect } = chai;
@@ -17,7 +17,7 @@ function getServiceWorkerUrl(text) {
} }
describe('RocketCli e2e', () => { describe('RocketCli e2e', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -26,20 +26,28 @@ describe('RocketCli e2e', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
it('will add a script to inject the service worker', async () => { it('will add a script to inject the service worker', async () => {
cli = await executeBuild('e2e-fixtures/service-worker/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/service-worker/rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'index.html'); captureLog: true,
type: 'build',
});
cleanupCli = cli;
// we check the start output here as in the rollup build version it's hard to find
const indexHtml = await readOutput('../__output-dev/index.html');
const indexInject = getInjectServiceWorker(indexHtml); const indexInject = getInjectServiceWorker(indexHtml);
expect(indexInject).to.equal( expect(indexInject).to.equal(
'<script type="module" inject-service-worker="" src="/_merged_assets/scripts/registerServiceWorker.js"></script>', '<script type="module" inject-service-worker="" src="/_merged_assets/scripts/registerServiceWorker.js"></script>',
); );
expect(getServiceWorkerUrl(indexHtml)).to.equal('/service-worker.js'); expect(getServiceWorkerUrl(indexHtml)).to.equal('/service-worker.js');
const subHtml = await readStartOutput(cli, 'sub/index.html');
// we check the start output here as in the rollup build version it's hard to find
const subHtml = await readOutput('../__output-dev/sub/index.html');
const subInject = getInjectServiceWorker(subHtml); const subInject = getInjectServiceWorker(subHtml);
expect(subInject).to.equal( expect(subInject).to.equal(
'<script type="module" inject-service-worker="" src="/_merged_assets/scripts/registerServiceWorker.js"></script>', '<script type="module" inject-service-worker="" src="/_merged_assets/scripts/registerServiceWorker.js"></script>',
@@ -49,14 +57,21 @@ describe('RocketCli e2e', () => {
// TODO: find a way to run these test either by forcing pathPrefix in start or skipping asset gathering for build or ... // TODO: find a way to run these test either by forcing pathPrefix in start or skipping asset gathering for build or ...
it.skip('will add a script to inject the service worker', async () => { it.skip('will add a script to inject the service worker', async () => {
cli = await executeBuild('e2e-fixtures/service-worker/pathPrefix.rocket.config.js'); const { cli, readOutput } = await execute(
const indexHtml = await readStartOutput(cli, 'index.html'); 'e2e-fixtures/service-worker/pathPrefix.rocket.config.js',
{
captureLog: true,
type: 'build',
},
);
cleanupCli = cli;
const indexHtml = await readOutput('index.html');
const indexInject = getInjectServiceWorker(indexHtml); const indexInject = getInjectServiceWorker(indexHtml);
expect(indexInject).to.equal( expect(indexInject).to.equal(
'<script type="module" inject-service-worker="" src="/my-prefix-folder/_merged_assets/scripts/registerServiceWorker.js"></script>', '<script type="module" inject-service-worker="" src="/my-prefix-folder/_merged_assets/scripts/registerServiceWorker.js"></script>',
); );
expect(getServiceWorkerUrl(indexHtml)).to.equal('/my-prefix-folder/service-worker.js'); expect(getServiceWorkerUrl(indexHtml)).to.equal('/my-prefix-folder/service-worker.js');
const subHtml = await readStartOutput(cli, 'sub/index.html'); const subHtml = await readOutput('sub/index.html');
const subInject = getInjectServiceWorker(subHtml); const subInject = getInjectServiceWorker(subHtml);
expect(subInject).to.equal( expect(subInject).to.equal(
'<script type="module" inject-service-worker="" src="/my-prefix-folder/_merged_assets/scripts/registerServiceWorker.js"></script>', '<script type="module" inject-service-worker="" src="/my-prefix-folder/_merged_assets/scripts/registerServiceWorker.js"></script>',

View File

@@ -1,16 +1,11 @@
import chai from 'chai'; import chai from 'chai';
import chalk from 'chalk'; import chalk from 'chalk';
import { import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
executeStart,
readStartOutput,
setFixtureDir,
startOutputExist,
} from '@rocket/cli/test-helpers';
const { expect } = chai; const { expect } = chai;
describe('RocketCli use cases', () => { describe('RocketCli use cases', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -19,18 +14,22 @@ describe('RocketCli use cases', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
it('supports dynamic imports', async () => { it('supports dynamic imports', async () => {
cli = await executeStart('use-cases/dynamic-imports/rocket.config.js'); const {
cli,
readOutput,
outputExists,
} = await execute('use-cases/dynamic-imports/rocket.config.js', { captureLog: true });
cleanupCli = cli;
expect(startOutputExist(cli, 'sub/assets/myData.js'), 'static files did not get copied').to.be expect(outputExists('sub/assets/myData.js'), 'static files did not get copied').to.be.true;
.true;
const aboutHtml = await readStartOutput(cli, 'about/index.html', { formatHtml: true }); const aboutHtml = await readOutput('about/index.html', { formatHtml: true });
expect(aboutHtml).to.equal( expect(aboutHtml).to.equal(
[ [
'<p><code>about.md</code></p>', '<p><code>about.md</code></p>',
@@ -38,7 +37,7 @@ describe('RocketCli use cases', () => {
].join('\n'), ].join('\n'),
); );
const subHtml = await readStartOutput(cli, 'sub/index.html', { formatHtml: true }); const subHtml = await readOutput('sub/index.html', { formatHtml: true });
expect(subHtml).to.equal( expect(subHtml).to.equal(
[ [
'<p><code>sub/index.md</code></p>', '<p><code>sub/index.md</code></p>',
@@ -46,7 +45,7 @@ describe('RocketCli use cases', () => {
].join('\n'), ].join('\n'),
); );
const subDetailsHtml = await readStartOutput(cli, 'sub/details/index.html', { const subDetailsHtml = await readOutput('sub/details/index.html', {
formatHtml: true, formatHtml: true,
}); });
expect(subDetailsHtml).to.equal( expect(subDetailsHtml).to.equal(
@@ -56,7 +55,7 @@ describe('RocketCli use cases', () => {
].join('\n'), ].join('\n'),
); );
const indexHtml = await readStartOutput(cli, 'index.html', { formatHtml: true }); const indexHtml = await readOutput('index.html', { formatHtml: true });
expect(indexHtml).to.equal( expect(indexHtml).to.equal(
[ [
'<p><code>index.md</code></p>', '<p><code>index.md</code></p>',

View File

@@ -1,89 +0,0 @@
import chai from 'chai';
import { RocketCli } from '../src/RocketCli.js';
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs-extra';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const { expect } = chai;
/**
* @param {function} method
* @param {string} errorMessage
*/
export async function expectThrowsAsync(method, { errorMatch, errorMessage } = {}) {
let error = null;
try {
await method();
} catch (err) {
error = err;
}
expect(error).to.be.an('Error', 'No error was thrown');
if (errorMatch) {
expect(error.message).to.match(errorMatch);
}
if (errorMessage) {
expect(error.message).to.equal(errorMessage);
}
}
export async function readOutput(
cli,
fileName,
{ stripToBody = false, stripStartEndWhitespace = true, type = 'build' } = {},
) {
const outputDir = type === 'build' ? cli.config.outputDir : cli.config.outputDevDir;
let text = await fs.promises.readFile(path.join(outputDir, fileName));
text = text.toString();
if (stripToBody) {
const bodyOpenTagEnd = text.indexOf('>', text.indexOf('<body') + 1) + 1;
const bodyCloseTagStart = text.indexOf('</body>');
text = text.substring(bodyOpenTagEnd, bodyCloseTagStart);
}
if (stripStartEndWhitespace) {
text = text.trim();
}
return text;
}
export async function readStartOutput(cli, fileName, options = {}) {
options.type = 'start';
return readOutput(cli, fileName, options);
}
export async function execute(cli, configFileDir) {
await cli.setup();
cli.config.outputDevDir = path.join(configFileDir, '__output-dev');
cli.config.devServer.open = false;
cli.config.watch = false;
cli.config.outputDir = path.join(configFileDir, '__output');
await cli.run();
return cli;
}
export async function executeStart(pathToConfig) {
const configFile = path.join(__dirname, pathToConfig.split('/').join(path.sep));
const cli = new RocketCli({
argv: ['start', '--config-file', configFile],
});
await execute(cli, path.dirname(configFile));
return cli;
}
export async function executeLint(pathToConfig) {
const configFile = path.join(__dirname, pathToConfig.split('/').join(path.sep));
const cli = new RocketCli({
argv: ['lint', '--config-file', configFile],
});
await execute(cli, path.dirname(configFile));
return cli;
}
export function trimWhiteSpace(inString) {
return inString
.split('\n')
.map(line => line.trim())
.filter(line => line)
.join('\n');
}

View File

@@ -1,5 +1,17 @@
# @rocket/drawer # @rocket/drawer
## 0.1.5
### Patch Changes
- 1f14105: Add export map which enables side effect import via `@rocket/drawer/define`
## 0.1.4
### Patch Changes
- 445b028: Update to latest lit, @open-wc, @lion packages
## 0.1.3 ## 0.1.3
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@rocket/drawer", "name": "@rocket/drawer",
"version": "0.1.3", "version": "0.1.5",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -13,6 +13,11 @@
}, },
"author": "Modern Web <hello@modern-web.dev> (https://modern-web.dev/)", "author": "Modern Web <hello@modern-web.dev> (https://modern-web.dev/)",
"main": "index.js", "main": "index.js",
"exports": {
".": "./index.js",
"./rocket-drawer.js": "./rocket-drawer.js",
"./define": "./rocket-drawer.js"
},
"scripts": { "scripts": {
"dev": "web-dev-server --node-resolve --root-dir ../../ --open packages/drawer/ --watch", "dev": "web-dev-server --node-resolve --root-dir ../../ --open packages/drawer/ --watch",
"rocket:build": "node src/build/cli.js -c demo/docs", "rocket:build": "node src/build/cli.js -c demo/docs",
@@ -33,8 +38,8 @@
"testing" "testing"
], ],
"dependencies": { "dependencies": {
"@lion/overlays": "^0.26.1", "@lion/overlays": "^0.29.1",
"lit-element": "^2.4.0" "lit": "^2.0.0"
}, },
"types": "dist-types/index.d.ts" "types": "dist-types/index.d.ts"
} }

View File

@@ -1,5 +1,11 @@
# @rocket/eleventy-rocket-nav # @rocket/eleventy-rocket-nav
## 0.3.1
### Patch Changes
- 60310ab: Improve performance by initializing sax-wasm only once even when it is running in parallel
## 0.3.0 ## 0.3.0
### Minor Changes ### Minor Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@rocket/eleventy-rocket-nav", "name": "@rocket/eleventy-rocket-nav",
"version": "0.3.0", "version": "0.3.1",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },

View File

@@ -97,6 +97,7 @@ function getHeadingsOfHtml(html) {
return { headings, insertPoint }; return { headings, insertPoint };
} }
/** @type {boolean | Promise<unknown>} */
let isSetup = false; let isSetup = false;
/** /**
@@ -104,9 +105,9 @@ let isSetup = false;
*/ */
async function addPageAnchors(content) { async function addPageAnchors(content) {
if (!isSetup) { if (!isSetup) {
await parser.prepareWasm(saxWasmBuffer); isSetup = parser.prepareWasm(saxWasmBuffer);
isSetup = true;
} }
await isSetup;
const { headings, insertPoint } = getHeadingsOfHtml(content); const { headings, insertPoint } = getHeadingsOfHtml(content);
const pageAnchorsHtml = []; const pageAnchorsHtml = [];

View File

@@ -1,11 +1,11 @@
import chai from 'chai'; import chai from 'chai';
import chalk from 'chalk'; import chalk from 'chalk';
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers'; import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai; const { expect } = chai;
describe('RocketLaunch preset', () => { describe('RocketLaunch preset', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -14,15 +14,18 @@ describe('RocketLaunch preset', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
it('sets layout-sidebar as default', async () => { it('sets layout-sidebar as default', async () => {
cli = await executeStart('fixtures/layout-sidebar/rocket.config.js'); const { cli, readOutput } = await execute('fixtures/layout-sidebar/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'page/index.html', { const indexHtml = await readOutput('page/index.html', {
stripScripts: true, stripScripts: true,
formatHtml: true, formatHtml: true,
}); });
@@ -251,9 +254,12 @@ describe('RocketLaunch preset', () => {
}); });
it('offers a layout-home', async () => { it('offers a layout-home', async () => {
cli = await executeStart('fixtures/layout-home/rocket.config.js'); const { cli, readOutput } = await execute('fixtures/layout-home/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html', { const indexHtml = await readOutput('index.html', {
stripScripts: true, stripScripts: true,
formatHtml: true, formatHtml: true,
}); });

View File

@@ -1,5 +1,61 @@
# Change Log # Change Log
## 0.9.4
### Patch Changes
- e6c3d27: Support `js client` as an alias to `js script`
## 0.9.3
### Patch Changes
- 62637a8: Replaces `rehype-prism-template` with `rehype-prism` to get a newer version of prism with essential security updates
## 0.9.2
### Patch Changes
- 97cb38c: Add missing slash dependency
## 0.9.1
### Patch Changes
- 6221e5f: If your preview is followed by a code blocks marked as `story-code` then those will be shown when switching between multiple platforms
````md
```js preview-story
// will be visible when platform web is selected
export const JsPreviewStory = () =>
html`
<demo-wc-card>JS Preview Story</demo-wc-card>
`;
```
```xml story-code
<!-- will be visible when platform android is selected -->
<Button
android:id="@+id/demoWcCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android Code"
style="@style/Widget.FooComponents.Demo.Wc.Card"
/>
```
```swift story-code
// will be visible when platform ios is selected
import DemoWc.Card
let card = DemoWcButton()
```
````
- Updated dependencies [5c6b9c9]
- Updated dependencies [6221e5f]
- @mdjs/mdjs-preview@0.5.3
## 0.9.0 ## 0.9.0
### Minor Changes ### Minor Changes

View File

@@ -1,5 +1,3 @@
# Markdown with JavaScript (mdjs) # Markdown with JavaScript (mdjs)
Combine Markdown with JavaScript [=> See Source <=](../../docs/docs/markdown-javascript/overview.md)
For docs please see our homepage [https://rocket.modern-web.dev/docs/markdown-javascript/overview/](https://rocket.modern-web.dev/docs/markdown-javascript/overview/).

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mdjs/core", "name": "@mdjs/core",
"version": "0.9.0", "version": "0.9.4",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -21,6 +21,7 @@
} }
}, },
"scripts": { "scripts": {
"prepublishOnly": "publish-docs --github-url https://github.com/modernweb-dev/rocket/ --git-root-dir ../../",
"start": "npm run start:stories", "start": "npm run start:stories",
"start:script": "web-dev-server -c demo/script/server.js --root-dir ../../", "start:script": "web-dev-server -c demo/script/server.js --root-dir ../../",
"start:stories": "web-dev-server -c demo/stories/server.js --root-dir ../../", "start:stories": "web-dev-server -c demo/stories/server.js --root-dir ../../",
@@ -44,14 +45,14 @@
"remark" "remark"
], ],
"dependencies": { "dependencies": {
"@mdjs/mdjs-preview": "^0.5.1", "@mdjs/mdjs-preview": "^0.5.3",
"@mdjs/mdjs-story": "^0.3.0", "@mdjs/mdjs-story": "^0.3.0",
"@types/unist": "^2.0.3", "@types/unist": "^2.0.3",
"es-module-lexer": "^0.3.26", "es-module-lexer": "^0.3.26",
"github-markdown-css": "^4.0.0", "github-markdown-css": "^4.0.0",
"plugins-manager": "^0.3.0", "plugins-manager": "^0.3.0",
"rehype-autolink-headings": "^5.0.1", "rehype-autolink-headings": "^5.0.1",
"rehype-prism-template": "^0.4.1", "rehype-prism": "^1.0.0",
"rehype-raw": "^5.0.0", "rehype-raw": "^5.0.0",
"rehype-slug": "^4.0.1", "rehype-slug": "^4.0.1",
"rehype-stringify": "^8.0.0", "rehype-stringify": "^8.0.0",
@@ -59,6 +60,7 @@
"remark-gfm": "^1.0.0", "remark-gfm": "^1.0.0",
"remark-parse": "^9.0.0", "remark-parse": "^9.0.0",
"remark-rehype": "^8.0.0", "remark-rehype": "^8.0.0",
"slash": "^3.0.0",
"unified": "^9.2.0", "unified": "^9.2.0",
"unist-util-remove": "^2.0.1", "unist-util-remove": "^2.0.1",
"unist-util-visit": "^2.0.3" "unist-util-visit": "^2.0.3"
@@ -66,7 +68,7 @@
"devDependencies": { "devDependencies": {
"demo-wc-card": "^0.1.0", "demo-wc-card": "^0.1.0",
"remark-autolink-headings": "^6.0.1", "remark-autolink-headings": "^6.0.1",
"remark-html": "^13.0.1", "remark-html": "^13.0.2",
"remark-slug": "^6.0.0", "remark-slug": "^6.0.0",
"remark-stringify": "^9.0.1" "remark-stringify": "^9.0.1"
}, },

View File

@@ -16,6 +16,9 @@ function mdjsParse() {
if (node.lang === 'js' && node.meta === 'script') { if (node.lang === 'js' && node.meta === 'script') {
jsCode += node.value; jsCode += node.value;
} }
if (node.lang === 'js' && node.meta === 'client') {
jsCode += node.value;
}
}); });
// we can only return/modify the tree but jsCode should not be part of the tree // we can only return/modify the tree but jsCode should not be part of the tree
// so we attach it globally to the file.data // so we attach it globally to the file.data
@@ -26,7 +29,9 @@ function mdjsParse() {
* @param {Node} node * @param {Node} node
*/ */
const removeFunction = node => const removeFunction = node =>
node.type === 'code' && node.lang === 'js' && node.meta === 'script'; node.type === 'code' &&
node.lang === 'js' &&
(node.meta === 'script' || node.meta === 'client');
remove(tree, removeFunction); remove(tree, removeFunction);
return tree; return tree;

View File

@@ -12,14 +12,16 @@ const raw = require('rehype-raw');
const htmlStringify = require('rehype-stringify'); const htmlStringify = require('rehype-stringify');
const htmlSlug = require('rehype-slug'); const htmlSlug = require('rehype-slug');
const htmlHeading = require('rehype-autolink-headings'); const htmlHeading = require('rehype-autolink-headings');
const rehypePrism = require('rehype-prism-template');
// @ts-ignore // @ts-ignore
const { executeSetupFunctions } = require('plugins-manager'); const { executeSetupFunctions } = require('plugins-manager');
const loadLanguages = require('prismjs/components/');
const { mdjsParse } = require('./mdjsParse.js'); const { mdjsParse } = require('./mdjsParse.js');
const { mdjsStoryParse } = require('./mdjsStoryParse.js'); const { mdjsStoryParse } = require('./mdjsStoryParse.js');
const { mdjsSetupCode } = require('./mdjsSetupCode.js'); const { mdjsSetupCode } = require('./mdjsSetupCode.js');
let prismLoaded = false;
/** @type {MdjsProcessPlugin[]} */ /** @type {MdjsProcessPlugin[]} */
const defaultMetaPlugins = [ const defaultMetaPlugins = [
{ plugin: markdown, options: {} }, { plugin: markdown, options: {} },
@@ -30,8 +32,6 @@ const defaultMetaPlugins = [
// @ts-ignore // @ts-ignore
{ plugin: remark2rehype, options: { allowDangerousHtml: true } }, { plugin: remark2rehype, options: { allowDangerousHtml: true } },
// @ts-ignore // @ts-ignore
{ plugin: rehypePrism, options: {} },
// @ts-ignore
{ plugin: raw, options: {} }, { plugin: raw, options: {} },
// @ts-ignore // @ts-ignore
{ plugin: htmlSlug, options: {} }, { plugin: htmlSlug, options: {} },
@@ -54,6 +54,12 @@ const defaultMetaPlugins = [
*/ */
async function mdjsProcess(mdjs, { setupUnifiedPlugins = [] } = {}) { async function mdjsProcess(mdjs, { setupUnifiedPlugins = [] } = {}) {
const parser = unified(); const parser = unified();
if (!prismLoaded) {
prismLoaded = true;
const rehypePrism = (await import('rehype-prism/lib/src/index.js')).default;
loadLanguages(['md', 'shell', 'yml']);
defaultMetaPlugins.splice(6, 0, { plugin: rehypePrism, options: {} });
}
const metaPlugins = executeSetupFunctions(setupUnifiedPlugins, defaultMetaPlugins); const metaPlugins = executeSetupFunctions(setupUnifiedPlugins, defaultMetaPlugins);

View File

@@ -77,17 +77,32 @@ function mdjsStoryParse({
const newValue = previewStoryTag(storyData.name); const newValue = previewStoryTag(storyData.name);
if (newValue.includes('[[CODE SLOT]]')) { if (newValue.includes('[[CODE SLOT]]')) {
const tagParts = newValue.split('[[CODE SLOT]]'); const tagParts = newValue.split('[[CODE SLOT]]');
const inside = [node];
let skipAmount = 1;
const next = parent.children[index + 1];
if (next && next.type === 'code' && next.meta === 'story-code') {
inside.push(next);
skipAmount += 1;
const next2 = parent.children[index + 2];
if (next2 && next2.type === 'code' && next2.meta === 'story-code') {
inside.push(next2);
skipAmount += 1;
}
}
node = { node = {
type: 'root', type: 'root',
children: [ children: [
{ type: 'html', value: tagParts[0] }, { type: 'html', value: tagParts[0] },
{ type: 'text', value: '\n\n' }, { type: 'text', value: '\n\n' },
node, ...inside,
{ type: 'text', value: '\n\n' }, { type: 'text', value: '\n\n' },
{ type: 'html', value: tagParts[1] }, { type: 'html', value: tagParts[1] },
], ],
}; };
parent.children.splice(index, 1, node); parent.children.splice(index, skipAmount, node);
} else { } else {
node.type = 'html'; node.type = 'html';
node.value = previewStoryTag(storyData.name); node.value = previewStoryTag(storyData.name);
@@ -115,17 +130,31 @@ function mdjsStoryParse({
const newValue = previewStoryTag(storyData.name); const newValue = previewStoryTag(storyData.name);
if (newValue.includes('[[CODE SLOT]]')) { if (newValue.includes('[[CODE SLOT]]')) {
const tagParts = newValue.split('[[CODE SLOT]]'); const tagParts = newValue.split('[[CODE SLOT]]');
const inside = [node];
let skipAmount = 1;
const next = parent.children[index + 1];
if (next && next.type === 'code' && next.meta === 'story-code') {
inside.push(next);
skipAmount += 1;
const next2 = parent.children[index + 2];
if (next2 && next2.type === 'code' && next2.meta === 'story-code') {
inside.push(next2);
skipAmount += 1;
}
}
node = { node = {
type: 'root', type: 'root',
children: [ children: [
{ type: 'html', value: tagParts[0] }, { type: 'html', value: tagParts[0] },
{ type: 'text', value: '\n\n' }, { type: 'text', value: '\n\n' },
node, ...inside,
{ type: 'text', value: '\n\n' }, { type: 'text', value: '\n\n' },
{ type: 'html', value: tagParts[1] }, { type: 'html', value: tagParts[1] },
], ],
}; };
parent.children.splice(index, 1, node); parent.children.splice(index, skipAmount, node);
} else { } else {
node.type = 'html'; node.type = 'html';
node.value = previewStoryTag(storyData.name); node.value = previewStoryTag(storyData.name);

View File

@@ -106,7 +106,7 @@ describe('Integration', () => {
}) })
.use(mdSlug) .use(mdSlug)
.use(mdHeadings) .use(mdHeadings)
.use(mdStringify); .use(mdStringify, { sanitize: false });
const result = await parser.process(input); const result = await parser.process(input);
expect(result.contents).to.equal(expected); expect(result.contents).to.equal(expected);
expect(/** @type {MDJSVFileData} */ (result.data).stories).to.deep.equal([ expect(/** @type {MDJSVFileData} */ (result.data).stories).to.deep.equal([

View File

@@ -35,7 +35,7 @@ describe('mdjsProcess', () => {
'', '',
'', '',
'', '',
'<pre class="language-js"><code class="language-js"><span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function">fooPreviewStory</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>', '<pre class="language-js"><code class="language-js"><span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">fooPreviewStory</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>',
'</code></pre>', '</code></pre>',
'', '',
'', '',

View File

@@ -20,7 +20,25 @@ describe('mdjsParse', () => {
'const bar = 22;', 'const bar = 22;',
'```', '```',
].join('\n'); ].join('\n');
const parser = unified().use(markdown).use(mdjsParse).use(html); const parser = unified().use(markdown).use(mdjsParse).use(html, { sanitize: false });
const result = await parser.process(input);
expect(result.contents).to.equal(
'<h2>Intro</h2>\n<pre><code class="language-js">const foo = 1;\n</code></pre>\n',
);
expect(/** @type {MDJSVFileData} */ (result.data).jsCode).to.equal('const bar = 22;');
});
it('extracts "js client" code blocks', async () => {
const input = [
'## Intro',
'```js',
'const foo = 1;',
'```',
'```js client',
'const bar = 22;',
'```',
].join('\n');
const parser = unified().use(markdown).use(mdjsParse).use(html, { sanitize: false });
const result = await parser.process(input); const result = await parser.process(input);
expect(result.contents).to.equal( expect(result.contents).to.equal(
'<h2>Intro</h2>\n<pre><code class="language-js">const foo = 1;\n</code></pre>\n', '<h2>Intro</h2>\n<pre><code class="language-js">const foo = 1;\n</code></pre>\n',
@@ -36,7 +54,7 @@ describe('mdjsParse', () => {
'const bar = 22;', 'const bar = 22;',
'```', '```',
].join('\n'); ].join('\n');
const parser = unified().use(markdown).use(mdjsParse).use(html); const parser = unified().use(markdown).use(mdjsParse).use(html, { sanitize: false });
const result = await parser.process(input); const result = await parser.process(input);
expect(result.contents).to.equal(''); expect(result.contents).to.equal('');
expect(/** @type {MDJSVFileData} */ (result.data).jsCode).to.equal('const bar = 22;'); expect(/** @type {MDJSVFileData} */ (result.data).jsCode).to.equal('const bar = 22;');

View File

@@ -61,7 +61,7 @@ describe('mdjsStoryParse', () => {
'', '',
].join('\n'); ].join('\n');
const parser = unified().use(markdown).use(mdjsStoryParse).use(html); const parser = unified().use(markdown).use(mdjsStoryParse).use(html, { sanitize: false });
const result = await parser.process(input); const result = await parser.process(input);
expect(result.contents).to.equal(expected); expect(result.contents).to.equal(expected);
expect(/** @type {MDJSVFileData} */ (result.data).stories).to.deep.equal([ expect(/** @type {MDJSVFileData} */ (result.data).stories).to.deep.equal([
@@ -110,7 +110,139 @@ describe('mdjsStoryParse', () => {
storyTag: name => `<Story name="${name}"></Story>`, storyTag: name => `<Story name="${name}"></Story>`,
previewStoryTag: name => `<Preview><Story name="${name}"></Story></Preview>`, previewStoryTag: name => `<Preview><Story name="${name}"></Story></Preview>`,
}) })
.use(html); .use(html, { sanitize: false });
const result = await parser.process(input);
expect(result.contents).to.equal(expected);
});
it('will wrap following story-code blocks', async () => {
const input = [
'```js preview-story',
'export const foo = () => {};',
'```',
'',
'```swift story-code',
'CODE for iOS',
'```',
'',
'```xml story-code',
'CODE for Android',
'```',
].join('\n');
const expected = [
'<mdjs-preview mdjs-story-name="foo">',
'',
'',
'',
'<pre><code class="language-js">export const foo = () => {};',
'</code></pre>',
'<pre><code class="language-swift">CODE for iOS',
'</code></pre>',
'<pre><code class="language-xml">CODE for Android',
'</code></pre>',
'',
'',
'',
'</mdjs-preview>',
'',
].join('\n');
const parser = unified().use(markdown).use(mdjsStoryParse).use(html, { sanitize: false });
const result = await parser.process(input);
expect(result.contents).to.equal(expected);
});
it('will wrap following story-code blocks also for html stories', async () => {
const input = [
'```html preview-story',
'<my-el></my-el>',
'```',
'',
'```swift story-code',
'CODE for iOS',
'```',
'',
'```xml story-code',
'CODE for Android',
'```',
].join('\n');
const expected = [
'<mdjs-preview mdjs-story-name="HtmlStory0">',
'',
'',
'',
'<pre><code class="language-html">&#x3C;my-el>&#x3C;/my-el>',
'</code></pre>',
'<pre><code class="language-swift">CODE for iOS',
'</code></pre>',
'<pre><code class="language-xml">CODE for Android',
'</code></pre>',
'',
'',
'',
'</mdjs-preview>',
'',
].join('\n');
const parser = unified().use(markdown).use(mdjsStoryParse).use(html, { sanitize: false });
const result = await parser.process(input);
expect(result.contents).to.equal(expected);
});
it('will wrap only following story-code blocks', async () => {
const input = [
'```js preview-story',
'export const foo = () => {};',
'```',
'```swift story-code',
'CODE for iOS',
'```',
'# hey',
'```swift story-code',
'SHOULD BE OUTSIDE',
'```',
'```js preview-story',
'export const foo2 = () => {};',
'```',
'```xml story-code',
'CODE for Android',
'```',
].join('\n');
const expected = [
'<mdjs-preview mdjs-story-name="foo">',
'',
'',
'',
'<pre><code class="language-js">export const foo = () => {};',
'</code></pre>',
'<pre><code class="language-swift">CODE for iOS',
'</code></pre>',
'',
'',
'',
'</mdjs-preview>',
'<h1>hey</h1>',
'<pre><code class="language-swift">SHOULD BE OUTSIDE',
'</code></pre>',
'<mdjs-preview mdjs-story-name="foo2">',
'',
'',
'',
'<pre><code class="language-js">export const foo2 = () => {};',
'</code></pre>',
'<pre><code class="language-xml">CODE for Android',
'</code></pre>',
'',
'',
'',
'</mdjs-preview>',
'',
].join('\n');
const parser = unified().use(markdown).use(mdjsStoryParse).use(html, { sanitize: false });
const result = await parser.process(input); const result = await parser.process(input);
expect(result.contents).to.equal(expected); expect(result.contents).to.equal(expected);
}); });

View File

@@ -28,12 +28,6 @@ declare module 'rehype-autolink-headings' {
export = unified.Plugin; export = unified.Plugin;
} }
declare module 'rehype-prism-template' {
import unified from 'unified';
export = unified.Plugin;
}
declare module 'unist-util-remove' { declare module 'unist-util-remove' {
import unified from 'unified'; import unified from 'unified';

View File

@@ -1,5 +1,84 @@
# @mdjs/mdjs-preview # @mdjs/mdjs-preview
## 0.5.6
### Patch Changes
- e81b77f: Change theme attribute into preview-theme attribute to separate theme styling of the preview section and the full mdjs viewer.
- 456b8e7: Add css variable to style border-color of the mdjs-viewer
## 0.5.5
### Patch Changes
- 445b028: Update to latest lit, @open-wc, @lion packages
## 0.5.4
### Patch Changes
- 15a82c0: Enable including script files into the simulator via `<script src=".." mdjs-use>`
- 15a82c0: Allow only a limited set of characters for simulator includes `[a-zA-Z0-9\/\-_]`.
Notably, there is no:
- `:` to prevent `http://...` includes
- `.` so filenames as `this.is.my.js` are not supported. Also includes will be without file endings which will be added automatically
## 0.5.3
### Patch Changes
- 5c6b9c9: The Platform and Size controls are now moved above the preview.
For the web platform we added a special "inline" size.
Only when platform=web & size=webInline it will render to dom.
On all other selections it will render the preview via an iframe.
```js
sizes: [
{
key: 'webInline',
name: 'Inline',
platform: 'web',
width: 360,
height: 640,
dpr: 1,
},
{
// ...
},
];
```
- 6221e5f: If your preview is followed by a code blocks marked as `story-code` then those will be shown when switching between multiple platforms
````md
```js preview-story
// will be visible when platform web is selected
export const JsPreviewStory = () =>
html`
<demo-wc-card>JS Preview Story</demo-wc-card>
`;
```
```xml story-code
<!-- will be visible when platform android is selected -->
<Button
android:id="@+id/demoWcCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android Code"
style="@style/Widget.FooComponents.Demo.Wc.Card"
/>
```
```swift story-code
// will be visible when platform ios is selected
import DemoWc.Card
let card = DemoWcButton()
```
````
## 0.5.2 ## 0.5.2
### Patch Changes ### Patch Changes

View File

@@ -1,3 +1,3 @@
# Preview element for mdjs # Preview element for mdjs
For docs please see our homepage [https://rocket.modern-web.dev/docs/markdown-javascript/preview/](https://rocket.modern-web.dev/docs/markdown-javascript/preview/). [=> See Source <=](../../docs/docs/markdown-javascript/preview.md)

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mdjs/mdjs-preview", "name": "@mdjs/mdjs-preview",
"version": "0.5.2", "version": "0.5.6",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -21,6 +21,7 @@
}, },
"scripts": { "scripts": {
"debug": "cd ../../ && npm run debug -- --group mdjs-preview", "debug": "cd ../../ && npm run debug -- --group mdjs-preview",
"prepublishOnly": "publish-docs --github-url https://github.com/modernweb-dev/rocket/ --git-root-dir ../../",
"test": "npm run test:web", "test": "npm run test:web",
"test:web": "cd ../../ && npm run test:web -- --group mdjs-preview" "test:web": "cd ../../ && npm run test:web -- --group mdjs-preview"
}, },
@@ -31,9 +32,9 @@
"src" "src"
], ],
"dependencies": { "dependencies": {
"@lion/accordion": "^0.6.1", "@lion/accordion": "^0.7.2",
"@open-wc/scoped-elements": "^2.0.0-next.3", "@open-wc/scoped-elements": "^2.0.0",
"lit": "^2.0.0-rc.2" "lit": "^2.0.0"
}, },
"types": "dist-types/index.d.ts" "types": "dist-types/index.d.ts"
} }

View File

@@ -10,6 +10,16 @@ import {
} from './mdjsViewerSharedStates.js'; } from './mdjsViewerSharedStates.js';
import { addResizeHandler } from './resizeHandler.js'; import { addResizeHandler } from './resizeHandler.js';
/**
* @param {string} input
* @param {'js'|'css'} type
* @returns {string}
*/
function sanitize(input, type) {
const url = new URL(input);
return url.pathname.slice(1, (type.length + 1) * -1);
}
/** /**
* @typedef {object} StoryOptions * @typedef {object} StoryOptions
* @property {HTMLElement | null} StoryOptions.shadowRoot * @property {HTMLElement | null} StoryOptions.shadowRoot
@@ -47,11 +57,11 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
contentHeight: { type: Number }, contentHeight: { type: Number },
simulatorUrl: { type: String }, simulatorUrl: { type: String },
// page settings // page settings
platform: { type: String }, platform: { type: String, reflect: true },
platforms: { type: Array }, platforms: { type: Array },
size: { type: String }, size: { type: String },
sizes: { type: Array }, sizes: { type: Array },
theme: { type: String, reflect: true }, previewTheme: { type: String, reflect: true, attribute: 'preview-theme' },
themes: { type: Array }, themes: { type: Array },
language: { type: String }, language: { type: String },
languages: { type: Array }, languages: { type: Array },
@@ -72,7 +82,7 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
this.__supportsClipboard = 'clipboard' in navigator; this.__supportsClipboard = 'clipboard' in navigator;
this.__copyButtonText = 'Copy Code'; this.__copyButtonText = 'Copy Code';
this.theme = 'light'; this.previewTheme = 'light';
/** @type {{ key: string, name: string }[]} */ /** @type {{ key: string, name: string }[]} */
this.themes = [ this.themes = [
// { key: 'light', name: 'Light' }, // { key: 'light', name: 'Light' },
@@ -107,8 +117,16 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
// { key: 'ios', name: 'iOS' }, // { key: 'ios', name: 'iOS' },
]; ];
this.size = 'webSmall'; this.size = 'webInline';
this.sizes = [ this.sizes = [
{
key: 'webInline',
name: 'Inline',
platform: 'web',
width: 360,
height: 640,
dpr: 1,
},
{ {
key: 'webSmall', key: 'webSmall',
name: 'Small', name: 'Small',
@@ -241,6 +259,10 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
if (this.lightDomRenderTarget && changeProps.has('story')) { if (this.lightDomRenderTarget && changeProps.has('story')) {
render(this.story({ shadowRoot: this }), this.lightDomRenderTarget); render(this.story({ shadowRoot: this }), this.lightDomRenderTarget);
} }
if (changeProps.has('platform') || changeProps.has('size')) {
this.deviceMode = this.platform === 'web' && this.size === 'webInline' ? false : true;
}
} }
disconnectedCallback() { disconnectedCallback() {
@@ -261,11 +283,10 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
if (!mdjsSetupScript) { if (!mdjsSetupScript) {
throw new Error('Could not find a <script type="module" src="..." mdjs-setup></script>'); throw new Error('Could not find a <script type="module" src="..." mdjs-setup></script>');
} }
const params = new URLSearchParams(); const params = new URLSearchParams();
params.set('story-file', mdjsSetupScript.src); params.set('story-file', sanitize(mdjsSetupScript.src, 'js'));
params.set('story-key', this.key); params.set('story-key', this.key);
params.set('theme', this.theme); params.set('theme', this.previewTheme);
params.set('platform', this.platform); params.set('platform', this.platform);
params.set('language', this.language); params.set('language', this.language);
params.set('edge-distance', this.edgeDistance.toString()); params.set('edge-distance', this.edgeDistance.toString());
@@ -275,7 +296,16 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
]); ]);
for (const link of links) { for (const link of links) {
if (link.href) { if (link.href) {
params.append('stylesheets', link.href); params.append('stylesheets', sanitize(link.href, 'css'));
}
}
const moduleUrls = /** @type {HTMLScriptElement[]} */ ([
...document.querySelectorAll('script[type=module][mdjs-use]'),
]);
for (const moduleUrl of moduleUrls) {
if (moduleUrl.src) {
params.append('moduleUrls', sanitize(moduleUrl.src, 'js'));
} }
} }
@@ -292,8 +322,15 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
} }
async onCopy() { async onCopy() {
if (this.textContent) { let nodeToConsider = this.children[0];
await navigator.clipboard.writeText(this.textContent.trim()); if (this.platform === 'android') {
nodeToConsider = this.children[1];
}
if (this.platform === 'ios') {
nodeToConsider = this.children[2];
}
if (nodeToConsider && nodeToConsider.textContent) {
await navigator.clipboard.writeText(nodeToConsider.textContent.trim());
this.__copyButtonText = 'Copied ✅'; this.__copyButtonText = 'Copied ✅';
setTimeout(() => { setTimeout(() => {
this.__copyButtonText = 'Copy code'; this.__copyButtonText = 'Copy code';
@@ -304,7 +341,6 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
renderPlatforms() { renderPlatforms() {
if (this.platforms.length) { if (this.platforms.length) {
return html` return html`
<h4>Platform</h4>
<div <div
class="segmented-control" class="segmented-control"
@change=${ @change=${
@@ -337,17 +373,27 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
if (this.platforms.length) { if (this.platforms.length) {
return html` return html`
<div> <div>
<h3>Platform</h3> <h4>Platform</h4>
${this.renderPlatforms()} ${this.renderPlatforms()}
</div> </div>
`; `;
} }
} }
renderSize() {
if (this.sizes.length) {
return html`
<div>
<h4>Size</h4>
${this.renderSizes()}
</div>
`;
}
}
renderSizes() { renderSizes() {
if (this.sizes.length) { if (this.sizes.length) {
return html` return html`
<h4>Size</h4>
<div <div
class="segmented-control" class="segmented-control"
@change=${ @change=${
@@ -380,7 +426,7 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
return html` return html`
<div> <div>
<h3>Viewport</h3> <h3>Viewport</h3>
${this.renderSizes()} ${this.renderAutoHeight()} ${this.renderAutoHeight()}
</div> </div>
`; `;
} }
@@ -393,20 +439,20 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
@change=${ @change=${
/** @param {Event} ev */ ev => { /** @param {Event} ev */ ev => {
if (ev.target) { if (ev.target) {
this.theme = /** @type {HTMLInputElement} */ (ev.target).value; this.previewTheme = /** @type {HTMLInputElement} */ (ev.target).value;
} }
} }
} }
> >
${this.themes.map( ${this.themes.map(
theme => html` previewTheme => html`
<label class="${this.theme === theme.key ? 'selected' : ''}"> <label class="${this.previewTheme === previewTheme.key ? 'selected' : ''}">
<span>${theme.name}</span> <span>${previewTheme.name}</span>
<input <input
type="radio" type="radio"
name="theme" name="theme"
value="${theme.key}" value="${previewTheme.key}"
?checked=${this.theme === theme.key} ?checked=${this.previewTheme === previewTheme.key}
/> />
</label> </label>
`, `,
@@ -564,6 +610,11 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
render() { render() {
return html` return html`
${this.simulatorUrl
? html`
<div class="platform-size-controls">${this.renderPlatform()} ${this.renderSize()}</div>
`
: ``}
<div id="wrapper"> <div id="wrapper">
<slot name="story"></slot> <slot name="story"></slot>
${this.deviceMode === true ${this.deviceMode === true
@@ -581,19 +632,28 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
: nothing} : nothing}
</div> </div>
<lion-accordion class="options"> <lion-accordion class="options">
${this.deviceMode ${this.simulatorUrl
? html` ? html`
<h3 slot="invoker"> <h3 slot="invoker">
<button>Settings</button> <button>Settings</button>
</h3> </h3>
<div slot="content"> <div slot="content">
${this.deviceMode
? ``
: html`<div>
Note: Additional settings become available when not in web inline mode
</div>`}
<div class="settings-wrapper"> <div class="settings-wrapper">
${this.renderPlatform()} ${this.renderViewport()} ${this.renderVisual()} ${this.deviceMode
${this.renderLocalization()} ${this.renderSyncSettings()} ? html`
${this.renderViewport()} ${this.renderVisual()} ${this.renderLocalization()}
${this.renderSyncSettings()}
`
: html` ${this.renderSyncSettings()} `}
</div> </div>
</div> </div>
` `
: ''} : ``}
<h3 slot="invoker"> <h3 slot="invoker">
<button>Code</button> <button>Code</button>
</h3> </h3>
@@ -608,12 +668,6 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
? html` ? html`
<div class="controls"> <div class="controls">
<a href=${this.iframeUrl} target="_blank">Open simulation in new window</a> <a href=${this.iframeUrl} target="_blank">Open simulation in new window</a>
<button
@click=${() => (this.deviceMode = !this.deviceMode)}
class="simulation-toggle"
>
${this.deviceMode ? html`Disable` : html`Enable`} device simulation
</button>
</div> </div>
` `
: ''} : ''}
@@ -631,8 +685,12 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
display: none; display: none;
} }
:host(:not([device-mode])) #wrapper {
border: 2px solid var(--primary-lines-color, #4caf50);
}
iframe { iframe {
border: 2px solid #4caf50; border: 2px solid var(--primary-lines-color, #4caf50);
background: #fff; background: #fff;
} }
@@ -725,6 +783,15 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
padding: 15px 0; padding: 15px 0;
} }
.platform-size-controls {
display: flex;
justify-content: flex-start;
}
.platform-size-controls > * {
margin-right: 25px;
}
.controls { .controls {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -845,6 +912,21 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
border: 1px solid #333; border: 1px solid #333;
border-radius: 3px; border-radius: 3px;
} }
/** Showing/Hiding additional code blocks **/
::slotted(pre) {
display: none;
}
:host([platform='web']) ::slotted(pre:nth-child(1)) {
display: block;
}
:host([platform='android']) ::slotted(pre:nth-child(2)) {
display: block;
}
:host([platform='ios']) ::slotted(pre:nth-child(3)) {
display: block;
}
`; `;
} }
} }

View File

@@ -1,7 +1,7 @@
const _sharedStates = { const _sharedStates = {
platform: 'web', platform: 'web',
size: 'webSmall', size: 'webSmall',
theme: 'light', previewTheme: 'light',
language: 'en', language: 'en',
autoHeight: true, autoHeight: true,
deviceMode: false, deviceMode: false,

View File

@@ -28,11 +28,8 @@ describe('mdjs-preview', () => {
expect(preview1.edgeDistance).to.be.true; expect(preview1.edgeDistance).to.be.true;
expect(preview2.edgeDistance).to.be.true; expect(preview2.edgeDistance).to.be.true;
preview1.platform = 'android';
preview1.edgeDistance = false; preview1.edgeDistance = false;
await preview1.updateComplete; await preview1.updateComplete;
expect(preview1.platform).to.equal('android');
expect(preview2.platform).to.equal('android');
expect(preview1.edgeDistance).to.be.false; expect(preview1.edgeDistance).to.be.false;
expect(preview2.edgeDistance).to.be.false; expect(preview2.edgeDistance).to.be.false;
}); });

View File

@@ -1,5 +1,11 @@
# @mdjs/mdjs-story # @mdjs/mdjs-story
## 0.3.1
### Patch Changes
- 445b028: Update to latest lit, @open-wc, @lion packages
## 0.3.0 ## 0.3.0
### Minor Changes ### Minor Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mdjs/mdjs-story", "name": "@mdjs/mdjs-story",
"version": "0.3.0", "version": "0.3.1",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -31,7 +31,7 @@
"src" "src"
], ],
"dependencies": { "dependencies": {
"lit": "^2.0.0-rc.2" "lit": "^2.0.0"
}, },
"types": "dist-types/index.d.ts" "types": "dist-types/index.d.ts"
} }

View File

@@ -1,5 +1,11 @@
# plugins-manager # plugins-manager
## 0.3.1
### Patch Changes
- 7e277cd: Add a "hidden" feature in addPlugin that if you attach a `wrapPlugin` property to the returning function it will call `wrapPlugin` on the plugin before adding it.
## 0.3.0 ## 0.3.0
### Minor Changes ### Minor Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "plugins-manager", "name": "plugins-manager",
"version": "0.3.0", "version": "0.3.1",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -23,10 +23,10 @@
}, },
"scripts": { "scripts": {
"build:package": "rimraf dist && esbuild --platform=node --format=cjs --bundle --outfile=dist/index.cjs ./index.js", "build:package": "rimraf dist && esbuild --platform=node --format=cjs --bundle --outfile=dist/index.cjs ./index.js",
"prepublishOnly": "publish-docs --github-url https://github.com/modernweb-dev/rocket/ --git-root-dir ../../",
"test": "mocha --timeout 5000 test-node/**/*.test.{js,cjs} test-node/*.test.{js,cjs}", "test": "mocha --timeout 5000 test-node/**/*.test.{js,cjs} test-node/*.test.{js,cjs}",
"test:watch": "onchange 'src/**/*.{js,cjs}' 'test-node/**/*.{js,cjs}' -- npm test", "test:watch": "onchange 'src/**/*.{js,cjs}' 'test-node/**/*.{js,cjs}' -- npm test",
"types:copy": "copyfiles \"./types/**/*.d.ts\" dist-types/", "types:copy": "copyfiles \"./types/**/*.d.ts\" dist-types/"
"prepublishOnly": "publish-docs --github-url https://github.com/modernweb-dev/rocket/ --git-root-dir ../../"
}, },
"files": [ "files": [
"*.js", "*.js",

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
/** /**
* @template {import('../types/main').Plugin} T * @template {import('../types/main').Plugin} T
* @param {T} plugin * @param {T} plugin
@@ -12,6 +13,10 @@ export function addPlugin(plugin, options = {}, { how = 'after', location = 'bot
if (plugins === undefined) { if (plugins === undefined) {
plugins = []; plugins = [];
} }
// @ts-ignore
const usePlugin = addPluginFn.wrapPlugin ? addPluginFn.wrapPlugin(plugin) : plugin;
// only add if name is not already in the meta plugin list // only add if name is not already in the meta plugin list
if (plugins.findIndex(pluginObj => pluginObj.plugin === plugin) === -1) { if (plugins.findIndex(pluginObj => pluginObj.plugin === plugin) === -1) {
let index = -1; let index = -1;
@@ -40,7 +45,7 @@ export function addPlugin(plugin, options = {}, { how = 'after', location = 'bot
} }
plugins.splice(index, 0, { plugins.splice(index, 0, {
plugin, plugin: usePlugin,
options, options,
}); });
} }

View File

@@ -109,4 +109,18 @@ describe('addPlugin', () => {
}); });
expect(config.plugins).to.deep.equal(['-- newFirst last Plugin --']); expect(config.plugins).to.deep.equal(['-- newFirst last Plugin --']);
}); });
it('[advanced] can add a `wrapPlugin` property to the function itself which will call it on the plugin on init', async () => {
function myWrapper(plugin) {
return () => 'wrapped' + plugin();
}
const config = applyPlugins({
setupPlugins: [addPlugin(insertPlugin)].map(mod => {
mod.wrapPlugin = myWrapper;
return mod;
}),
});
expect(config.plugins).to.deep.equal(['wrapped-- first last Plugin --']);
});
}); });

View File

@@ -1,5 +1,11 @@
# @rocket/search # @rocket/search
## 0.5.1
### Patch Changes
- 445b028: Update to latest lit, @open-wc, @lion packages
## 0.5.0 ## 0.5.0
### Minor Changes ### Minor Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@rocket/search", "name": "@rocket/search",
"version": "0.5.0", "version": "0.5.1",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -42,10 +42,10 @@
"search" "search"
], ],
"dependencies": { "dependencies": {
"@lion/combobox": "^0.8.0", "@lion/combobox": "^0.8.6",
"@lion/core": "^0.18.0", "@lion/core": "^0.19.0",
"@lion/listbox": "^0.10.1", "@lion/listbox": "^0.10.7",
"@open-wc/scoped-elements": "^2.0.0-next.3", "@open-wc/scoped-elements": "^2.0.0",
"chalk": "^4.0.0", "chalk": "^4.0.0",
"minisearch": "^3.0.2", "minisearch": "^3.0.2",
"plugins-manager": "^0.3.0", "plugins-manager": "^0.3.0",

View File

@@ -189,7 +189,7 @@ export class RocketSearchCombobox extends LionCombobox {
} }
static get properties() { static get properties() {
return /** @type {typeof LionCombobox['properties'] & { showInput: import("lit-element").PropertyDeclaration } } */ ({ return /** @type {typeof LionCombobox['properties'] & { showInput: import("lit").PropertyDeclaration } } */ ({
showInput: { type: Boolean, reflect: true, attribute: 'show-input' }, showInput: { type: Boolean, reflect: true, attribute: 'show-input' },
}); });
} }

1444
yarn.lock

File diff suppressed because it is too large Load Diff