Compare commits

..

7 Commits

Author SHA1 Message Date
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
31 changed files with 1116 additions and 371 deletions

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

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

@@ -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",

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

@@ -1,5 +1,16 @@
# @rocket/cli # @rocket/cli
## 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.1",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },

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

@@ -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,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,43 @@
# Change Log # Change Log
## 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.1",
"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,7 +45,7 @@
"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",

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

@@ -114,4 +114,136 @@ describe('mdjsStoryParse', () => {
const result = await parser.process(input); const result = await parser.process(input);
expect(result.contents).to.equal(expected); 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);
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);
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);
const result = await parser.process(input);
expect(result.contents).to.equal(expected);
});
}); });

View File

@@ -1,5 +1,71 @@
# @mdjs/mdjs-preview # @mdjs/mdjs-preview
## 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.4",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -20,6 +20,7 @@
"./define": "./src/define/define.js" "./define": "./src/define/define.js"
}, },
"scripts": { "scripts": {
"prepublishOnly": "publish-docs --github-url https://github.com/modernweb-dev/rocket/ --git-root-dir ../../",
"debug": "cd ../../ && npm run debug -- --group mdjs-preview", "debug": "cd ../../ && npm run debug -- --group mdjs-preview",
"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"

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,7 +57,7 @@ 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 },
@@ -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,9 +283,8 @@ 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.theme);
params.set('platform', this.platform); params.set('platform', this.platform);
@@ -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>
`; `;
} }
@@ -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,6 +685,10 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
display: none; display: none;
} }
:host(:not([device-mode])) #wrapper {
border: 2px solid #4caf50;
}
iframe { iframe {
border: 2px solid #4caf50; border: 2px solid #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

@@ -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

@@ -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",

228
yarn.lock
View File

@@ -1475,6 +1475,11 @@
resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.9.tgz#01d7b86949f455402a94c788883fe4ba574cad41" resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.9.tgz#01d7b86949f455402a94c788883fe4ba574cad41"
integrity sha512-qZLoYeXSTgQuK1h7QQS16hqLGdmqtRmN8w/rl3Au/l5x/zkHx+a4VHrHyBsi1I1vtK2oBHxSzKIu0R5p6spdOA== integrity sha512-qZLoYeXSTgQuK1h7QQS16hqLGdmqtRmN8w/rl3Au/l5x/zkHx+a4VHrHyBsi1I1vtK2oBHxSzKIu0R5p6spdOA==
"@types/babel__code-frame@^7.0.2":
version "7.0.3"
resolved "https://registry.yarnpkg.com/@types/babel__code-frame/-/babel__code-frame-7.0.3.tgz#eda94e1b7c9326700a4b69c485ebbc9498a0b63f"
integrity sha512-2TN6oiwtNjOezilFVl77zwdNPwQWaDBBCCWWxyo1ctiO3vAtd7H/aB/CBJdw9+kqq3+latD0SXoedIuHySSZWw==
"@types/babylon@^6.16.2": "@types/babylon@^6.16.2":
version "6.16.5" version "6.16.5"
resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.5.tgz#1c5641db69eb8cdf378edd25b4be7754beeb48b4" resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.5.tgz#1c5641db69eb8cdf378edd25b4be7754beeb48b4"
@@ -1507,6 +1512,14 @@
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.18.tgz#0c8e298dbff8205e2266606c1ea5fbdba29b46e4" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.18.tgz#0c8e298dbff8205e2266606c1ea5fbdba29b46e4"
integrity sha512-rS27+EkB/RE1Iz3u0XtVL5q36MGDWbgYe7zWiodyKNUnthxY0rukK5V36eiUCtCisB7NN8zKYH6DO2M37qxFEQ== integrity sha512-rS27+EkB/RE1Iz3u0XtVL5q36MGDWbgYe7zWiodyKNUnthxY0rukK5V36eiUCtCisB7NN8zKYH6DO2M37qxFEQ==
"@types/co-body@^6.1.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@types/co-body/-/co-body-6.1.0.tgz#b52625390eb0d113c9b697ea92c3ffae7740cdb9"
integrity sha512-3e0q2jyDAnx/DSZi0z2H0yoZ2wt5yRDZ+P7ymcMObvq0ufWRT4tsajyO+Q1VwVWiv9PRR4W3YEjEzBjeZlhF+w==
dependencies:
"@types/node" "*"
"@types/qs" "*"
"@types/command-line-args@^5.0.0": "@types/command-line-args@^5.0.0":
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/@types/command-line-args/-/command-line-args-5.0.0.tgz#484e704d20dbb8754a8f091eee45cdd22bcff28c" resolved "https://registry.yarnpkg.com/@types/command-line-args/-/command-line-args-5.0.0.tgz#484e704d20dbb8754a8f091eee45cdd22bcff28c"
@@ -1524,6 +1537,11 @@
resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.3.tgz#0aa116701955c2faa0717fc69cd1596095e49d96" resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.3.tgz#0aa116701955c2faa0717fc69cd1596095e49d96"
integrity sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg== integrity sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==
"@types/convert-source-map@^1.5.1":
version "1.5.2"
resolved "https://registry.yarnpkg.com/@types/convert-source-map/-/convert-source-map-1.5.2.tgz#318dc22d476632a4855594c16970c6dc3ed086e7"
integrity sha512-tHs++ZeXer40kCF2JpE51Hg7t4HPa18B1b1Dzy96S0eCw8QKECNMYMfwa1edK/x8yCN0r4e6ewvLcc5CsVGkdg==
"@types/cookies@*": "@types/cookies@*":
version "0.7.6" version "0.7.6"
resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.6.tgz#71212c5391a976d3bae57d4b09fac20fc6bda504" resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.6.tgz#71212c5391a976d3bae57d4b09fac20fc6bda504"
@@ -1534,6 +1552,11 @@
"@types/keygrip" "*" "@types/keygrip" "*"
"@types/node" "*" "@types/node" "*"
"@types/debounce@^1.2.0":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@types/debounce/-/debounce-1.2.1.tgz#79b65710bc8b6d44094d286aecf38e44f9627852"
integrity sha512-epMsEE85fi4lfmJUH/89/iV/LI+F5CvNIvmgs5g5jYFPfhO2S/ae8WSsLOKWdwtoaZw9Q2IhJ4tQ5tFCcS/4HA==
"@types/debug@^4.0.0": "@types/debug@^4.0.0":
version "4.1.6" version "4.1.6"
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.6.tgz#0b7018723084918a865eff99249c490505df2163" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.6.tgz#0b7018723084918a865eff99249c490505df2163"
@@ -1600,11 +1623,25 @@
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.0.tgz#682477dbbbd07cd032731cb3b0e7eaee3d026b69" resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.0.tgz#682477dbbbd07cd032731cb3b0e7eaee3d026b69"
integrity sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA== integrity sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA==
"@types/istanbul-lib-coverage@^2.0.1": "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.1", "@types/istanbul-lib-coverage@^2.0.3":
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==
"@types/istanbul-lib-report@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686"
integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==
dependencies:
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-reports@^3.0.0":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff"
integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==
dependencies:
"@types/istanbul-lib-report" "*"
"@types/json-schema@^7.0.3": "@types/json-schema@^7.0.3":
version "7.0.6" version "7.0.6"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
@@ -1705,6 +1742,11 @@
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109"
integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==
"@types/parse5@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.1.tgz#f8ae4fbcd2b9ba4ff934698e28778961f9cb22ca"
integrity sha512-ARATsLdrGPUnaBvxLhUlnltcMgn7pQG312S8ccdYlnyijabrX9RN/KN/iGj9Am96CoW8e/K9628BA7Bv4XHdrA==
"@types/qs@*": "@types/qs@*":
version "6.9.5" version "6.9.5"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b"
@@ -1869,6 +1911,13 @@
dependencies: dependencies:
errorstacks "^2.2.0" errorstacks "^2.2.0"
"@web/browser-logs@^0.2.1":
version "0.2.5"
resolved "https://registry.yarnpkg.com/@web/browser-logs/-/browser-logs-0.2.5.tgz#0895efb641eacb0fbc1138c6092bd18c01df2734"
integrity sha512-Qxo1wY/L7yILQqg0jjAaueh+tzdORXnZtxQgWH23SsTCunz9iq9FvsZa8Q5XlpjnZ3vLIsFEuEsCMqFeohJnEg==
dependencies:
errorstacks "^2.2.0"
"@web/config-loader@^0.1.3": "@web/config-loader@^0.1.3":
version "0.1.3" version "0.1.3"
resolved "https://registry.yarnpkg.com/@web/config-loader/-/config-loader-0.1.3.tgz#8325ea54f75ef2ee7166783e64e66936db25bff7" resolved "https://registry.yarnpkg.com/@web/config-loader/-/config-loader-0.1.3.tgz#8325ea54f75ef2ee7166783e64e66936db25bff7"
@@ -1876,6 +1925,30 @@
dependencies: dependencies:
semver "^7.3.4" semver "^7.3.4"
"@web/dev-server-core@^0.3.16":
version "0.3.16"
resolved "https://registry.yarnpkg.com/@web/dev-server-core/-/dev-server-core-0.3.16.tgz#7404383d05031f462a29f578dc35948d0af35344"
integrity sha512-nj6liCErIGtpuZYPf6QaxGQ9nlaHd8Cf/NBcRhogskvjOVFkF3FS9xpjRw3WidkmOQnk+D0ZGCeXjtTibgy5CA==
dependencies:
"@types/koa" "^2.11.6"
"@types/ws" "^7.4.0"
"@web/parse5-utils" "^1.2.0"
chokidar "^3.4.3"
clone "^2.1.2"
es-module-lexer "^0.9.0"
get-stream "^6.0.0"
is-stream "^2.0.0"
isbinaryfile "^4.0.6"
koa "^2.13.0"
koa-etag "^4.0.0"
koa-send "^5.0.1"
koa-static "^5.0.0"
lru-cache "^6.0.0"
mime-types "^2.1.27"
parse5 "^6.0.1"
picomatch "^2.2.2"
ws "^7.4.2"
"@web/dev-server-core@^0.3.2", "@web/dev-server-core@^0.3.3": "@web/dev-server-core@^0.3.2", "@web/dev-server-core@^0.3.3":
version "0.3.3" version "0.3.3"
resolved "https://registry.yarnpkg.com/@web/dev-server-core/-/dev-server-core-0.3.3.tgz#814bc86460c43ab9d66b640f2b3b65d452ce30e0" resolved "https://registry.yarnpkg.com/@web/dev-server-core/-/dev-server-core-0.3.3.tgz#814bc86460c43ab9d66b640f2b3b65d452ce30e0"
@@ -1940,6 +2013,14 @@
"@types/parse5" "^5.0.3" "@types/parse5" "^5.0.3"
parse5 "^6.0.1" parse5 "^6.0.1"
"@web/parse5-utils@^1.2.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@web/parse5-utils/-/parse5-utils-1.3.0.tgz#e2e9e98b31a4ca948309f74891bda8d77399f6bd"
integrity sha512-Pgkx3ECc8EgXSlS5EyrgzSOoUbM6P8OKS471HLAyvOBcP1NCBn0to4RN/OaKASGq8qa3j+lPX9H14uA5AHEnQg==
dependencies:
"@types/parse5" "^6.0.1"
parse5 "^6.0.1"
"@web/parse5-utils@^1.2.2": "@web/parse5-utils@^1.2.2":
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/@web/parse5-utils/-/parse5-utils-1.2.2.tgz#33eec93321eb07cf364651c131b980a7afd8c4d7" resolved "https://registry.yarnpkg.com/@web/parse5-utils/-/parse5-utils-1.2.2.tgz#33eec93321eb07cf364651c131b980a7afd8c4d7"
@@ -2039,6 +2120,38 @@
picomatch "^2.2.2" picomatch "^2.2.2"
uuid "^8.3.2" uuid "^8.3.2"
"@web/test-runner-core@^0.10.20":
version "0.10.21"
resolved "https://registry.yarnpkg.com/@web/test-runner-core/-/test-runner-core-0.10.21.tgz#fe8a01f3595330940189ff4b9d32514ede55d184"
integrity sha512-Dh1TJITyil4w22DXwCmYEyp4BBzRFxRqiUbJ/iPziT1E5heAx/pZPug1oFs83LKUc/crOcDhObz6u4ynGWz9wQ==
dependencies:
"@babel/code-frame" "^7.12.11"
"@types/babel__code-frame" "^7.0.2"
"@types/co-body" "^6.1.0"
"@types/convert-source-map" "^1.5.1"
"@types/debounce" "^1.2.0"
"@types/istanbul-lib-coverage" "^2.0.3"
"@types/istanbul-reports" "^3.0.0"
"@web/browser-logs" "^0.2.1"
"@web/dev-server-core" "^0.3.16"
chokidar "^3.4.3"
cli-cursor "^3.1.0"
co-body "^6.1.0"
convert-source-map "^1.7.0"
debounce "^1.2.0"
dependency-graph "^0.11.0"
globby "^11.0.1"
ip "^1.1.5"
istanbul-lib-coverage "^3.0.0"
istanbul-lib-report "^3.0.0"
istanbul-reports "^3.0.2"
log-update "^4.0.0"
nanocolors "^0.2.1"
nanoid "^3.1.25"
open "^8.0.2"
picomatch "^2.2.2"
source-map "^0.7.3"
"@web/test-runner-coverage-v8@^0.4.0": "@web/test-runner-coverage-v8@^0.4.0":
version "0.4.0" version "0.4.0"
resolved "https://registry.yarnpkg.com/@web/test-runner-coverage-v8/-/test-runner-coverage-v8-0.4.0.tgz#8289d12fb826c92c1d3cb8334b9e580a3b99927c" resolved "https://registry.yarnpkg.com/@web/test-runner-coverage-v8/-/test-runner-coverage-v8-0.4.0.tgz#8289d12fb826c92c1d3cb8334b9e580a3b99927c"
@@ -2048,6 +2161,16 @@
istanbul-lib-coverage "^3.0.0" istanbul-lib-coverage "^3.0.0"
v8-to-istanbul "^7.1.0" v8-to-istanbul "^7.1.0"
"@web/test-runner-coverage-v8@^0.4.8":
version "0.4.8"
resolved "https://registry.yarnpkg.com/@web/test-runner-coverage-v8/-/test-runner-coverage-v8-0.4.8.tgz#d4ff9ebd9c48312d09a7391abbfdfc47f21e9d0d"
integrity sha512-Ib0AscR8Xf9E/V7rf3XOVQTe4vKIbwSTupxV1xGgzj3x4RKUuMUg9FLz9EigZ5iN0mOzZKDllyRS523hbdhDtA==
dependencies:
"@web/test-runner-core" "^0.10.20"
istanbul-lib-coverage "^3.0.0"
picomatch "^2.2.2"
v8-to-istanbul "^8.0.0"
"@web/test-runner-mocha@^0.7.0": "@web/test-runner-mocha@^0.7.0":
version "0.7.0" version "0.7.0"
resolved "https://registry.yarnpkg.com/@web/test-runner-mocha/-/test-runner-mocha-0.7.0.tgz#1c844ee0446345deacfbbfeae614db7d45a1a7dc" resolved "https://registry.yarnpkg.com/@web/test-runner-mocha/-/test-runner-mocha-0.7.0.tgz#1c844ee0446345deacfbbfeae614db7d45a1a7dc"
@@ -2056,14 +2179,14 @@
"@types/mocha" "^8.2.0" "@types/mocha" "^8.2.0"
"@web/test-runner-core" "^0.10.0" "@web/test-runner-core" "^0.10.0"
"@web/test-runner-playwright@^0.8.0": "@web/test-runner-playwright@^0.8.8":
version "0.8.0" version "0.8.8"
resolved "https://registry.yarnpkg.com/@web/test-runner-playwright/-/test-runner-playwright-0.8.0.tgz#65c4f31edf8db845960c2af10e5b40b213274351" resolved "https://registry.yarnpkg.com/@web/test-runner-playwright/-/test-runner-playwright-0.8.8.tgz#c06de60c0283611f5f0ef478779a7605a35e0895"
integrity sha512-VoRfBxioOJuUFRROcwKkXL75iRtf4Qc9zVSGUvVlCZoLstG5EuqYyuvIdnGCkcf/sqCXsAh1WbQ+wfRXd7h6Cw== integrity sha512-bhb0QVldfDoPJqOj5mm1hpE6FReyddc/iIuAkVf/kbJvgggTCT2bWGxUvXJlGzf+4epmDhU+hSTfEoLL9R2vGw==
dependencies: dependencies:
"@web/test-runner-core" "^0.10.0" "@web/test-runner-core" "^0.10.20"
"@web/test-runner-coverage-v8" "^0.4.0" "@web/test-runner-coverage-v8" "^0.4.8"
playwright "^1.7.1" playwright "^1.14.0"
"@web/test-runner@^0.12.2": "@web/test-runner@^0.12.2":
version "0.12.2" version "0.12.2"
@@ -3146,7 +3269,7 @@ commander@^5.1.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
commander@^6.2.0: commander@^6.1.0, commander@^6.2.0:
version "6.2.1" version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
@@ -3534,6 +3657,11 @@ defaults@^1.0.3:
dependencies: dependencies:
clone "^1.0.2" clone "^1.0.2"
define-lazy-prop@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
define-properties@^1.1.2, define-properties@^1.1.3: define-properties@^1.1.2, define-properties@^1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -3586,6 +3714,11 @@ dependency-graph@^0.10.0:
resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.10.0.tgz#dfebe384f1f36faf7782be203a7a71102a6335a6" resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.10.0.tgz#dfebe384f1f36faf7782be203a7a71102a6335a6"
integrity sha512-c9amUgpgxSi1bE5/sbLwcs5diLD0ygCQYmhfM5H1s5VH1mCsYkcmAL3CcNdv4kdSw6JuMoHeDGzLgj/gAXdWVg== integrity sha512-c9amUgpgxSi1bE5/sbLwcs5diLD0ygCQYmhfM5H1s5VH1mCsYkcmAL3CcNdv4kdSw6JuMoHeDGzLgj/gAXdWVg==
dependency-graph@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27"
integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==
dependency-graph@^0.9.0: dependency-graph@^0.9.0:
version "0.9.0" version "0.9.0"
resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.9.0.tgz#11aed7e203bc8b00f48356d92db27b265c445318" resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.9.0.tgz#11aed7e203bc8b00f48356d92db27b265c445318"
@@ -3897,6 +4030,11 @@ es-module-lexer@^0.3.26:
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.3.26.tgz#7b507044e97d5b03b01d4392c74ffeb9c177a83b" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.3.26.tgz#7b507044e97d5b03b01d4392c74ffeb9c177a83b"
integrity sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA== integrity sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA==
es-module-lexer@^0.9.0:
version "0.9.3"
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19"
integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==
es-to-primitive@^1.2.1: es-to-primitive@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
@@ -3938,6 +4076,11 @@ escape-string-regexp@4.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
escape-string-regexp@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
escape-string-regexp@^5.0.0: escape-string-regexp@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8"
@@ -5153,6 +5296,11 @@ is-docker@^2.0.0:
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156"
integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==
is-docker@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
is-expression@^3.0.0: is-expression@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-3.0.0.tgz#39acaa6be7fd1f3471dc42c7416e61c24317ac9f" resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-3.0.0.tgz#39acaa6be7fd1f3471dc42c7416e61c24317ac9f"
@@ -6677,11 +6825,21 @@ mustache@^2.3.2:
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5"
integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==
nanocolors@^0.2.1:
version "0.2.12"
resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.2.12.tgz#4d05932e70116078673ea4cc6699a1c56cc77777"
integrity sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug==
nanoid@3.1.12: nanoid@3.1.12:
version "3.1.12" version "3.1.12"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654"
integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A== integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==
nanoid@^3.1.25:
version "3.1.29"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.29.tgz#214fb2d7a33e1a5bef4757b779dfaeb6a4e5aeb4"
integrity sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg==
napi-build-utils@^1.0.1: napi-build-utils@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806"
@@ -6961,6 +7119,15 @@ open@^7.3.0:
is-docker "^2.0.0" is-docker "^2.0.0"
is-wsl "^2.1.1" is-wsl "^2.1.1"
open@^8.0.2:
version "8.3.0"
resolved "https://registry.yarnpkg.com/open/-/open-8.3.0.tgz#fdef1cdfe405e60dec8ebd18889e7e812f39c59f"
integrity sha512-7INcPWb1UcOwSQxAXTnBJ+FxVV4MPs/X++FWWBtgY69/J5lc+tCteMt/oFK1MnkyHC4VILLa9ntmwKTwDR4Q9w==
dependencies:
define-lazy-prop "^2.0.0"
is-docker "^2.1.1"
is-wsl "^2.2.0"
opencollective-postinstall@^2.0.2: opencollective-postinstall@^2.0.2:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
@@ -7341,11 +7508,12 @@ pkg-dir@^5.0.0:
dependencies: dependencies:
find-up "^5.0.0" find-up "^5.0.0"
playwright@^1.7.1: playwright@^1.14.0:
version "1.7.1" version "1.15.2"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.7.1.tgz#841638811bc39eb2fed792ffaacbcc959a0aaf5e" resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.15.2.tgz#b350056d1fffbe5de5b1bdaca6ab73e35758baad"
integrity sha512-dOSWME42wDedJ/PXv8k0zG0Kxd6d6R2OKA51/05++Z2ISdA4N58gHlWqlVKPDkBog1MI6lu/KNt7QDn19AybWQ== integrity sha512-+Z+7ckihyxR6rK5q8DWC6eUbKARfXpyxpjNcoJfgwSr64lAOzjhyFQiPC/JkdIqhsLgZjxpWfl1S7fLb+wPkgA==
dependencies: dependencies:
commander "^6.1.0"
debug "^4.1.1" debug "^4.1.1"
extract-zip "^2.0.1" extract-zip "^2.0.1"
https-proxy-agent "^5.0.0" https-proxy-agent "^5.0.0"
@@ -7356,7 +7524,9 @@ playwright@^1.7.1:
proper-lockfile "^4.1.1" proper-lockfile "^4.1.1"
proxy-from-env "^1.1.0" proxy-from-env "^1.1.0"
rimraf "^3.0.2" rimraf "^3.0.2"
ws "^7.3.1" stack-utils "^2.0.3"
ws "^7.4.6"
yazl "^2.5.1"
please-upgrade-node@^3.2.0: please-upgrade-node@^3.2.0:
version "3.2.0" version "3.2.0"
@@ -8686,6 +8856,13 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
stack-utils@^2.0.3:
version "2.0.5"
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5"
integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==
dependencies:
escape-string-regexp "^2.0.0"
"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@^1.5.0: "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@^1.5.0:
version "1.5.0" version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
@@ -9518,6 +9695,15 @@ v8-to-istanbul@^7.1.0:
convert-source-map "^1.6.0" convert-source-map "^1.6.0"
source-map "^0.7.3" source-map "^0.7.3"
v8-to-istanbul@^8.0.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz#0aeb763894f1a0a1676adf8a8b7612a38902446c"
integrity sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==
dependencies:
"@types/istanbul-lib-coverage" "^2.0.1"
convert-source-map "^1.6.0"
source-map "^0.7.3"
valid-url@^1.0.9: valid-url@^1.0.9:
version "1.0.9" version "1.0.9"
resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
@@ -9761,7 +9947,7 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
ws@^7.2.3, ws@^7.3.1: ws@^7.2.3:
version "7.4.1" version "7.4.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.1.tgz#a333be02696bd0e54cea0434e21dcc8a9ac294bb" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.1.tgz#a333be02696bd0e54cea0434e21dcc8a9ac294bb"
integrity sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ== integrity sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==
@@ -9771,6 +9957,11 @@ ws@^7.4.2:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd"
integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA== integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==
ws@^7.4.6:
version "7.5.5"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881"
integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==
ws@~3.3.1: ws@~3.3.1:
version "3.3.3" version "3.3.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
@@ -9942,6 +10133,13 @@ yauzl@^2.10.0:
buffer-crc32 "~0.2.3" buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0" fd-slicer "~1.1.0"
yazl@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35"
integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==
dependencies:
buffer-crc32 "~0.2.3"
yeast@0.1.2: yeast@0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"