Compare commits

...

47 Commits

Author SHA1 Message Date
github-actions[bot]
26d3de1444 Version Packages 2022-01-30 11:48:03 +01:00
Thomas Allmer
1f141058c1 fix(drawer): add export map with /define side effect import 2022-01-30 11:45:47 +01:00
github-actions[bot]
08574c9b31 Version Packages 2022-01-05 09:34:58 +01:00
gvangeest
e81b77f236 fix(mdjs-preview): separate preview and viewer theme styling 2022-01-03 18:36:09 +01:00
qa46hx
456b8e78f0 fix(mdjs-preview): add css variable to border-color of viewer 2021-12-05 13:30:28 +01:00
github-actions[bot]
0d7ea015af Version Packages 2021-11-16 18:48:20 +01:00
Thomas Allmer
445b02872f fix: update to latest lit, @open-wc, @lion packages 2021-11-16 17:07:53 +01:00
Thomas Allmer
1a599db3ed chore: lock file maintainance 2021-11-16 08:05:37 +01:00
Thomas Allmer
6b6bed5391 chore: update remark-html 2021-11-16 08:05:37 +01:00
github-actions[bot]
30eb822151 Version Packages 2021-11-11 10:11:42 +01:00
Thomas Allmer
15a82c0e4d fix: improve mdjs preview iframe security 2021-11-11 10:05:51 +01:00
github-actions[bot]
0197bee621 Version Packages 2021-10-15 19:25:11 +02:00
Thomas Allmer
5c6b9c91eb feat(mdjs-preview): Move platform and sizes settings above preview 2021-10-15 12:33:30 +02:00
Thomas Allmer
6221e5f9ea feat: mdjs support for story-code blocks 2021-10-15 12:33:30 +02:00
Jorge del Casar
06741ed729 chore: update playwright 2021-10-11 19:23:33 +02:00
Thomas Allmer
23c164c822 chore: reduce test output noise 2021-10-03 22:06:22 +02:00
github-actions[bot]
c2a76c3f53 Version Packages 2021-10-03 17:15:38 +02:00
Thomas Allmer
70bb7a128e feat: update all packages to use new plugins-manager api 2021-10-03 17:10:18 +02:00
Thomas Allmer
3c342473d7 feat(plugin-manager): new type safe API
Co-authored-by: Benny Powers <web@bennypowers.com>
2021-10-03 17:10:18 +02:00
Thomas Allmer
9e0579ab19 chore: version linting considering valid semver 2021-09-13 15:22:52 +02:00
Thomas Allmer
de202da0a5 chore: reenable all tests 2021-09-13 15:22:52 +02:00
github-actions[bot]
509a8d9115 Version Packages 2021-09-13 13:33:26 +02:00
Mathieu Puech
42418f2c00 fix: disable service worker for local development 2021-09-13 13:29:05 +02:00
Benny Powers
cadd8588b0 fix(blog): conditionally apply blog overview styles 2021-09-13 12:36:51 +02:00
Benny Powers
aabe011427 Update 30-articles.njk 2021-09-13 12:36:51 +02:00
qa46hx
e1089c5701 fix(blog): add title to blog page 2021-09-13 12:36:38 +02:00
Benny Powers
9f10386eb2 fix: hide 404 page from sitemap.xml 2021-08-10 23:57:52 +02:00
qa46hx
0987a41620 fix(mdjs-viewer): fix styling mdjs-viewer 2021-08-10 23:55:09 +02:00
Thomas Allmer
7301a0f354 feat(cli): enable conditional eleventy config 2021-08-01 16:49:20 +02:00
Thomas Allmer
5ac6aa6693 fix(cli): set the encoding of the simulator to utf8 2021-07-27 21:03:51 +02:00
github-actions[bot]
9f1633cccc Version Packages 2021-07-27 12:54:55 +02:00
Thijs Louisse
00f4a91550 fix(blog): alignment + spacings for article grids 2021-07-27 12:51:30 +02:00
Jorge del Casar
eb62dd9fd5 fix: use semver to lint versions 2021-07-21 20:42:22 +02:00
github-actions[bot]
bb07267289 Version Packages 2021-07-21 16:36:44 +02:00
Thomas Allmer
738941afdd feat(cli): add rollup config function to rocket config 2021-07-21 15:57:31 +02:00
github-actions[bot]
ef086c7aa3 Version Packages 2021-07-19 19:32:13 +02:00
Thijs Louisse
3d22fbb72e fix: make markdown css not conflict with lion components 2021-07-19 16:23:52 +02:00
Jorge del Casar
adf0f1d88f fix(cli): use openEnd to insert responsive image 2021-07-19 15:23:00 +02:00
Benny Powers
4145031162 docs: update code-tabs 2021-07-18 14:57:10 +03:00
Benny Powers
ac58953527 docs: nicer dark mode 2021-07-15 09:34:36 +02:00
Benny Powers
7dc3e0f9b0 docs: dark mode 2021-07-15 09:34:36 +02:00
Benny Powers
305a657ff5 docs: generated manifests 2021-07-15 09:34:36 +02:00
Thomas Allmer
8585e2ad66 chore: add open in vs code to readme 2021-07-15 08:56:18 +02:00
github-actions[bot]
4585675b00 Version Packages 2021-07-13 19:45:32 +02:00
Jorge del Casar
39f4fa7050 chore: update dependencies 2021-07-13 19:24:26 +02:00
github-actions[bot]
ccdd4d077e Version Packages 2021-07-11 17:02:49 +03:00
Benny Powers
a5661b85c2 chore: update dependencies 2021-07-11 17:01:27 +03:00
136 changed files with 3454 additions and 1362 deletions

View File

@@ -19,6 +19,11 @@
src="https://img.shields.io/badge/twitter-@modern_web_dev-1DA1F3?style=flat-square"
alt="Follow @modern_web_dev on Twitter"
/></a>
<a href="https://open.vscode.dev/modernweb-dev/rocket"
><img
src="https://open.vscode.dev/badges/open-in-vscode.svg"
alt="Open in VS Code"
/></a>
</p>
<p align="center">

1
docs/.eleventyignore Normal file
View File

@@ -0,0 +1 @@
*.docs.md

View File

@@ -1,5 +1,39 @@
:root {
--markdown-table-row-odd-background-color: #efefef;
:not(rocket-navigation):not(:defined) {
opacity: 0;
}
rocket-navigation,
header {
font-family: 'Montserrat', sans-serif;
}
code-tabs[collection="package-managers"] {
--code-tabs-icon-height: 18px;
}
.call-to-action {
background: var(--button-one) !important;
text-shadow: none !important;
border-radius: 5px !important;
padding-top: 15px !important;
padding-bottom: 15px !important;
border: none !important;
}
.call-to-action:hover,
.call-to-action:focus,
.call-to-action:active {
background: var(--button-one-hover) !important;
}
.call-to-action:nth-child(2) {
background: var(--button-two) !important;
}
.call-to-action:nth-child(2):hover,
.call-to-action:nth-child(2):focus,
.call-to-action:nth-child(2):active {
background: var(--button-two-hover) !important;
}
body[layout^='layout-home'] .markdown-body .call-to-action:nth-of-type(2) {
@@ -15,20 +49,3 @@ body[layout^='layout-home'] .markdown-body .call-to-action:nth-of-type(2) {
transform: rotate(45deg);
}
}
rocket-navigation {
font-family: 'Montserrat', sans-serif;
}
header {
font-family: 'Montserrat', sans-serif;
}
code-tabs[collection="package-managers"] {
--code-tabs-icon-height: 18px;
--code-tabs-justify-tabs: end;
}
:not(rocket-navigation):not(:defined) {
opacity: 0;
}

141
docs/_assets/theme.css Normal file
View File

@@ -0,0 +1,141 @@
html {
--button-one-hover: #436eff;
--button-one: #2758ff;
--button-two-hover: #444;
--button-two: black;
--contrast-color-dark: #1d3557;
--contrast-color-light: #fff;
--footer-background: rgba(0, 0, 0, 0.02);
--header-color: white;
--markdown-link-color: #2758ff;
--markdown-syntax-background-color: #f9f9f9;
--markdown-table-row-odd-background-color: #efefef;
--owc-active-color: #2758ff;
--owc-hover-color: #436eff;
--page-background: white;
--primary-color-accent: #cee5f6;
--primary-color-darker: #1a5285;
--primary-color-lighter: #449ad7;
--primary-color: rgb(44, 62, 80);
--primary-lines-color: #ccc;
--primary-text-color: #2c3e50;
--primary-text-inverse-color: #eee;
--switch-unselected-color: #808080;
--switch-selected-color: #42b983;
}
@media (prefers-color-scheme: dark) {
html {
--header-color: #2f3136;
--footer-background: rgba(255, 255, 255, 0.1);
--page-background: #36393e;
--text-color: #eee;
--primary-text-color: #eee;
--primary-color: white;
--primary-color-lighter: #449ad7;
--primary-color-darker: #1a5285;
--primary-color-accent: #cee5f6;
--contrast-color-light: #fff;
--contrast-color-dark: #1d3557;
--primary-lines-color: #333;
--owc-active-color: #41ffb0;
--owc-hover-color: #6dffc2;
--button-one: #9b03fe;
--button-one-hover: #a724ff;
--button-two: black;
--button-two-hover: rgb(36, 36, 36);
--rocket-search-background-color: #4a4d52;
--rocket-search-highlight-color: #41ffb0;
--rocket-search-hover-background-color: #6b717a;
--rocket-search-fill-color: #fff;
--primary-text-inverse-color: #2c3e50;
--switch-unselected-color: #808080;
--switch-selected-color: #42b983;
/* Markdown */
--markdown-octicon-link: var(--primary-text-color);
--markdown-link-color: #41ffb0;
--markdown-divider-color: #e1e4e8;
--markdown-blockquote-border-color: #dfe2e5;
--markdown-blockquote-color: #90aac7;
--markdown-kbd-background-color: #fafbfc;
--markdown-kbd-border-color: #c6cbd1;
--markdown-kbd-border-bottom-color: #959da5;
--markdown-kbd-color: #444d56;
--markdown-heading-color-6: #6a737d;
--markdown-table-background-color: var(--markdown-syntax-background-color);
--markdown-table-row-odd-background-color: var(--markdown-kbd-color);
--markdown-table-border-color: transparent;
--markdown-code-background-color: rgba(27, 31, 35, 0.05);
--markdown-pre-background-color: rgb(49, 49, 49);
/* syntax */
--markdown-syntax-color: #f8f8f2;
--markdown-syntax-background-color: #2e3440;
--markdown-syntax-atrule-color: #88c0d0;
--markdown-syntax-attr-name-color: #a3be8c;
--markdown-syntax-attr-value-color: #88c0d0;
--markdown-syntax-builtin-color: #a3be8c;
--markdown-syntax-boolean-color: #81a1c1;
--markdown-syntax-class-name-color: #88c0d0;
--markdown-syntax-constant-color: #81a1c1;
--markdown-syntax-char-color: #a3be8c;
--markdown-syntax-deleted-color: #81a1c1;
--markdown-syntax-entity-color: #81a1c1;
--markdown-syntax-function-color: #88c0d0;
--markdown-syntax-inserted-color: #a3be8c;
--markdown-syntax-keyword-color: #81a1c1;
--markdown-syntax-number-color: #b48ead;
--markdown-syntax-operator-color: #81a1c1;
--markdown-syntax-property-color: #81a1c1;
--markdown-syntax-punctuation-color: #81a1c1;
--markdown-syntax-regex-color: #81a1c1;
--markdown-syntax-important-color: #81a1c1;
--markdown-syntax-selector-color: #a3be8c;
--markdown-syntax-symbol-color: #81a1c1;
--markdown-syntax-string-color: #a3be8c;
--markdown-syntax-tag-color: #81a1c1;
--markdown-syntax-url-color: #81a1c1;
--markdown-syntax-variable-color: #81a1c1;
--markdown-syntax-hotkey-selector-color: #d73a49;
--markdown-syntax-keyword-color: #22863a;
--markdown-syntax-background-color: rgb(27, 29, 35);
--markdown-syntax-atrule-color: rgb(198, 120, 221);
--markdown-syntax-attr-name-color: rgb(198, 120, 221);
--markdown-syntax-boolean-color: rgb(209, 154, 102);
--markdown-syntax-class-name-color: rgb(97, 175, 239);
--markdown-syntax-constant-color: rgb(220, 220, 170);
--markdown-syntax-entity-color: rgb(220, 220, 170);
--markdown-syntax-function-color: rgb(97, 175, 239);
--markdown-syntax-inserted-color: rgb(220, 220, 170);
--markdown-syntax-keyword-color: rgb(198, 120, 221);
--markdown-syntax-number-color: rgb(220, 220, 170);
--markdown-syntax-operator-color: rgb(220, 220, 170);
--markdown-syntax-property-color: rgb(220, 220, 170);
--markdown-syntax-punctuation-color: white;
--markdown-syntax-regex-color: rgb(209, 154, 102);
--markdown-syntax-selector-color: rgb(86, 156, 214);
--markdown-syntax-symbol-color: rgb(220, 220, 170);
--markdown-syntax-tag-color: rgb(86, 156, 214);
--markdown-syntax-url-color: rgb(220, 220, 170);
--markdown-syntax-variable-color: rgb(220, 220, 170);
}
.string {
color: rgb(152, 195, 121);
}
.comment {
color: #7d7d7d;
}
.language-css {
--markdown-syntax-string-color: #81a1c1;
}
}
body[layout='home'] .markdown-body .call-to-action:nth-of-type(2) {
--primary-color: #222;
--primary-color-lighter: #333;
--primary-color-darker: #000;
}

View File

@@ -0,0 +1 @@
<link rel="stylesheet" href="{{ '/_assets/theme.css' | asset | url }}">

View File

@@ -88,8 +88,10 @@ The default preset for regular markdown content is available as `responsive`.
👉 `rocket.config.js`
<!-- prettier-ignore-start -->
```js
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
imagePresets: {
responsive: {
widths: [300, 820],
@@ -97,8 +99,9 @@ export default {
sizes: '(min-width: 1024px) 820px, calc(100vw - 20px)',
},
},
};
});
```
<!-- prettier-ignore-end -->
## Ignoring Images
@@ -148,8 +151,10 @@ For this example we want to also ignore `.jpeg` files.
👉 `rocket.config.js`
<!-- prettier-ignore-start -->
```js
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
imagePresets: {
responsive: {
// ...
@@ -157,8 +162,9 @@ export default {
src.endsWith('.jpeg') || src.endsWith('svg') || src.includes('rocket-unresponsive.'),
},
},
};
});
```
<!-- prettier-ignore-end -->
With that setting we get the following behavior
@@ -180,8 +186,10 @@ becomes
You can add your own image preset like so
<!-- prettier-ignore-start -->
```js
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
imagePresets: {
'my-image-preset': {
widths: [30, 60],
@@ -189,8 +197,9 @@ export default {
sizes: '(min-width: 1024px) 30px, 60px',
},
},
};
});
```
<!-- prettier-ignore-end -->
Once that `imagePreset` is defined you can use it by adding it to any `img` tag.
@@ -232,15 +241,18 @@ If you want to add `webp` (or replace `avif` with it) you can do so by setting t
👉 `rocket.config.js`
<!-- prettier-ignore-start -->
```js
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
imagePresets: {
responsive: {
formats: ['avif', 'webp', 'jpeg'],
},
},
};
});
```
<!-- prettier-ignore-end -->
## Default widths
@@ -262,16 +274,19 @@ If you want to add more widths you can add them to `widths`.
👉 `rocket.config.js`
<!-- prettier-ignore-start -->
```js
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
imagePresets: {
responsive: {
widths: [300, 600, 900, 1200, 1640],
sizes: '(min-width: 1024px) 820px, calc(100vw - 20px)',
},
},
};
});
```
<!-- prettier-ignore-end -->
<inline-notification type="tip">

View File

@@ -4,22 +4,27 @@ The configuration file is `rocket.config.js` or `rocket.config.mjs`.
The config files consist of the following parts:
<!-- prettier-ignore-start -->
```js
import { rocketLaunch } from '@rocket/launch';
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
presets: [rocketLaunch()],
emptyOutputDir: true,
pathPrefix: 'subfolder-only-for-build',
};
});
```
<!-- prettier-ignore-end -->
Rocket is primarily build around plugins for each of its systems.
New plugins can be added and all default plugins can be adjusted or even removed by using the following functions.
<!-- prettier-ignore-start -->
```js
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
// add remark/unified plugin to the Markdown processing (e.g. enable special code blocks)
setupUnifiedPlugins: [],
@@ -40,8 +45,9 @@ export default {
// add a plugin to the cli (e.g. a new command like "rocket my-command")
setupCliPlugins: [],
};
});
```
<!-- prettier-ignore-end -->
## Adding Rollup Plugins
@@ -55,19 +61,19 @@ You can accomplish this with Rollup and dev server plugins. Make sure to add bot
For these cases you can use `setupDevAndBuildPlugins`, which will automatically add the plugin for you to both Rollup and dev-server:
<!-- prettier-ignore-start -->
```js
import json from '@rollup/plugin-json';
import { addPlugin } from 'plugins-manager';
/** @type {import('@rocket/cli').RocketCliOptions} */
const config = {
export default ({
setupDevAndBuildPlugins: [
addPlugin({ name: 'json', plugin: json, location: 'top', options: { my: 'settings' } }),
],
};
export default config;
});
```
<!-- prettier-ignore-end -->
This will add the Rollup plugin `json` with the id `json` at the top of the plugin list of Rollup and the dev server. It needs to be at the top so further plugins down the line can work with JSON imports.
For the Dev Server the plugins are automatically wrapped by `@web/dev-server-rollup`. Note that [not all Rollup plugins](https://modern-web.dev/docs/dev-server/plugins/rollup/#compatibility-with-rollup-plugins) will work with the dev-server.
@@ -76,25 +82,85 @@ For the Dev Server the plugins are automatically wrapped by `@web/dev-server-rol
All plugins which are either default or are added via a preset can still be adjusted by using `adjustPluginOptions`.
<!-- prettier-ignore-start -->
```js
import { adjustPluginOptions } from 'plugins-manager';
/** @type {import('@rocket/cli').RocketCliOptions} */
const config = {
export default ({
setupDevAndBuildPlugins: [adjustPluginOptions('json', { my: 'overwrite settings' })],
};
export default config;
});
```
<!-- prettier-ignore-end -->
## Lifecycle
You can hook into the rocket lifecycle by specifying a function for `before11ty`. This function runs before 11ty calls it's write method. If it is an async function, Rocket will await it's promise.
<!-- prettier-ignore-start -->
```js
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
async before11ty() {
await copyDataFiles();
},
};
});
```
<!-- prettier-ignore-end -->
## Advanced
Sometimes you need even more control over specific settings.
### Rollup
For example if you wanna add an `acron` plugin to rollup
<!-- prettier-ignore-start -->
```js
import { importAssertions } from 'acorn-import-assertions';
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
rollup: config => ({
...config,
acornInjectPlugins: [importAssertions],
}),
});
```
<!-- prettier-ignore-end -->
### Eleventy
For example to add custom filter you can access the eleventy config directly
<!-- prettier-ignore-start -->
```js
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
eleventy: eleventyConfig => {
eleventyConfig.addFilter('value', value => `prefix${value}`);
},
});
```
<!-- prettier-ignore-end -->
You even have access to the full rocketConfig if you for example want to create filters that behave differently during start/build.
<!-- prettier-ignore-start -->
```js
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
eleventy: (config, rocketConfig) => {
config.addFilter('conditional-resolve', value => {
if (rocketConfig.command === 'build') {
return `build:${value}`;
}
if (rocketConfig.command === 'start') {
return `start:${value}`;
}
});
},
});
```
<!-- prettier-ignore-end -->

View File

@@ -12,11 +12,14 @@ Changing the service worker file name can be quite a hassle so you can adjust ge
👉 `rocket.config.js`
<!-- prettier-ignore-start -->
```js
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
serviceWorkerName: 'my-service-worker-name.js',
};
});
```
<!-- prettier-ignore-end -->
## Meet the Service Worker

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
### Storybook

View File

@@ -40,6 +40,68 @@ will result in
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
````md
@@ -72,15 +134,18 @@ excludeFromSearch: true
Once you have that you need to configure it for the story renderer by setting it in your `rocket.config.js`.
<!-- prettier-ignore-start -->
```js
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
setupUnifiedPlugins: [
adjustPluginOptions('mdjsSetupCode', {
simulationSettings: { simulatorUrl: '/simulator/' },
}),
],
};
});
```
<!-- prettier-ignore-end -->
<inline-notification type="tip">

View File

@@ -4,7 +4,7 @@ Enable writing blog posts within your Rocket site.
## Installation
<code-tabs collection="package-managers" default-tab="npm">
<code-tabs collection="package-managers" default-tab="npm" align="end">
```bash tab npm
npm i @rocket/blog
@@ -24,10 +24,13 @@ pnpm add @rocket/blog
👉 `rocket.config.js`
<!-- prettier-ignore-start -->
```js
import { rocketBlog } from '@rocket/blog';
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
presets: [rocketBlog()],
};
});
```
<!-- prettier-ignore-end -->

View File

@@ -0,0 +1,7 @@
---
layout: layout-api
package: '@rocket/launch'
module: inline-notification/index.js
---
# Presets >> Launch >> Custom Elements || 20

View File

@@ -0,0 +1,3 @@
# Presets >> Launch || 20
- [Preset](./preset/)

View File

@@ -8,7 +8,7 @@ alerts:
content: You **really** shouldn't!
---
# Presets >> Launch || 20
# Presets >> Launch >> Preset || 10
Rocket comes with a preset you will love. Simple, responsive and behaving like native, it sure is going to be a hit among your users.
@@ -16,7 +16,7 @@ Rocket comes with a preset you will love. Simple, responsive and behaving like n
Install `@rocket/launch` from the NPM repository using your favourite package manager.
<code-tabs collection="package-managers" default-tab="npm">
<code-tabs collection="package-managers" default-tab="npm" align="end">
```bash tab npm
npm i @rocket/launch
@@ -36,13 +36,16 @@ pnpm add @rocket/launch
👉 `rocket.config.js`
<!-- prettier-ignore-start -->
```js
import { rocketLaunch } from '@rocket/launch';
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
presets: [rocketLaunch()],
};
});
```
<!-- prettier-ignore-end -->
## Data

View File

@@ -1,43 +0,0 @@
# Presets >> Search || 30
Add a search for all your static content.
## Installation
<code-tabs collection="package-managers" default-tab="npm">
```bash tab npm
npm i @rocket/search
```
```bash tab yarn
yarn add @rocket/search
```
```bash tab pnpm
pnpm add @rocket/search
```
</code-tabs>
## Usage
👉 `rocket.config.js`
```js
import { rocketSearch } from '@rocket/search';
export default {
presets: [rocketSearch()],
};
```
## Styling
| Property | Default | Description |
| ------------------------------------- | --------- | ------------------------------------ |
| `--rocket-search-background-color` | `#fff` | Search results background color |
| `--rocket-search-input-border-color` | `#dfe1e5` | |
| `--rocket-search-input-border-radius` | `24px` | |
| `--rocket-search-fill-color` | `#000` | Search Icon Color |
| `--rocket-search-highlight-color` | `#6c63ff` | Highlighted search result text color |

View File

@@ -0,0 +1,9 @@
---
layout: layout-api
package: '@rocket/search'
modules:
- src/RocketSearch.js
- src/RocketSearchCombobox.js
---
# Presets >> Search >> Custom Elements || 20

View File

@@ -0,0 +1,3 @@
# Presets >> Search || 10
- [Preset](./preset/)

View File

@@ -0,0 +1,36 @@
# Presets >> Search >> Preset || 10
Add a search for all your static content.
## Installation
<code-tabs collection="package-managers" default-tab="npm" align="end">
```bash tab npm
npm i @rocket/search
```
```bash tab yarn
yarn add @rocket/search
```
```bash tab pnpm
pnpm add @rocket/search
```
</code-tabs>
## Usage
👉 `rocket.config.js`
<!-- prettier-ignore-start -->
```js
import { rocketSearch } from '@rocket/search';
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
presets: [rocketSearch()],
});
```
<!-- prettier-ignore-end -->

View File

@@ -3,16 +3,125 @@
The Plugins Manager replaces the specific registration/execution (with options) in a given plugin system by an intend to use a plugin (with these options).
This allows your users to adjust the options before actually applying the plugins.
## Setup
1. Install npm package
```bash
npm i plugins-manager
```
2. Change your public API from an array of plugin "instances" to an array of setup functions
```diff
import myPlugin from 'my-plugin';
+ import { addPlugin } from 'plugins-manager';
export default {
- plugins: [myPlugin],
+ setupPlugins: [addPlugin(myPlugin)]
}
```
3. Convert setup function to plugins
```js
import { applyPlugins } from 'plugins-manager';
const finalConfig = applyPlugins(config); // "converts" setupPlugins to plugins
// work with plugins or pass it on to another tool
const bundle = await rollup(finalConfig);
```
## Usage
As you users in most cases you will need to either add or adjust a given plugin in a config file.
👉 `my-tool.config.js`
```js
import { addPlugin, adjustPluginOptions } from 'plugins-manager';
import json from '@rollup/plugin-json';
import { nodeResolve } from '@rollup/plugin-node-resolve';
export default {
setupPlugins: [
// add a new plugin with optional plugin options
addPlugin(json, {
/* ... */
}),
// adjust the options of a plugin that is already registered
adjustPluginOptions(nodeResolve, {
/* ... */
}),
],
};
```
## Plugins can be functions or classes
### Function Plugins
```js
function myPlugin({ lastName: 'initial-second' }) {
// ...
}
export default {
setupPlugins: [addPlugin(myPlugin)],
};
// function parameters are type safe
addPlugin(myPlugin, { lastName: 'new name' }); // ts ok
addPlugin(myPlugin, { otherProp: 'new name' }); // ts error
```
### Class Plugins
The options are passed to the constructor.
```js
/**
* @typedef {object} MyClassOptions
* @property {string} lastName
*/
class MyClass {
/** @type {MyClassOptions} */
options = {
lastName: 'initial-second',
};
/**
* @param {Partial<MyClassOptions>} options
*/
constructor(options = {}) {
this.options = { ...this.options, ...options };
}
// ...
}
export default {
setupPlugins: [addPlugin(MyClass)],
};
// constructor parameters are type safe
addPlugin(MyClass, { lastName: 'new name' }); // ts ok
addPlugin(MyClass, { otherProp: 'new name' }); // ts error
```
## Problem
Many plugin systems require you to either execute a plugin function like in `rollup`.
<!-- prettier-ignore-start -->
```js
import json from '@rollup/plugin-json';
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
plugins: [json({ preferConst: true })],
};
});
```
<!-- prettier-ignore-end -->
or add it in a special way like in `eleventy`
@@ -44,18 +153,14 @@ This means if you wish to define default plugins and allow your user to override
The plugins manager lets you orchestrate a set of "meta plugins" which are defined by
- name
- plugin
- options
- plugin (class or function)
- it's options
```js
import beep from '@rollup/plugin-beep';
import url from '@rollup/plugin-url';
let metaPlugins = [
{ name: 'beep', plugin: beep },
{ name: 'url', plugin: url, options: { limit: 10000 } },
];
let metaPlugins = [{ plugin: beep }, { plugin: url, options: { limit: 10000 } }];
```
This array can be modified by adding/removing or adjusting options.
@@ -90,16 +195,13 @@ export default {
### Adding Helpers
Doing array manipulations is kinda error-prone so we offer encourage to use an array of setup function. Where as each setup function can either add a new plugin (with a unique name) or adjust an already existing plugin.
Doing array manipulations is kinda error-prone so we encourage to use an array of setup function. Where as each setup function can either add a new plugin (with a unique name) or adjust an already existing plugin.
```js
import { addPlugin, adjustPluginOptions } from 'plugins-manager';
const systemSetupFunctions = [
addPlugin({ name: 'first', plugin: first }),
addPlugin({ name: 'second', plugin: second }),
];
const userSetupFunctions = [adjustPluginOptions('first', { my: 'options' })];
const systemSetupFunctions = [addPlugin(first), addPlugin(second)];
const userSetupFunctions = [adjustPluginOptions(first, { my: 'options' })];
```
Arrays of functions can by merged like so
@@ -111,9 +213,9 @@ const finalSetupFunctions = [...systemSetupFunctions, ...userSetupFunctions];
and then converted to the final output.
```js
import { metaPluginsToRollupPlugins } from 'plugins-manager';
import { applyPlugins } from 'plugins-manager';
const plugins = metaPluginsToRollupPlugins(finalSetupFunctions, metaPlugins);
const plugins = applyPlugins(finalSetupFunctions, metaPlugins);
```
## Adding a Plugin
@@ -129,18 +231,27 @@ By default it adds at the bottom.
import json from '@rollup/plugin-json';
import { addPlugin } from 'plugins-manager';
const userSetupFunctions = [
addPlugin({ name: 'json', plugin: json, options: { preferConst: true } }),
];
const userSetupFunctions = [addPlugin(json, { preferConst: true })];
```
Example usage:
```js
addPlugin({ name: 'json', plugin: json }); // Add at the bottom (default)
addPlugin({ name: 'json', plugin: json, location: 'top' }); // Add at the top/beginning of the array
addPlugin({ name: 'json', plugin: json, location: 'beep' }); // Add after (default) plugin 'beep'
addPlugin({ name: 'json', plugin: json, location: 'beep', how: 'before' }); // Add before plugin 'beep'
addPlugin(json); // Add at the bottom (default)
addPlugin(json, {}, { location: 'top' }); // Add at the top/beginning of the array
addPlugin(json, {}, { location: beep }); // Add after (default) plugin 'beep'
addPlugin(json, {}, { location: beep, how: 'before' }); // Add before plugin 'beep'
```
This is type safe and typescript will throw an error if you pass the wrong type.
```js
function myPlugin({ myFlag = false } = {}) {
// ...
}
addPlugin(myPlugin, { myFlag: true }); // ts ok
addPlugin(myPlugin, { notExisting: true }); // ts error
```
## Adjusting Plugin Options
@@ -150,12 +261,14 @@ Adjusting options means to either
- flatly merge objects (e.g. only the first level will be preserved)
- calling a function to do the merge yourself
- setting the raw value (if not an object or function)
- you need to have a reference to the plugin (which is used to auto complete the available options via typescript)
```js
import json from '@rollup/plugin-json';
import { adjustPluginOptions } from 'plugins-manager';
const userSetupFunctions = [
adjustPluginOptions('json', { preferConst: false, anotherOption: 'format' }),
adjustPluginOptions(json, { preferConst: false, anotherOption: 'format' }),
];
```
@@ -163,36 +276,53 @@ Example usage:
```js
// given
addPlugin({
name: 'json',
plugin: json,
options: {
other: {
nested: 'other.nested',
nested2: 'other.nested2',
},
main: true,
addPlugin(json, {
other: {
nested: 'other.nested',
nested2: 'other.nested2',
},
main: true,
});
// merge objects flately
adjustPluginOptions('json', { other: { nested: '--overwritten--' } });
adjustPluginOptions(json, { other: { nested: '--overwritten--' } });
// resulting options = { other: { nested: '--overwritten--' }, main: true }
// NOTE: nested2 is removed
// merge via function
adjustPluginOptions('json', config => ({ other: { ...config.other, nested: '--overwritten--' } }));
adjustPluginOptions(json, config => ({ other: { ...config.other, nested: '--overwritten--' } }));
// resulting options = { other: { nested: '--overwritten--', nested2: 'other.nested2' }, main: true }
// merge via function to override full options
adjustPluginOptions('json', config => ({ only: 'this' }));
adjustPluginOptions(json, config => ({ only: 'this' }));
// resulting options = { only: 'this' }
// setting a raw value
adjustPluginOptions('json', false);
adjustPluginOptions(json, false);
// resulting options = false
```
This is type safe and typescript will throw an error if you pass the wrong type.
```js
function myPlugin({ myFlag = false } = {}) {
// ...
}
adjustPluginOptions(myPlugin, { myFlag: true }); // ts ok
adjustPluginOptions(myPlugin, { notExisting: true }); // ts error
```
## Remove Plugin
Sometimes you would like to remove a default plugin from the config.
```js
export default {
setupPlugins: [removePlugin(json)],
};
```
## Converting metaPlugins to an Actual Plugin
To execute all setup function you can use this little helper
@@ -223,25 +353,9 @@ Rollup has a more specific helper that handles
Note: if you provide `config.plugins` then it will return that directly ignoring `setupPlugins`
```js
import { metaConfigToRollupConfig } from 'plugins-manager';
import { applyPlugins } from 'plugins-manager';
const finalConfig = metaConfigToRollupConfig(currentConfig, defaultMetaPlugins);
```
Web Dev Server has a more specific helper that handles
- `config.setupPlugins`
- `config.setupRollupPlugins`
Note: if you provide `config.plugins` then it will return that directly ignoring `setupPlugins` and `setupRollupPlugins`
```js
import { metaConfigToWebDevServerConfig } from 'plugins-manager';
import { fromRollup } from '@web/dev-server-rollup';
const finalConfig = metaConfigToWebDevServerConfig(currentConfig, defaultMetaPlugins, {
rollupWrapperFunction: fromRollup,
});
const finalConfig = applyPlugins(currentConfig, defaultMetaPlugins);
```
Eleventy

View File

@@ -22,17 +22,17 @@ The Plugins Manager helps you register and execute your plugins across the vario
If you want to add a plugin to the Markdown processing you can use `setupUnifiedPlugins`.
<!-- prettier-ignore-start -->
```js
import emoji from 'remark-emoji';
import { addPlugin } from 'plugins-manager';
/** @type {Partial<import('@rocket/cli').RocketCliOptions>} */
const config = {
export default ({
setupUnifiedPlugins: [addPlugin({ location: 'markdown', name: 'emoji', plugin: emoji })],
};
export default config;
});
```
<!-- prettier-ignore-end -->
For plugins that should handle the Markdown <abbr title="Abstract Syntax Tree">AST</abbr> you should use `addPlugin({ location: 'markdown', name: 'my-plugin', plugin: MyPlugin})`. <br>
While for the rehype AST you should use `addPlugin({ location: 'remark2rehype', name: 'my-plugin', plugin: MyPlugin})`.

View File

@@ -21,7 +21,7 @@ cd my-project
Then initialize a package.json file
<code-tabs collection="package-managers" default-tab="npm">
<code-tabs collection="package-managers" default-tab="npm" align="end">
```bash tab npm
npm init -y
@@ -39,7 +39,7 @@ pnpm init -y
### Step 2. Install dependencies
<code-tabs collection="package-managers" default-tab="npm">
<code-tabs collection="package-managers" default-tab="npm" align="end">
```bash tab npm
npm install --save-dev @rocket/cli @rocket/launch
@@ -57,7 +57,7 @@ pnpm add -D @rocket/cli @rocket/launch
### Step 3. Bootstrap the project
<code-tabs collection="package-managers" default-tab="npm">
<code-tabs collection="package-managers" default-tab="npm" align="end">
```bash tab npm
npx rocket bootstrap
@@ -92,13 +92,16 @@ If you don't want to use the `module` package type, make sure to rename the gene
<code-tabs default-tab="rocket.config.js">
<!-- prettier-ignore-start -->
```js tab rocket.config.js
import { rocketLaunch } from '@rocket/launch';
export default {
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
presets: [rocketLaunch()],
};
});
```
<!-- prettier-ignore-end -->
```md tab docs/index.md
# Welcome to Your Rocket Site
@@ -145,7 +148,7 @@ Please note that the heading - text prefixed with `#` or `##` - is not optional
Now you can launch your site locally with
<code-tabs collection="package-managers" default-tab="npm">
<code-tabs collection="package-managers" default-tab="npm" align="end">
```bash tab npm
npm start

View File

@@ -42,11 +42,13 @@ eleventyExcludeFromCollections: true
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% raw %}{% for page in collections.all %}
{%- if page.url !== '/404.html' -%}
<url>
<loc>{{ rocketConfig.absoluteBaseUrl }}{{ page.url | url }}</loc>
<lastmod>{{ page.date.toISOString() }}</lastmod>
<changefreq>{{ page.data.changeFreq if page.data.changeFreq else "monthly" }}</changefreq>
</url>
{%- endif -%}
{% endfor %}{% endraw %}
</urlset>
```

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

@@ -8,15 +8,16 @@
},
"type": "module",
"scripts": {
"analyze": "node scripts/workspaces-scripts-bin.mjs analyze",
"analyze": "run-s analyze:* format:*",
"analyze:analyze": "node scripts/workspaces-scripts-bin.mjs analyze",
"build": "npm run build:packages && npm run build:site",
"build:packages": "node scripts/workspaces-scripts-bin.mjs build:package",
"build:site": "npm run rocket:build",
"build:site": "run-s analyze:* rocket:build",
"changeset": "changeset",
"debug": "web-test-runner --watch --config web-test-runner-chrome.config.mjs",
"debug:firefox": "web-test-runner --watch --config web-test-runner-firefox.config.mjs",
"debug:webkit": "web-test-runner --watch --config web-test-runner-webkit.config.mjs",
"format": "npm run format:eslint && npm run format:prettier",
"format": "run-s format:*",
"format:eslint": "eslint --ext .ts,.js,.mjs,.cjs . --fix",
"format:prettier": "node node_modules/prettier/bin-prettier.js \"**/*.{ts,js,mjs,cjs,md}\" \"**/!(expected)/package.json\" --write --ignore-path .eslintignore",
"lint": "run-p lint:*",
@@ -32,7 +33,8 @@
"setup": "npm run setup:ts-configs && npm run build:packages",
"setup:patches": "npx patch-package",
"setup:ts-configs": "node scripts/generate-ts-configs.mjs",
"start": "node packages/cli/src/cli.js start",
"xprestart": "yarn analyze",
"start": "node --trace-warnings packages/cli/src/cli.js start",
"test": "yarn test:node && yarn test:web",
"test:node": "mocha \"packages/*/test-node/**/*.test.{ts,js,mjs,cjs}\" --timeout 5000 --reporter dot --exit",
"test:web": "web-test-runner",
@@ -60,13 +62,13 @@
"@typescript-eslint/parser": "^4.13.0",
"@web/test-runner": "^0.12.2",
"@web/test-runner-commands": "^0.4.0",
"@web/test-runner-playwright": "^0.8.0",
"cem-plugin-readme": "^0.1.2",
"@web/test-runner-playwright": "^0.8.8",
"cem-plugin-readme": "^0.1.3",
"chai": "^4.2.0",
"concurrently": "^5.3.0",
"copyfiles": "^2.4.1",
"deepmerge": "^4.2.2",
"esbuild": "^0.8.31",
"esbuild": "^0.12.15",
"eslint": "^7.17.0",
"eslint-config-prettier": "^7.1.0",
"hanbi": "^0.4.1",
@@ -78,10 +80,12 @@
"onchange": "^7.1.0",
"prettier": "^2.2.1",
"prettier-plugin-package": "^1.3.0",
"publish-docs": "^0.1.2",
"puppeteer": "^9.0.0",
"remark-emoji": "^2.1.0",
"rimraf": "^3.0.2",
"rocket-preset-code-tabs": "^0.2.1",
"rocket-preset-code-tabs": "^0.2.6",
"rocket-preset-custom-elements-manifest": "^0.1.7",
"rollup": "^2.36.1",
"rollup-plugin-terser": "^7.0.2",
"sinon": "^9.2.3",

View File

@@ -1,5 +1,50 @@
# @rocket/blog
## 0.4.0
### Minor Changes
- 70bb7a1: BREAKING CHANGE: Update to latest plugins manager to get type safe options
There is no longer a name string as a key for a plugin. It is identified by it's function/class. You will need to adjust your code if you are adding or adjusting plugins.
```diff
- addPlugin({ name: 'my-plugin', plugin: myPlugin, options: { myFlag: true }, location: 'top' });
+ addPlugin(myPlugin, { myFlag: true }, { location: 'top' });
- adjustPluginOptions('my-plugin', { myFlag: true });
+ adjustPluginOptions(myPlugin, { myFlag: true });
```
For more details please see the [Changelog](https://github.com/modernweb-dev/rocket/blob/main/packages/plugins-manager/CHANGELOG.md#030) of the plugins-manager package.
### Patch Changes
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- plugins-manager@0.3.0
## 0.3.3
### Patch Changes
- e1089c5: add title to blog page
## 0.3.2
### Patch Changes
- 00f4a91: alignment + spacings for article grids
## 0.3.1
### Patch Changes
- a5661b8: Updates dependencies
## 0.3.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/blog",
"version": "0.3.0",
"version": "0.4.0",
"publishConfig": {
"access": "public"
},
@@ -38,6 +38,6 @@
"testing"
],
"dependencies": {
"plugins-manager": "^0.2.3"
"plugins-manager": "^0.3.0"
}
}

View File

@@ -20,6 +20,8 @@ body[layout='layout-blog-details'] #sidebar-nav li.anchor a:hover::before {
flex-wrap: wrap;
margin: calc(-1 * var(--gap)) 0 0 calc(-1 * var(--gap));
width: calc(100% + var(--gap));
align-items: flex-start;
}
.articles article {
@@ -32,6 +34,12 @@ body[layout='layout-blog-details'] #sidebar-nav li.anchor a:hover::before {
.articles article h2 {
margin: 0;
border: none;
padding-top: 1rem;
}
.articles article .thumbnail {
display: block;
height: 200px;
}
.articles article .read {
@@ -48,7 +56,7 @@ body[layout='layout-blog-details'] #sidebar-nav li.anchor a:hover::before {
}
@media screen and (min-width: 1024px) {
body[layout='layout-blog-details'] #sidebar {
body[layout='layout-blog-details'] #sidebar {
display: block;
}
}
}

View File

@@ -1,3 +1,6 @@
{% if title %}
<h1>{{title}}</h1>
{% endif %}
{% if cover_image %}
<img src="{{ cover_image | url }}" alt="">
{% endif %}

View File

@@ -3,8 +3,7 @@
{% if post.data.published %}
<article>
{% if post.data.cover_image %}
<a href="{{ post.url | url }}">
<img src="{{ post.data.cover_image | url }}" alt="">
<a href="{{ post.url | url }}" class="thumbnail" style="background-image: url({{ post.data.cover_image | url }});">
</a>
{% endif %}
<div class="content">

View File

@@ -1 +1,9 @@
<link rel="stylesheet" href="{{ '/_assets/rocket-blog.css' | asset | url }}">
{%- if layout == 'layout-blog-overview' -%}
<style>
.articles article .thumbnail {
background-size: cover;
background-position: center;
}
</style>
{%- endif -%}

View File

@@ -47,6 +47,6 @@ export function rocketBlog({ section = SECTION, postCollection = POST_COLLECTION
return {
path: path.resolve(__dirname),
setupEleventyPlugins: [addPlugin({ name: 'rocket-blog', plugin: eleventyPluginRocketBlog })],
setupEleventyPlugins: [addPlugin(eleventyPluginRocketBlog)],
};
}

View File

@@ -1,5 +1,22 @@
# @rocket/building-rollup
## 0.4.0
### Minor Changes
- 70bb7a1: BREAKING CHANGE: Update to latest plugins manager to get type safe options
There is no longer a name string as a key for a plugin. It is identified by it's function/class. You will need to adjust your code if you are adding or adjusting plugins.
```diff
- addPlugin({ name: 'my-plugin', plugin: myPlugin, options: { myFlag: true }, location: 'top' });
+ addPlugin(myPlugin, { myFlag: true }, { location: 'top' });
- adjustPluginOptions('my-plugin', { myFlag: true });
+ adjustPluginOptions(myPlugin, { myFlag: true });
```
For more details please see the [Changelog](https://github.com/modernweb-dev/rocket/blob/main/packages/plugins-manager/CHANGELOG.md#030) of the plugins-manager package.
## 0.3.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/building-rollup",
"version": "0.3.1",
"version": "0.4.0",
"publishConfig": {
"access": "public"
},

View File

@@ -2,13 +2,13 @@ import resolve from '@rollup/plugin-node-resolve';
import { terser } from 'rollup-plugin-terser';
import babelPkg from '@rollup/plugin-babel';
import { metaConfigToRollupConfig } from 'plugins-manager';
import { applyPlugins } from 'plugins-manager';
const { babel } = babelPkg;
export function createBasicConfig(userConfig) {
const { config, metaPlugins } = createBasicMetaConfig(userConfig);
return metaConfigToRollupConfig(config, metaPlugins);
return applyPlugins(config, metaPlugins);
}
export function createBasicMetaConfig(userConfig = { output: {} }) {
@@ -39,14 +39,12 @@ export function createBasicMetaConfig(userConfig = { output: {} }) {
let metaPlugins = [
{
name: 'node-resolve',
plugin: resolve,
options: {
moduleDirectories: ['node_modules', 'web_modules'],
},
},
{
name: 'babel',
plugin: babel,
options: {
babelHelpers: 'bundled',
@@ -73,7 +71,6 @@ export function createBasicMetaConfig(userConfig = { output: {} }) {
},
},
{
name: 'terser',
plugin: terser,
},
];

View File

@@ -1,10 +1,11 @@
import { createSpaMetaConfig } from './createSpaConfig.js';
import { adjustPluginOptions, metaConfigToRollupConfig } from 'plugins-manager';
import { adjustPluginOptions, applyPlugins } from 'plugins-manager';
import { rollupPluginHTML } from '@web/rollup-plugin-html';
export function createMpaConfig(userConfig) {
const { config, metaPlugins } = createMpaMetaConfig(userConfig);
const final = metaConfigToRollupConfig(config, metaPlugins);
const final = applyPlugins(config, metaPlugins);
return final;
}
@@ -12,7 +13,7 @@ export function createMpaMetaConfig(userConfig = { output: {}, setupPlugins: []
const { config, metaPlugins } = createSpaMetaConfig(userConfig);
config.setupPlugins = [
adjustPluginOptions('html', {
adjustPluginOptions(rollupPluginHTML, {
flattenOutput: false,
}),
...config.setupPlugins,

View File

@@ -3,13 +3,13 @@ import { terser } from 'rollup-plugin-terser';
import babelPkg from '@rollup/plugin-babel';
import replace from '@rollup/plugin-replace';
import { metaConfigToRollupConfig } from 'plugins-manager';
import { applyPlugins } from 'plugins-manager';
const { babel } = babelPkg;
export function createServiceWorkerConfig(userConfig) {
const { config, metaPlugins } = createServiceWorkerMetaConfig(userConfig);
return metaConfigToRollupConfig(config, metaPlugins);
return applyPlugins(config, metaPlugins);
}
export function createServiceWorkerMetaConfig(userConfig = { output: {} }) {
@@ -33,21 +33,19 @@ export function createServiceWorkerMetaConfig(userConfig = { output: {} }) {
let metaPlugins = [
{
name: 'node-resolve',
plugin: resolve,
options: {
moduleDirectories: ['node_modules', 'web_modules'],
},
},
{
name: 'replace',
plugin: replace,
options: {
'process.env.NODE_ENV': JSON.stringify(developmentMode ? 'development' : 'production'),
preventAssignment: true,
},
},
{
name: 'babel',
plugin: babel,
options: {
babelHelpers: 'bundled',
@@ -74,7 +72,6 @@ export function createServiceWorkerMetaConfig(userConfig = { output: {} }) {
},
},
{
name: 'terser',
plugin: terser,
options: {
mangle: {

View File

@@ -1,13 +1,13 @@
import { rollupPluginHTML } from '@web/rollup-plugin-html';
import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets';
import { polyfillsLoader } from '@web/rollup-plugin-polyfills-loader';
import { metaConfigToRollupConfig } from 'plugins-manager';
import { applyPlugins } from 'plugins-manager';
import { createBasicMetaConfig } from './createBasicConfig.js';
export function createSpaConfig(userConfig) {
const { config, metaPlugins } = createSpaMetaConfig(userConfig);
return metaConfigToRollupConfig(config, metaPlugins);
return applyPlugins(config, metaPlugins);
}
export function createSpaMetaConfig(userConfig = { output: {} }) {
@@ -30,7 +30,6 @@ export function createSpaMetaConfig(userConfig = { output: {} }) {
const spaMetaPlugins = [
...metaPlugins,
{
name: 'html',
plugin: rollupPluginHTML,
options: {
rootDir,
@@ -38,11 +37,9 @@ export function createSpaMetaConfig(userConfig = { output: {} }) {
},
},
{
name: 'import-meta-assets',
plugin: importMetaAssets,
},
{
name: 'polyfills-loader',
plugin: polyfillsLoader,
options: {
polyfills: {},

View File

@@ -1,5 +1,85 @@
# @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
### Minor Changes
- 70bb7a1: BREAKING CHANGE: Update to latest plugins manager to get type safe options
There is no longer a name string as a key for a plugin. It is identified by it's function/class. You will need to adjust your code if you are adding or adjusting plugins.
```diff
- addPlugin({ name: 'my-plugin', plugin: myPlugin, options: { myFlag: true }, location: 'top' });
+ addPlugin(myPlugin, { myFlag: true }, { location: 'top' });
- adjustPluginOptions('my-plugin', { myFlag: true });
+ adjustPluginOptions(myPlugin, { myFlag: true });
```
For more details please see the [Changelog](https://github.com/modernweb-dev/rocket/blob/main/packages/plugins-manager/CHANGELOG.md#030) of the plugins-manager package.
### Patch Changes
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- plugins-manager@0.3.0
- @rocket/eleventy-plugin-mdjs-unified@0.6.0
- @rocket/building-rollup@0.4.0
## 0.9.11
### Patch Changes
- 7301a0f: Pass on rocketConfig to the eleventy function to enable conditional configurations/filters
- 42418f2: Disable the service worker for local development
- 5ac6aa6: Set the encoding of the simulator to utf8 via a html meta tag
## 0.9.10
### Patch Changes
- 738941a: In `rocket.config.js` you can now supply a rollup config function.
```js
export default {
rollup: config => {
// config will be the fully generated config object after all presets have been applied
if (config.plugins.includes('...')) {
// change some config options
}
return config;
},
};
```
## 0.9.9
### Patch Changes
- adf0f1d: use img openEnd to insert responsive image
## 0.9.8
### Patch Changes
- a5661b8: Updates dependencies
## 0.9.7
### Patch Changes

View File

@@ -1,10 +1,26 @@
const { setComputedConfig, getComputedConfig } = require('./src/public/computedConfig.cjs');
const { generateEleventyComputed } = require('./src/public/generateEleventyComputed.cjs');
const {
generateEleventyComputed,
LayoutPlugin,
TitleMetaPlugin,
TitlePlugin,
EleventyNavigationPlugin,
SectionPlugin,
SocialMediaImagePlugin,
JoiningBlocksPlugin,
} = require('./src/public/generateEleventyComputed.cjs');
const { createSocialImage } = require('./src/public/createSocialImage.cjs');
module.exports = {
setComputedConfig,
getComputedConfig,
generateEleventyComputed,
LayoutPlugin,
TitleMetaPlugin,
TitlePlugin,
EleventyNavigationPlugin,
SectionPlugin,
SocialMediaImagePlugin,
JoiningBlocksPlugin,
createSocialImage,
};

View File

@@ -1,3 +1,16 @@
/** @typedef {import('@rocket/cli/types/main').RocketCliOptions} RocketCliOptions */
export { setComputedConfig, getComputedConfig } from './src/public/computedConfig.cjs';
export {
generateEleventyComputed,
LayoutPlugin,
TitleMetaPlugin,
TitlePlugin,
EleventyNavigationPlugin,
SectionPlugin,
SocialMediaImagePlugin,
JoiningBlocksPlugin,
} from './src/public/generateEleventyComputed.cjs';
export { createSocialImage } from './src/public/createSocialImage.cjs';
export { RocketCli } from './src/RocketCli.js';

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/cli",
"version": "0.9.7",
"version": "0.10.1",
"publishConfig": {
"access": "public"
},
@@ -57,9 +57,9 @@
"dependencies": {
"@11ty/eleventy": "^0.11.1",
"@11ty/eleventy-img": "^0.9.0",
"@rocket/building-rollup": "^0.3.1",
"@rocket/building-rollup": "^0.4.0",
"@rocket/core": "^0.1.2",
"@rocket/eleventy-plugin-mdjs-unified": "^0.5.1",
"@rocket/eleventy-plugin-mdjs-unified": "^0.6.0",
"@rocket/eleventy-rocket-nav": "^0.3.0",
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-node-resolve": "^11.0.1",
@@ -72,7 +72,7 @@
"command-line-usage": "^6.1.1",
"fs-extra": "^9.0.1",
"micromatch": "^4.0.2",
"plugins-manager": "^0.2.3",
"plugins-manager": "^0.3.0",
"slash": "^3.0.0",
"utf8": "^3.0.0",
"workbox-window": "^6.1.5"

View File

@@ -4,4 +4,6 @@
window.__rocketServiceWorkerUrl = '{{ rocketServiceWorkerUrl | url }}';
</script>
{% if rocketConfig.command == 'build' %}
<script type="module" inject-service-worker="" src="{{ '/_assets/scripts/registerServiceWorker.js' | asset | url }}"></script>
{% endif %}

View File

@@ -1,6 +1,7 @@
<html theme="light" platform="web" lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<style type="text/css">
body {
margin: 0;
@@ -13,19 +14,37 @@
<script type="module">
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() {
const urlParts = new URLSearchParams(document.location.hash.substr(1));
if (urlParts.get('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');
link.rel = 'stylesheet';
link.href = stylesheet;
link.href = safeStylesheetUrl;
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')) {
document.documentElement.setAttribute('theme', urlParts.get('theme'));
}
@@ -45,7 +64,8 @@
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);
}

View File

@@ -5,6 +5,7 @@ import { rollup } from 'rollup';
import fs from 'fs-extra';
import path from 'path';
import { copy } from '@web/rollup-plugin-copy';
import { rollupPluginHTML } from '@web/rollup-plugin-html';
import { createMpaConfig, createServiceWorkerConfig } from '@rocket/building-rollup';
import { addPlugin, adjustPluginOptions } from 'plugins-manager';
@@ -25,18 +26,14 @@ async function buildAndWrite(config) {
async function productionBuild(config) {
const defaultSetupPlugins = [
addPlugin({
name: 'copy',
plugin: copy,
options: {
patterns: ['!(*.md|*.html)*', '_merged_assets/_static/**/*'],
rootDir: config.outputDevDir,
},
addPlugin(copy, {
patterns: ['!(*.md|*.html)*', '_merged_assets/_static/**/*'],
rootDir: config.outputDevDir,
}),
];
if (config.pathPrefix) {
defaultSetupPlugins.push(
adjustPluginOptions('html', { absolutePathPrefix: config.pathPrefix }),
adjustPluginOptions(rollupPluginHTML, { absolutePathPrefix: config.pathPrefix }),
);
}
@@ -54,8 +51,8 @@ async function productionBuild(config) {
...config.setupBuildPlugins,
],
});
await buildAndWrite(mpaConfig);
const finalConfig = typeof config.rollup === 'function' ? config.rollup(mpaConfig) : mpaConfig;
await buildAndWrite(finalConfig);
const serviceWorkerSourcePath = path.resolve('docs/_merged_assets/service-worker.js');
if (fs.existsSync(serviceWorkerSourcePath)) {

View File

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

View File

@@ -1,11 +1,61 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { startDevServer } from '@web/dev-server';
import { fromRollup } from '@web/dev-server-rollup';
import { metaConfigToWebDevServerConfig } from 'plugins-manager';
import { executeSetupFunctions } from 'plugins-manager';
/** @typedef {import('../types/main').RocketCliOptions} RocketCliOptions */
/** @typedef {import('@web/dev-server').DevServerConfig} DevServerConfig */
/**
* @param {any} config
* @param {MetaPluginWrapable[]} metaPlugins
* @param {object} [options]
* @param {function | null} [options.rollupWrapperFunction]
*/
export function metaConfigToWebDevServerConfig(
config,
metaPlugins,
{ rollupWrapperFunction = null } = {},
) {
if (config.plugins) {
delete config.setupPlugins;
delete config.setupRollupPlugins;
return config;
}
const metaPluginsNoWrap = metaPlugins.map(pluginObj => {
pluginObj.__noWrap = true;
return pluginObj;
});
const rollupPlugins = /** @type {MetaPluginWrapable[]} */ (executeSetupFunctions(
config.setupRollupPlugins,
[...metaPluginsNoWrap],
));
const wrappedRollupPlugins = rollupPlugins.map(pluginObj => {
if (typeof rollupWrapperFunction === 'function' && pluginObj.__noWrap !== true) {
pluginObj.plugin = rollupWrapperFunction(pluginObj.plugin);
}
return pluginObj;
});
const _metaPlugins = executeSetupFunctions(config.setupPlugins, [...wrappedRollupPlugins]);
const plugins = _metaPlugins.map(pluginObj => {
if (pluginObj.options) {
return pluginObj.plugin(pluginObj.options);
} else {
return pluginObj.plugin();
}
});
config.plugins = plugins;
delete config.setupPlugins;
delete config.setupRollupPlugins;
return config;
}
export class RocketStart {
static pluginName = 'RocketStart';
commands = ['start'];

View File

@@ -33,7 +33,7 @@ function replaceBetween({ html, start, end, insert = '' }) {
const i = start.line;
const line = lines[i];
const upToChange = line.slice(0, start.character);
const afterChange = line.slice(end.character - 4);
const afterChange = line.slice(end.character);
lines[i] = `${upToChange}${insert}${afterChange}`;
return lines.join('\n');
@@ -103,7 +103,8 @@ function getImages(html, { imagePresets }) {
if (ev === SaxEventType.CloseTag) {
const data = /** @type {Tag} */ (/** @type {any} */ (_data));
if (data.name === 'img') {
const { openStart, closeEnd } = data;
// Img tag only has open tag.
const { openStart, openEnd } = data;
const attributes = getAttributes(data);
const presetName = getAttribute(data, 'rocket-image');
@@ -127,7 +128,7 @@ function getImages(html, { imagePresets }) {
title,
alt,
openStart,
closeEnd,
openEnd,
});
}
}
@@ -219,7 +220,7 @@ function updateHtml(html, changes) {
newHtml = replaceBetween({
html: newHtml,
start: change.openStart,
end: change.closeEnd,
end: change.openEnd,
insert: change.newHtml,
});
}

View File

@@ -174,11 +174,7 @@ export async function normalizeConfig(inConfig) {
config._presetPaths.push(path.resolve(_inputDirCwdRelative));
/** @type {MetaPlugin[]} */
let pluginsMeta = [
{ name: 'RocketStart', plugin: RocketStart },
{ name: 'RocketBuild', plugin: RocketBuild },
{ name: 'RocketLint', plugin: RocketLint },
];
let pluginsMeta = [{ plugin: RocketStart }, { plugin: RocketBuild }, { plugin: RocketLint }];
if (Array.isArray(config.setupCliPlugins)) {
for (const setupFn of config.setupCliPlugins) {

View File

@@ -5,8 +5,10 @@ const { createSocialImage: defaultCreateSocialImage } = require('./createSocialI
const { getComputedConfig } = require('./computedConfig.cjs');
const { executeSetupFunctions } = require('plugins-manager');
function titleMetaPlugin() {
return async data => {
class TitleMetaPlugin {
static dataName = 'titleMeta';
async execute(data) {
if (data.titleMeta) {
return data.titleMeta;
}
@@ -17,29 +19,35 @@ function titleMetaPlugin() {
return titleMetaFromContent;
}
return {};
};
}
}
function titlePlugin() {
return async data => {
class TitlePlugin {
static dataName = 'title';
async execute(data) {
if (data.title) {
return data.title;
}
return data.titleMeta?.title;
};
}
}
function eleventyNavigationPlugin() {
return async data => {
class EleventyNavigationPlugin {
static dataName = 'eleventyNavigation';
async execute(data) {
if (data.eleventyNavigation) {
return data.eleventyNavigation;
}
return data.titleMeta?.eleventyNavigation;
};
}
}
function sectionPlugin() {
return async data => {
class SectionPlugin {
static dataName = 'section';
async execute(data) {
if (data.section) {
return data.section;
}
@@ -52,11 +60,17 @@ function sectionPlugin() {
return parts[1];
}
}
};
}
}
function layoutPlugin({ defaultLayout = 'layout-default' } = {}) {
return async data => {
class LayoutPlugin {
static dataName = 'layout';
constructor({ defaultLayout = 'layout-default' } = {}) {
this.defaultLayout = defaultLayout;
}
async execute(data) {
if (data.layout) {
return data.layout;
}
@@ -66,22 +80,29 @@ function layoutPlugin({ defaultLayout = 'layout-default' } = {}) {
return 'layout-index';
}
}
return defaultLayout;
};
return this.defaultLayout;
}
}
function socialMediaImagePlugin(args = {}) {
const { createSocialImage = defaultCreateSocialImage, rocketConfig = {} } = args;
class SocialMediaImagePlugin {
static dataName = 'socialMediaImage';
const cleanedUpArgs = { ...args };
delete cleanedUpArgs.createSocialImage;
constructor(args = {}) {
const { createSocialImage = defaultCreateSocialImage, rocketConfig = {} } = args;
return async data => {
this.cleanedUpArgs = { ...args };
delete this.cleanedUpArgs.createSocialImage;
this.rocketConfig = rocketConfig;
this.createSocialImage = createSocialImage;
}
async execute(data) {
if (data.socialMediaImage) {
return data.socialMediaImage;
}
if (rocketConfig.createSocialMediaImages === false) {
if (this.rocketConfig.createSocialMediaImages === false) {
return;
}
@@ -95,15 +116,15 @@ function socialMediaImagePlugin(args = {}) {
const section = data.section ? ' ' + data.section[0].toUpperCase() + data.section.slice(1) : '';
const footer = `${data.site.name}${section}`;
const imgUrl = await createSocialImage({
const imgUrl = await this.createSocialImage({
title,
subTitle,
footer,
section,
...cleanedUpArgs,
...this.cleanedUpArgs,
});
return imgUrl;
};
}
}
function sortByOrder(a, b) {
@@ -146,26 +167,31 @@ async function dirToTree(sourcePath, extra = '') {
return sortedTree;
}
function joiningBlocksPlugin(rocketConfig) {
const { _inputDirCwdRelative } = rocketConfig;
const partialsSource = path.resolve(_inputDirCwdRelative, '_merged_includes');
return async () => {
const joiningBlocks = await dirToTree(partialsSource, '_joiningBlocks');
class JoiningBlocksPlugin {
static dataName = '_joiningBlocks';
constructor(rocketConfig) {
const { _inputDirCwdRelative } = rocketConfig;
this.partialsSource = path.resolve(_inputDirCwdRelative, '_merged_includes');
}
async execute() {
const joiningBlocks = await dirToTree(this.partialsSource, '_joiningBlocks');
return joiningBlocks;
};
}
}
function generateEleventyComputed() {
const rocketConfig = getComputedConfig();
let metaPlugins = [
{ name: 'titleMeta', plugin: titleMetaPlugin },
{ name: 'title', plugin: titlePlugin },
{ name: 'eleventyNavigation', plugin: eleventyNavigationPlugin },
{ name: 'section', plugin: sectionPlugin },
{ name: 'socialMediaImage', plugin: socialMediaImagePlugin, options: { rocketConfig } },
{ name: '_joiningBlocks', plugin: joiningBlocksPlugin, options: rocketConfig },
{ name: 'layout', plugin: layoutPlugin },
{ plugin: TitleMetaPlugin, options: {} },
{ plugin: TitlePlugin, options: {} },
{ plugin: EleventyNavigationPlugin, options: {} },
{ plugin: SectionPlugin, options: {} },
{ plugin: SocialMediaImagePlugin, options: { rocketConfig } },
{ plugin: JoiningBlocksPlugin, options: rocketConfig },
{ plugin: LayoutPlugin, options: {} },
];
const finalMetaPlugins = executeSetupFunctions(
@@ -176,13 +202,24 @@ function generateEleventyComputed() {
const eleventyComputed = {};
for (const pluginObj of finalMetaPlugins) {
if (pluginObj.options) {
eleventyComputed[pluginObj.name] = pluginObj.plugin(pluginObj.options);
const inst = new pluginObj.plugin(pluginObj.options);
eleventyComputed[inst.constructor.dataName] = inst.execute.bind(inst);
} else {
eleventyComputed[pluginObj.name] = pluginObj.plugin();
const inst = new pluginObj.plugin();
eleventyComputed[inst.constructor.dataName] = inst.execute.bind(inst);
}
}
return eleventyComputed;
}
module.exports = { generateEleventyComputed };
module.exports = {
generateEleventyComputed,
LayoutPlugin,
TitleMetaPlugin,
TitlePlugin,
EleventyNavigationPlugin,
SectionPlugin,
SocialMediaImagePlugin,
JoiningBlocksPlugin,
};

View File

@@ -1,5 +1,6 @@
const eleventyPluginMdjsUnified = require('@rocket/eleventy-plugin-mdjs-unified');
const eleventyRocketNav = require('@rocket/eleventy-rocket-nav');
const remark2rehype = require('remark-rehype');
const { getComputedConfig } = require('../public/computedConfig.cjs');
const rocketFilters = require('../eleventy-plugins/rocketFilters.cjs');
@@ -9,7 +10,7 @@ const { adjustPluginOptions } = require('plugins-manager');
const image = require('./mdjsImageHandler.cjs');
const defaultSetupUnifiedPlugins = [
adjustPluginOptions('remark2rehype', {
adjustPluginOptions(remark2rehype, {
handlers: {
image,
},
@@ -23,28 +24,24 @@ module.exports = function (eleventyConfig) {
let metaPlugins = [
{
name: 'rocket-filters',
plugin: rocketFilters,
options: { _inputDirCwdRelative },
},
{
name: 'rocket-copy',
plugin: rocketCopy,
options: { _inputDirCwdRelative },
},
{
name: 'eleventy-plugin-mdjs-unified',
plugin: eleventyPluginMdjsUnified,
options: {
setupUnifiedPlugins: [...defaultSetupUnifiedPlugins, ...config.setupUnifiedPlugins],
},
},
{
name: 'eleventy-rocket-nav',
plugin: eleventyRocketNav,
options: {},
},
{
name: 'rocket-collections',
plugin: rocketCollections,
options: { _inputDirCwdRelative },
},
@@ -69,7 +66,7 @@ module.exports = function (eleventyConfig) {
}
if (config.eleventy) {
const returnValue = config.eleventy(eleventyConfig);
const returnValue = config.eleventy(eleventyConfig, config);
if (returnValue) {
const returnString = JSON.stringify(returnValue, null, 2);
const msg = [

View File

@@ -91,86 +91,78 @@ export async function readOutput(
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) {
const cwd = path.join(fixtureDir, pathToDir);
const paths = await globby('**/*', { cwd, absolute: true, dot: true });
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();
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(cli.config.outputDevDir);
await fs.emptyDir(cli.config.outputDir);
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) {
const configFileDir = path.join(fixtureDir, pathToDir.split('/').join(path.sep));
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 execute(cli, configFileDir);
return cli;
}
await cli.run();
export async function executeStart(pathToConfig) {
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;
return { cli };
}
export function trimWhiteSpace(inString) {

View File

@@ -1,17 +1,11 @@
import chai from 'chai';
import chalk from 'chalk';
import {
executeBuild,
executeStart,
readBuildOutput,
readStartOutput,
setFixtureDir,
} from '@rocket/cli/test-helpers';
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
describe('RocketCli computedConfig', () => {
let cli;
let cleanupCli;
before(() => {
// ignore colors in tests as most CIs won't support it
@@ -20,90 +14,117 @@ describe('RocketCli computedConfig', () => {
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
if (cleanupCli?.cleanup) {
await cleanupCli.cleanup();
}
});
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');
expect(indexTitle).to.equal('Root');
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');
expect(subTitle).to.equal('Root: 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');
expect(subSubTitle).to.equal('Sub: SubSub');
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');
expect(sub2Title).to.equal('Root: 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');
expect(withDataTitle).to.equal('Set via data');
expect(withDataSection).be.undefined;
});
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('');
});
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,
});
expect(indexHtml).to.equal('/_merged_assets/11ty-img/5893749-1200.png');
});
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');
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');
const gettingStartedHtml = await readStartOutput(
cli,
'guides/first-pages/getting-started/index.html',
);
const gettingStartedHtml = await readOutput('guides/first-pages/getting-started/index.html');
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 () => {
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');
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');
const gettingStartedHtml = await readStartOutput(
cli,
'guides/first-pages/getting-started/index.html',
);
const gettingStartedHtml = await readOutput('guides/first-pages/getting-started/index.html');
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 () => {
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 = [
'<p>',
@@ -127,22 +148,22 @@ describe('RocketCli computedConfig', () => {
'</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(
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(
[...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(
'<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(
[
'<div>',
@@ -159,7 +180,7 @@ describe('RocketCli computedConfig', () => {
);
// 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(
[
'<p>',
@@ -188,19 +209,28 @@ describe('RocketCli computedConfig', () => {
});
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');
});
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">');
const pageHtml = await readStartOutput(cli, 'page/index.html');
const pageHtml = await readOutput('page/index.html');
expect(pageHtml).to.include('<body layout="layout-default">');
});
});

View File

@@ -2,13 +2,9 @@ import chai from 'chai';
import fetch from 'node-fetch';
import chalk from 'chalk';
import {
execute,
executeBootstrap,
executeBuild,
executeLint,
executeStart,
expectThrowsAsync,
readBuildOutput,
readStartOutput,
getfixtureExpectedFiles,
setFixtureDir,
} from '@rocket/cli/test-helpers';
@@ -17,7 +13,7 @@ import fs from 'fs-extra';
const { expect } = chai;
describe('RocketCli e2e', () => {
let cli;
let cleanupCli;
before(() => {
// ignore colors in tests as most CIs won't support it
@@ -26,20 +22,24 @@ describe('RocketCli e2e', () => {
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
if (cleanupCli?.cleanup) {
await cleanupCli.cleanup();
}
});
it('can add a unified plugin via the config', async () => {
cli = await executeStart('e2e-fixtures/unified-plugin/rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html');
const { cli, readOutput } = await execute('e2e-fixtures/unified-plugin/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal(`<p>See a 🐶</p>`);
});
describe('bootstrap command', () => {
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')) {
const actual = await fs.readFile(
@@ -54,8 +54,11 @@ describe('RocketCli e2e', () => {
describe('eleventy in config', () => {
it('can modify eleventy via an elventy function in the config', async () => {
cli = await executeStart('e2e-fixtures/content/eleventy.rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html');
const { cli, readOutput } = await execute('e2e-fixtures/content/eleventy.rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal(
['# 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 () => {
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.*/,
},
@@ -73,13 +77,23 @@ describe('RocketCli e2e', () => {
describe('setupDevAndBuildPlugins in config', () => {
it('can add a rollup plugin via setupDevAndBuildPlugins for build command', async () => {
cli = await executeBuild('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js');
const inlineModule = await readBuildOutput(cli, 'e97af63d.js');
const { cli, readOutput } = await execute(
'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);');
});
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');
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 () => {
cli = await executeBuild('e2e-fixtures/rollup-plugin/devbuild-build.rocket.config.js');
const inlineModule = await readBuildOutput(cli, 'e97af63d.js');
const { cli, readOutput } = await execute(
'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);');
});
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>');
});
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(
'<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 () => {
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(
['<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">');
const imageHtml = await readStartOutput(cli, 'image/index.html', { replaceImageHashes: true });
const imageHtml = await readOutput('image/index.html', { replaceImageHashes: true });
expect(imageHtml).to.equal(
[
'<p>',
@@ -147,9 +180,13 @@ describe('RocketCli e2e', () => {
});
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,
});
expect(linkHtml).to.equal(
@@ -157,11 +194,11 @@ describe('RocketCli e2e', () => {
'\n',
),
);
const assetHtml = await readBuildOutput(cli, 'use-assets/index.html');
const assetHtml = await readOutput('use-assets/index.html');
expect(assetHtml).to.equal(
'<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__.');
expect(imageHtml).to.equal(
[
@@ -184,8 +221,63 @@ describe('RocketCli e2e', () => {
});
it('smoke test for link checking', async () => {
await expectThrowsAsync(() => executeLint('e2e-fixtures/lint-links/rocket.config.js'), {
errorMatch: /Found 1 missing reference targets/,
await expectThrowsAsync(
() => 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 () => {
const { cli, readOutput } = await execute('e2e-fixtures/rollup-override/rocket.config.js', {
captureLog: true,
type: 'build',
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html', {
stripToBody: true,
formatHtml: true,
});
expect(indexHtml).to.equal(
[
'<h1 id="importing-foo">',
' <a aria-hidden="true" tabindex="-1" href="#importing-foo"><span class="icon icon-link"></span></a',
' >Importing foo',
'</h1>',
'',
'<script type="module" src="./7338509a.js" mdjs-setup=""></script>',
].join('\n'),
);
});
describe('can adjust the eleventy config while having access to the rocketConfig', () => {
it('testing start', async () => {
const { cli, readOutput } = await execute(
'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>');
});
it('testing build', async () => {
const { cli, readOutput } = await execute(
'e2e-fixtures/adjust-eleventy-config/rocket.config.js',
{
captureLog: true,
type: 'build',
},
);
cleanupCli = cli;
const indexBuildHtml = await readOutput('index.html', {
stripToBody: true,
});
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 chalk from 'chalk';
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers';
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
describe('RocketCli images', () => {
let cli;
let cleanupCli;
before(() => {
// ignore colors in tests as most CIs won't support it
@@ -14,15 +14,18 @@ describe('RocketCli images', () => {
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
if (cleanupCli?.cleanup) {
await cleanupCli.cleanup();
}
});
describe('Images', () => {
it('does render content images responsive', async () => {
cli = await executeStart('e2e-fixtures/images/rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html', {
const { cli, readOutput } = await execute('e2e-fixtures/images/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html', {
formatHtml: true,
replaceImageHashes: true,
});
@@ -57,7 +60,7 @@ describe('RocketCli images', () => {
].join('\n'),
);
const keepSvgHtml = await readStartOutput(cli, 'ignores/index.html', {
const keepSvgHtml = await readOutput('ignores/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
@@ -101,11 +104,61 @@ describe('RocketCli images', () => {
'</p>',
].join('\n'),
);
const tableHtml = await readOutput('table/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
expect(tableHtml).to.equal(
[
'<table>',
' <thead>',
' <tr>',
' <th>Image</th>',
' </tr>',
' </thead>',
' <tbody>',
' <tr>',
' <td>',
' <figure>',
' <picture>',
' <source',
' type="image/avif"',
' srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w"',
' sizes="100vw"',
' />',
' <source',
' type="image/jpeg"',
' srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w"',
' sizes="100vw"',
' />',
' <img',
' alt="My Image Alternative Text"',
' rocket-image="responsive"',
' src="/images/__HASH__-600.jpeg"',
' width="600"',
' height="316"',
' loading="lazy"',
' decoding="async"',
' />',
' </picture>',
' <figcaption>My Image Description</figcaption>',
' </figure>',
' </td>',
' </tr>',
' </tbody>',
'</table>',
].join('\n'),
);
});
it('can configure more patterns to ignore', async () => {
cli = await executeStart('e2e-fixtures/images/ignore-more.rocket.config.js');
const keepSvgHtml = await readStartOutput(cli, 'ignores/index.html', {
const { cli, readOutput } = await execute(
'e2e-fixtures/images/ignore-more.rocket.config.js',
{ captureLog: true },
);
cleanupCli = cli;
const keepSvgHtml = await readOutput('ignores/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
@@ -132,8 +185,11 @@ describe('RocketCli images', () => {
});
it('renders multiple images in the correct order', async () => {
cli = await executeStart('e2e-fixtures/images/rocket.config.js');
const indexHtml = await readStartOutput(cli, 'two-images/index.html', {
const { cli, readOutput } = await execute('e2e-fixtures/images/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('two-images/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
@@ -196,8 +252,11 @@ describe('RocketCli images', () => {
});
it('can configure those responsive images', async () => {
cli = await executeStart('e2e-fixtures/images/small.rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html', {
const { cli, readOutput } = await execute('e2e-fixtures/images/small.rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html', {
formatHtml: true,
replaceImageHashes: true,
});
@@ -234,8 +293,11 @@ describe('RocketCli images', () => {
});
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 indexHtml = await readStartOutput(cli, 'no-title/index.html', {
const { cli, readOutput } = await execute('e2e-fixtures/images/small.rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('no-title/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
@@ -269,8 +331,12 @@ describe('RocketCli images', () => {
});
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 indexHtml = await readStartOutput(cli, 'no-title/index.html', {
const {
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,
replaceImageHashes: true,
});

View File

@@ -1,16 +1,11 @@
import chai from 'chai';
import chalk from 'chalk';
import {
executeStart,
readStartOutput,
trimWhiteSpace,
setFixtureDir,
} from '@rocket/cli/test-helpers';
import { execute, trimWhiteSpace, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
describe('RocketCli mergeTemplates', () => {
let cli;
let cleanupCli;
before(() => {
// ignore colors in tests as most CIs won't support it
@@ -19,15 +14,18 @@ describe('RocketCli mergeTemplates', () => {
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
if (cleanupCli?.cleanup) {
await cleanupCli.cleanup();
}
});
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(
[
'<p>30-first</p>',
@@ -40,9 +38,13 @@ describe('RocketCli mergeTemplates', () => {
});
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(
['<p>overwritten second</p>', '<p>third</p>', '<p>overwritten first to be last</p>'].join(
'\n',
@@ -51,9 +53,12 @@ describe('RocketCli mergeTemplates', () => {
});
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(
[
'<p>first</p>',

View File

@@ -1,11 +1,11 @@
import chai from 'chai';
import chalk from 'chalk';
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers';
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
describe('RocketCli preset', () => {
let cli;
let cleanupCli;
before(() => {
// ignore colors in tests as most CIs won't support it
@@ -14,21 +14,24 @@ describe('RocketCli preset', () => {
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
if (cleanupCli?.cleanup) {
await cleanupCli.cleanup();
}
});
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>');
const indexHtml = await readStartOutput(cli, 'index.html');
const indexHtml = await readOutput('index.html');
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,
formatHtml: true,
});
@@ -86,12 +89,6 @@ describe('RocketCli preset', () => {
' </div>',
'',
' <footer id="main-footer"></footer>',
'',
' <script',
' type="module"',
' inject-service-worker=""',
' src="/_merged_assets/scripts/registerServiceWorker.js"',
' ></script>',
' </body>',
'</html>',
].join('\n'),
@@ -99,16 +96,22 @@ describe('RocketCli preset', () => {
});
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" />');
});
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,
replaceImageHashes: true,
});

View File

@@ -1,6 +1,6 @@
import chai from 'chai';
import chalk from 'chalk';
import { executeBuild, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers';
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
@@ -17,7 +17,7 @@ function getServiceWorkerUrl(text) {
}
describe('RocketCli e2e', () => {
let cli;
let cleanupCli;
before(() => {
// ignore colors in tests as most CIs won't support it
@@ -26,20 +26,28 @@ describe('RocketCli e2e', () => {
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
if (cleanupCli?.cleanup) {
await cleanupCli.cleanup();
}
});
it('will add a script to inject the service worker', async () => {
cli = await executeBuild('e2e-fixtures/service-worker/rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html');
const { cli, readOutput } = await execute('e2e-fixtures/service-worker/rocket.config.js', {
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);
expect(indexInject).to.equal(
'<script type="module" inject-service-worker="" src="/_merged_assets/scripts/registerServiceWorker.js"></script>',
);
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);
expect(subInject).to.equal(
'<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 ...
it.skip('will add a script to inject the service worker', async () => {
cli = await executeBuild('e2e-fixtures/service-worker/pathPrefix.rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html');
const { cli, readOutput } = await execute(
'e2e-fixtures/service-worker/pathPrefix.rocket.config.js',
{
captureLog: true,
type: 'build',
},
);
cleanupCli = cli;
const indexHtml = await readOutput('index.html');
const indexInject = getInjectServiceWorker(indexHtml);
expect(indexInject).to.equal(
'<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');
const subHtml = await readStartOutput(cli, 'sub/index.html');
const subHtml = await readOutput('sub/index.html');
const subInject = getInjectServiceWorker(subHtml);
expect(subInject).to.equal(
'<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 chalk from 'chalk';
import {
executeStart,
readStartOutput,
setFixtureDir,
startOutputExist,
} from '@rocket/cli/test-helpers';
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
describe('RocketCli use cases', () => {
let cli;
let cleanupCli;
before(() => {
// ignore colors in tests as most CIs won't support it
@@ -19,18 +14,22 @@ describe('RocketCli use cases', () => {
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
if (cleanupCli?.cleanup) {
await cleanupCli.cleanup();
}
});
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
.true;
expect(outputExists('sub/assets/myData.js'), 'static files did not get copied').to.be.true;
const aboutHtml = await readStartOutput(cli, 'about/index.html', { formatHtml: true });
const aboutHtml = await readOutput('about/index.html', { formatHtml: true });
expect(aboutHtml).to.equal(
[
'<p><code>about.md</code></p>',
@@ -38,7 +37,7 @@ describe('RocketCli use cases', () => {
].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(
[
'<p><code>sub/index.md</code></p>',
@@ -46,7 +45,7 @@ describe('RocketCli use cases', () => {
].join('\n'),
);
const subDetailsHtml = await readStartOutput(cli, 'sub/details/index.html', {
const subDetailsHtml = await readOutput('sub/details/index.html', {
formatHtml: true,
});
expect(subDetailsHtml).to.equal(
@@ -56,7 +55,7 @@ describe('RocketCli use cases', () => {
].join('\n'),
);
const indexHtml = await readStartOutput(cli, 'index.html', { formatHtml: true });
const indexHtml = await readOutput('index.html', { formatHtml: true });
expect(indexHtml).to.equal(
[
'<p><code>index.md</code></p>',

View File

@@ -1,3 +1,4 @@
import remark2rehype from 'remark-rehype';
import { adjustPluginOptions } from 'plugins-manager';
function image(h, node) {
@@ -10,7 +11,7 @@ function image(h, node) {
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
setupUnifiedPlugins: [
adjustPluginOptions('remark2rehype', {
adjustPluginOptions(remark2rehype, {
handlers: {
image,
},

View File

@@ -1,8 +1,16 @@
import { addPlugin } from 'plugins-manager';
class Test {
static dataName = 'test';
execute() {
return 'test-value';
}
}
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
setupEleventyComputedConfig: [addPlugin({ name: 'test', plugin: () => 'test-value' })],
setupEleventyComputedConfig: [addPlugin(Test)],
};
export default config;

View File

@@ -1,4 +1,5 @@
import { adjustPluginOptions } from 'plugins-manager';
import { SocialMediaImagePlugin } from '@rocket/cli';
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
@@ -6,7 +7,7 @@ const config = {
createSocialMediaImages: true,
},
setupEleventyComputedConfig: [
adjustPluginOptions('socialMediaImage', {
adjustPluginOptions(SocialMediaImagePlugin, {
createSocialImageSvg: async () => {
return `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630">

View File

@@ -0,0 +1,5 @@
---
layout: layout-raw
---
<a href="{{ '/path/to/page/' | conditional-resolve }}">link</a>

View File

@@ -0,0 +1,15 @@
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
eleventy: (config, rocketConfig) => {
config.addFilter('conditional-resolve', value => {
if (rocketConfig.command === 'build') {
return `build:${value}`;
}
if (rocketConfig.command === 'start') {
return `start:${value}`;
}
});
},
};
export default config;

View File

@@ -0,0 +1,7 @@
---
layout: layout-raw
---
| Image |
| --------------------------------------------------------------------------- |
| ![My Image Alternative Text](./_assets/my-image.jpg 'My Image Description') |

View File

@@ -0,0 +1 @@
**/*.njk

View File

@@ -0,0 +1,11 @@
---
layout: layout-raw
---
# Importing foo
```js script
import { foo } from './not-foo.js';
console.log(foo);
```

View File

@@ -0,0 +1 @@
export const notFoo = 'not-foo';

View File

@@ -0,0 +1,11 @@
// @ts-no-check
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
rollup: config => ({
...config,
shimMissingExports: true,
}),
};
export default config;

View File

@@ -1,11 +1,14 @@
// @ts-no-check
import json from '@rollup/plugin-json';
import { rollupPluginHTML } from '@web/rollup-plugin-html';
import { addPlugin, adjustPluginOptions } from 'plugins-manager';
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
setupDevAndBuildPlugins: [addPlugin({ name: 'json', plugin: json, location: 'top' })],
setupBuildPlugins: [adjustPluginOptions('html', { absoluteBaseUrl: 'https://test-me.com' })],
setupDevAndBuildPlugins: [addPlugin(json, {}, { location: 'top' })],
setupBuildPlugins: [
adjustPluginOptions(rollupPluginHTML, { absoluteBaseUrl: 'https://test-me.com' }),
],
};
export default config;

View File

@@ -1,10 +1,9 @@
// @ts-no-check
import json from '@rollup/plugin-json';
import { addPlugin } from 'plugins-manager';
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
setupDevAndBuildPlugins: [addPlugin({ name: 'json', plugin: json, location: 'top' })],
setupDevAndBuildPlugins: [addPlugin(json, {}, { location: 'top' })],
devServer: {
mimeTypes: {
// serve all json files as js

View File

@@ -1,10 +1,11 @@
// @ts-check
import emoji from 'remark-emoji';
import { addPlugin } from 'plugins-manager';
import markdown from 'remark-parse';
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
setupUnifiedPlugins: [addPlugin({ location: 'markdown', name: 'emoji', plugin: emoji })],
setupUnifiedPlugins: [addPlugin(emoji, {}, { location: markdown })],
};
export default config;

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

@@ -40,6 +40,7 @@ export interface RocketCliOptions extends Pick<RocketPreset, PresetKeys> {
start?: RocketStartConfig;
// advanced
rollup?: (config: any) => void; // TODO: improve
devServer?: DevServerConfig;
eleventy?: (eleventyConfig: any) => void; // TODO: improve
plugins?: RocketPlugin[];

View File

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

View File

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

View File

@@ -1,5 +1,22 @@
# @rocket/eleventy-plugin-mdjs-unified
## 0.6.0
### Minor Changes
- 70bb7a1: BREAKING CHANGE: Updating to latest version of `@mdjs/core` which requires the latest version of `plugins-manager`
### Patch Changes
- Updated dependencies [70bb7a1]
- @mdjs/core@0.9.0
## 0.5.2
### Patch Changes
- 39f4fa7: Updates dependencies
## 0.5.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/eleventy-plugin-mdjs-unified",
"version": "0.5.1",
"version": "0.6.0",
"publishConfig": {
"access": "public"
},
@@ -31,7 +31,7 @@
"mdjs"
],
"dependencies": {
"@mdjs/core": "^0.8.1",
"@mdjs/core": "^0.9.0",
"es-module-lexer": "^0.3.26",
"unist-util-visit": "^2.0.3"
},

View File

@@ -5,6 +5,7 @@ const fs = require('fs');
const { mdjsProcess } = require('@mdjs/core');
const visit = require('unist-util-visit');
const { init, parse } = require('es-module-lexer');
const markdown = require('remark-parse');
// @ts-ignore
const { parseTitle } = require('@rocket/core/title');
@@ -45,12 +46,12 @@ function cleanupTitleHeadline() {
* @param {MdjsProcessPlugin[]} plugins
*/
function addCleanupTitleHeadline(plugins) {
if (plugins.findIndex(plugin => plugin.name === 'cleanupTitleHeadline') === -1) {
if (plugins.findIndex(pluginObj => pluginObj.plugin === cleanupTitleHeadline) === -1) {
// add plugins right after markdown
const markdownPluginIndex = plugins.findIndex(plugin => plugin.name === 'markdown');
const markdownPluginIndex = plugins.findIndex(pluginObj => pluginObj.plugin === markdown);
plugins.splice(markdownPluginIndex + 1, 0, {
name: 'cleanupTitleHeadline',
plugin: cleanupTitleHeadline,
options: {},
});
}
return plugins;

View File

@@ -1,8 +1,9 @@
const htmlHeading = require('rehype-autolink-headings');
const pluginMdjs = require('../../../index.js');
function addClassAnchorToHtmlHeading(plugins) {
return plugins.map(pluginObj => {
if (pluginObj.name === 'htmlHeading') {
if (pluginObj.plugin === htmlHeading) {
return {
...pluginObj,
options: {

View File

@@ -1,5 +1,34 @@
# @rocket/launch
## 0.6.0
### Minor Changes
- 70bb7a1: BREAKING CHANGE: Update to latest plugins manager to get type safe options
There is no longer a name string as a key for a plugin. It is identified by it's function/class. You will need to adjust your code if you are adding or adjusting plugins.
```diff
- addPlugin({ name: 'my-plugin', plugin: myPlugin, options: { myFlag: true }, location: 'top' });
+ addPlugin(myPlugin, { myFlag: true }, { location: 'top' });
- adjustPluginOptions('my-plugin', { myFlag: true });
+ adjustPluginOptions(myPlugin, { myFlag: true });
```
For more details please see the [Changelog](https://github.com/modernweb-dev/rocket/blob/main/packages/plugins-manager/CHANGELOG.md#030) of the plugins-manager package.
## 0.5.6
### Patch Changes
- 0987a41: Fix styling in darkmode
## 0.5.5
### Patch Changes
- 3d22fbb: Prevent styles from applying to lion components that are rendered in light dom
## 0.5.4
### Patch Changes

View File

@@ -28,16 +28,22 @@ For docs please see our homepage [https://rocket.modern-web.dev/docs/presets/lau
#### CSS Properties
| Name | Description |
| ---------------------------------------------- | ----------- |
| --inline-notification-tip-background-color | |
| --inline-notification-tip-border-color | |
| --inline-notification-warning-background-color | |
| --inline-notification-warning-border-color | |
| --inline-notification-danger-background-color | |
| --inline-notification-danger-border-color | |
| --inline-notification-warning-heading-color | |
| --inline-notification-danger-heading-color | |
| Name | Default | Description |
| ---------------------------------------------- | -------------------------- | ----------- |
| --inline-notification-tip-background-color | `rgba(221, 221, 221, 0.3)` | |
| --inline-notification-tip-border-color | `#42b983` | |
| --inline-notification-warning-background-color | `rgba(255, 229, 100, 0.2)` | |
| --inline-notification-warning-border-color | `#e7c000` | |
| --inline-notification-danger-background-color | `rgba(192, 0, 0, 0.1)` | |
| --inline-notification-danger-border-color | `#c00` | |
| --inline-notification-warning-heading-color | `#b29400` | |
| --inline-notification-danger-heading-color | `#900` | |
#### CSS Parts
| Name | Description |
| ----- | ----------------- |
| title | the title heading |
<hr/>

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/launch",
"version": "0.5.4",
"version": "0.6.0",
"publishConfig": {
"access": "public"
},

View File

@@ -1,7 +1,6 @@
@font-face {
font-family: octicons-link;
src:
url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==)
src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==)
format('woff');
}
@@ -121,7 +120,7 @@
overflow: visible;
}
.markdown-body [type='checkbox'] {
.markdown-body input[type='checkbox'] {
box-sizing: border-box;
padding: 0;
}

View File

@@ -5,6 +5,7 @@ html {
--primary-color-accent: #cee5f6;
--primary-text-color: #2c3e50;
--primary-lines-color: #ccc;
--primary-text-inverse-color: #eee;
/* Contrast colors */
--contrast-color-light: #fff;
@@ -19,6 +20,10 @@ html {
--primary-font-family: 'Open Sans', sans-serif;
--secondary-font-family: 'Montserrat', sans-serif;
--monospace-font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', 'Courier', monospace;
/* controls */
--switch-unselected-color: #808080;
--switch-selected-color: #42b983;
}
html.dark {
@@ -27,6 +32,7 @@ html.dark {
--primary-color-darker: #a22831;
--primary-color-accent: #cee5f6;
--primary-text-color: #eee;
--primary-text-inverse-color: #2c3e50;
/* Contrast colors */
--contrast-color-light: #fff;
@@ -39,6 +45,10 @@ html.dark {
/* typography */
--text-color: white;
/* controls */
--switch-unselected-color: #808080;
--switch-selected-color: #42b983;
/* markdown */
--markdown-octicon-link: white;
--markdown-syntax-background-color: #a0a0a0;

View File

@@ -2,12 +2,14 @@ import path from 'path';
import { adjustPluginOptions } from 'plugins-manager';
// import { addPlugin } from 'plugins-manager';
import { fileURLToPath } from 'url';
import { LayoutPlugin } from '@rocket/cli';
import htmlHeading from 'rehype-autolink-headings';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
function addOcticonToHeadlines(plugins) {
return plugins.map(pluginObj => {
if (pluginObj.name === 'htmlHeading') {
if (pluginObj.plugin === htmlHeading) {
return {
...pluginObj,
options: {
@@ -50,7 +52,7 @@ export function rocketLaunch() {
path: path.resolve(__dirname),
setupUnifiedPlugins: [addOcticonToHeadlines],
setupEleventyComputedConfig: [
adjustPluginOptions('layout', { defaultLayout: 'layout-sidebar' }),
adjustPluginOptions(LayoutPlugin, { defaultLayout: 'layout-sidebar' }),
],
adjustImagePresets: imagePresets => ({
...imagePresets,

View File

@@ -1,11 +1,11 @@
import chai from 'chai';
import chalk from 'chalk';
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers';
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
describe('RocketLaunch preset', () => {
let cli;
let cleanupCli;
before(() => {
// ignore colors in tests as most CIs won't support it
@@ -14,15 +14,18 @@ describe('RocketLaunch preset', () => {
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
if (cleanupCli?.cleanup) {
await cleanupCli.cleanup();
}
});
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,
formatHtml: true,
});
@@ -244,12 +247,6 @@ describe('RocketLaunch preset', () => {
' </footer>',
'',
' <script type="module" src="/_merged_assets/scripts/init-navigation.js"></script>',
'',
' <script',
' type="module"',
' inject-service-worker=""',
' src="/_merged_assets/scripts/registerServiceWorker.js"',
' ></script>',
' </body>',
'</html>',
].join('\n'),
@@ -257,9 +254,12 @@ describe('RocketLaunch preset', () => {
});
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,
formatHtml: true,
});
@@ -508,12 +508,6 @@ describe('RocketLaunch preset', () => {
' </footer>',
'',
' <script type="module" src="/_merged_assets/scripts/init-navigation.js"></script>',
'',
' <script',
' type="module"',
' inject-service-worker=""',
' src="/_merged_assets/scripts/registerServiceWorker.js"',
' ></script>',
' </body>',
'</html>',
].join('\n'),

View File

@@ -1,5 +1,76 @@
# 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
### Minor Changes
- 70bb7a1: BREAKING CHANGE: Update to latest plugins manager to get type safe options
There is no longer a name string as a key for a plugin. It is identified by it's function/class. You will need to adjust your code if you are adding or adjusting plugins.
```diff
- addPlugin({ name: 'my-plugin', plugin: myPlugin, options: { myFlag: true }, location: 'top' });
+ addPlugin(myPlugin, { myFlag: true }, { location: 'top' });
- adjustPluginOptions('my-plugin', { myFlag: true });
+ adjustPluginOptions(myPlugin, { myFlag: true });
```
For more details please see the [Changelog](https://github.com/modernweb-dev/rocket/blob/main/packages/plugins-manager/CHANGELOG.md#030) of the plugins-manager package.
### Patch Changes
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- Updated dependencies [70bb7a1]
- plugins-manager@0.3.0
## 0.8.2
### Patch Changes
- a5661b8: Updates dependencies
## 0.8.1
### Patch Changes

View File

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

View File

@@ -3,6 +3,7 @@
/** @typedef {import('@mdjs/core/types/code').MdjsProcessPlugin} MdjsProcessPlugin */
const { mdjsParse } = require('./src/mdjsParse.js');
const { mdjsSetupCode } = require('./src/mdjsSetupCode.js');
const { mdjsStoryParse } = require('./src/mdjsStoryParse.js');
const { mdjsDocPage } = require('./src/mdjsDocPage.js');
const { mdjsProcess } = require('./src/mdjsProcess.js');
@@ -14,4 +15,5 @@ module.exports = {
mdjsDocPage,
mdjsProcess,
isMdjsContent,
mdjsSetupCode,
};

View File

@@ -1,5 +1,12 @@
import cjsEntrypoint from './index.js';
const { mdjsParse, mdjsStoryParse, mdjsDocPage, mdjsProcess, isMdjsContent } = cjsEntrypoint;
const {
mdjsParse,
mdjsStoryParse,
mdjsDocPage,
mdjsProcess,
isMdjsContent,
mdjsSetupCode,
} = cjsEntrypoint;
export { mdjsParse, mdjsStoryParse, mdjsDocPage, mdjsProcess, isMdjsContent };
export { mdjsParse, mdjsStoryParse, mdjsDocPage, mdjsProcess, isMdjsContent, mdjsSetupCode };

View File

@@ -1,6 +1,6 @@
{
"name": "@mdjs/core",
"version": "0.8.1",
"version": "0.9.1",
"publishConfig": {
"access": "public"
},
@@ -21,6 +21,7 @@
}
},
"scripts": {
"prepublishOnly": "publish-docs --github-url https://github.com/modernweb-dev/rocket/ --git-root-dir ../../",
"start": "npm run start:stories",
"start:script": "web-dev-server -c demo/script/server.js --root-dir ../../",
"start:stories": "web-dev-server -c demo/stories/server.js --root-dir ../../",
@@ -44,12 +45,12 @@
"remark"
],
"dependencies": {
"@mdjs/mdjs-preview": "^0.5.1",
"@mdjs/mdjs-preview": "^0.5.3",
"@mdjs/mdjs-story": "^0.3.0",
"@types/unist": "^2.0.3",
"es-module-lexer": "^0.3.26",
"github-markdown-css": "^4.0.0",
"plugins-manager": "^0.2.3",
"plugins-manager": "^0.3.0",
"rehype-autolink-headings": "^5.0.1",
"rehype-prism-template": "^0.4.1",
"rehype-raw": "^5.0.0",
@@ -66,7 +67,7 @@
"devDependencies": {
"demo-wc-card": "^0.1.0",
"remark-autolink-headings": "^6.0.1",
"remark-html": "^13.0.1",
"remark-html": "^13.0.2",
"remark-slug": "^6.0.0",
"remark-stringify": "^9.0.1"
},

View File

@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
/** @typedef {import('@mdjs/core/types/code').Story} Story */
/** @typedef {import('@mdjs/core/types/code').ParseResult} ParseResult */
/** @typedef {import('@mdjs/core/types/code').ProcessResult} ProcessResult */
/** @typedef {import('@mdjs/core/types/code').MdjsProcessPlugin} MdjsProcessPlugin */
/** @typedef {import('../types/code').Story} Story */
/** @typedef {import('../types/code').ParseResult} ParseResult */
/** @typedef {import('../types/code').ProcessResult} ProcessResult */
/** @typedef {import('../types/code').MdjsProcessPlugin} MdjsProcessPlugin */
const unified = require('unified');
const markdown = require('remark-parse');
@@ -22,23 +22,23 @@ const { mdjsSetupCode } = require('./mdjsSetupCode.js');
/** @type {MdjsProcessPlugin[]} */
const defaultMetaPlugins = [
{ name: 'markdown', plugin: markdown },
{ name: 'gfm', plugin: gfm },
{ name: 'mdjsParse', plugin: mdjsParse },
{ name: 'mdjsStoryParse', plugin: mdjsStoryParse },
{ name: 'mdjsSetupCode', plugin: mdjsSetupCode },
{ plugin: markdown, options: {} },
{ plugin: gfm, options: {} },
{ plugin: mdjsParse, options: {} },
{ plugin: mdjsStoryParse, options: {} },
{ plugin: mdjsSetupCode, options: {} },
// @ts-ignore
{ name: 'remark2rehype', plugin: remark2rehype, options: { allowDangerousHtml: true } },
{ plugin: remark2rehype, options: { allowDangerousHtml: true } },
// @ts-ignore
{ name: 'rehypePrism', plugin: rehypePrism },
{ plugin: rehypePrism, options: {} },
// @ts-ignore
{ name: 'raw', plugin: raw },
{ plugin: raw, options: {} },
// @ts-ignore
{ name: 'htmlSlug', plugin: htmlSlug },
{ plugin: htmlSlug, options: {} },
// @ts-ignore
{ name: 'htmlHeading', plugin: htmlHeading },
{ plugin: htmlHeading, options: {} },
// @ts-ignore
{ name: 'htmlStringify', plugin: htmlStringify },
{ plugin: htmlStringify, options: {} },
];
/**
@@ -57,33 +57,8 @@ async function mdjsProcess(mdjs, { setupUnifiedPlugins = [] } = {}) {
const metaPlugins = executeSetupFunctions(setupUnifiedPlugins, defaultMetaPlugins);
/**
* @param {string} code
*/
async function highlightCode(code) {
// @ts-ignore
const codePlugins = metaPlugins.filter(pluginObj =>
['markdown', 'remark2rehype', 'rehypePrism', 'htmlStringify'].includes(pluginObj.name),
);
const codeParser = unified();
// @ts-ignore
for (const pluginObj of codePlugins) {
codeParser.use(pluginObj.plugin, pluginObj.options);
}
const codeResult = await codeParser.process(code);
return codeResult.contents;
}
// @ts-ignore
for (const pluginObj of metaPlugins) {
if (pluginObj.name === 'mdjsSetupCode') {
if (pluginObj.options && !pluginObj.options.highlightCode) {
pluginObj.options.highlightCode = highlightCode;
}
if (!pluginObj.options) {
pluginObj.options = { highlightCode };
}
}
// @ts-ignore
parser.use(pluginObj.plugin, pluginObj.options);
}

View File

@@ -77,17 +77,32 @@ function mdjsStoryParse({
const newValue = previewStoryTag(storyData.name);
if (newValue.includes('[[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 = {
type: 'root',
children: [
{ type: 'html', value: tagParts[0] },
{ type: 'text', value: '\n\n' },
node,
...inside,
{ type: 'text', value: '\n\n' },
{ type: 'html', value: tagParts[1] },
],
};
parent.children.splice(index, 1, node);
parent.children.splice(index, skipAmount, node);
} else {
node.type = 'html';
node.value = previewStoryTag(storyData.name);
@@ -115,17 +130,31 @@ function mdjsStoryParse({
const newValue = previewStoryTag(storyData.name);
if (newValue.includes('[[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 = {
type: 'root',
children: [
{ type: 'html', value: tagParts[0] },
{ type: 'text', value: '\n\n' },
node,
...inside,
{ type: 'text', value: '\n\n' },
{ type: 'html', value: tagParts[1] },
],
};
parent.children.splice(index, 1, node);
parent.children.splice(index, skipAmount, node);
} else {
node.type = 'html';
node.value = previewStoryTag(storyData.name);

View File

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

View File

@@ -3,6 +3,8 @@
const chai = require('chai');
const { adjustPluginOptions } = require('plugins-manager');
const { mdjsProcess } = require('../src/mdjsProcess.js');
const { mdjsSetupCode } = require('../src/mdjsSetupCode.js');
const { mdjsStoryParse } = require('../src/mdjsStoryParse.js');
const { expect } = chai;
@@ -106,7 +108,7 @@ describe('mdjsProcess', () => {
function replaceStoryTag(plugins) {
return plugins.map(pluginObj => {
if (pluginObj.name === 'mdjsStoryParse') {
if (pluginObj.plugin === mdjsStoryParse) {
return {
...pluginObj,
options: {
@@ -136,7 +138,7 @@ describe('mdjsProcess', () => {
function replaceStoryTag2(plugins) {
return plugins.map(pluginObj => {
if (pluginObj.name === 'mdjsStoryParse') {
if (pluginObj.plugin === mdjsStoryParse) {
return {
...pluginObj,
options: {
@@ -202,7 +204,7 @@ describe('mdjsProcess', () => {
].join('\n');
const result = await mdjsProcess(input, {
setupUnifiedPlugins: [
adjustPluginOptions('mdjsSetupCode', {
adjustPluginOptions(mdjsSetupCode, {
simulationSettings: { languages: [{ key: 'en', name: 'English' }] },
}),
],

View File

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

View File

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

View File

@@ -31,4 +31,4 @@ export interface ParseResult {
};
}
export type MdjsProcessPlugin = MetaPlugin<unified.Plugin, unified.Settings>;
export type MdjsProcessPlugin = MetaPlugin<unified.Plugin>;

View File

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

Some files were not shown because too many files have changed in this diff Show More