Compare commits

...

25 Commits

Author SHA1 Message Date
Thomas Allmer
0166dc6f04 feat(web-menu): initial release 2021-11-07 13:53:04 +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
245 changed files with 6628 additions and 1148 deletions

1
.gitignore vendored
View File

@@ -40,3 +40,4 @@ _merged_assets
_merged_includes _merged_includes
__output __output
__output-dev __output-dev
docs_backup

View File

@@ -1,4 +1,6 @@
--- ---
layout: layout-404 layout: layout-404
permalink: 404.html permalink: 404.html
menu:
exclude: true
--- ---

View File

@@ -1,8 +1,8 @@
:not(rocket-navigation):not(:defined) { :not(web-menu):not(:defined) {
opacity: 0; opacity: 0;
} }
rocket-navigation, web-menu,
header { header {
font-family: 'Montserrat', sans-serif; font-family: 'Montserrat', sans-serif;
} }

View File

@@ -19,6 +19,9 @@ html {
--primary-color: rgb(44, 62, 80); --primary-color: rgb(44, 62, 80);
--primary-lines-color: #ccc; --primary-lines-color: #ccc;
--primary-text-color: #2c3e50; --primary-text-color: #2c3e50;
--primary-text-inverse-color: #eee;
--switch-unselected-color: #808080;
--switch-selected-color: #42b983;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
@@ -45,6 +48,9 @@ html {
--rocket-search-highlight-color: #41ffb0; --rocket-search-highlight-color: #41ffb0;
--rocket-search-hover-background-color: #6b717a; --rocket-search-hover-background-color: #6b717a;
--rocket-search-fill-color: #fff; --rocket-search-fill-color: #fff;
--primary-text-inverse-color: #2c3e50;
--switch-unselected-color: #808080;
--switch-selected-color: #42b983;
/* Markdown */ /* Markdown */
--markdown-octicon-link: var(--primary-text-color); --markdown-octicon-link: var(--primary-text-color);

View File

@@ -0,0 +1,3 @@
module.exports = {
layout: 'layout-blog-details',
};

View File

@@ -107,3 +107,60 @@ export default ({
}); });
``` ```
<!-- prettier-ignore-end --> <!-- 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

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

View File

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

View File

@@ -1,4 +1,3 @@
# Presets >> Launch || 20 # Presets >> Launch || 20
- [Preset](./preset/) - [Preset](./preset/)
- [Custom Elements](./custom-elements/)

View File

@@ -1,4 +1,3 @@
# Presets >> Search || 10 # Presets >> Search || 10
- [Preset](./preset/) - [Preset](./preset/)
- [Custom Elements](./custom-elements/)

View File

@@ -3,6 +3,111 @@
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). 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. 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 ## Problem
Many plugin systems require you to either execute a plugin function like in `rollup`. Many plugin systems require you to either execute a plugin function like in `rollup`.
@@ -48,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 The plugins manager lets you orchestrate a set of "meta plugins" which are defined by
- name - plugin (class or function)
- plugin - it's options
- options
```js ```js
import beep from '@rollup/plugin-beep'; import beep from '@rollup/plugin-beep';
import url from '@rollup/plugin-url'; import url from '@rollup/plugin-url';
let metaPlugins = [ let metaPlugins = [{ plugin: beep }, { plugin: url, options: { limit: 10000 } }];
{ name: 'beep', plugin: beep },
{ name: 'url', plugin: url, options: { limit: 10000 } },
];
``` ```
This array can be modified by adding/removing or adjusting options. This array can be modified by adding/removing or adjusting options.
@@ -94,16 +195,13 @@ export default {
### Adding Helpers ### 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 ```js
import { addPlugin, adjustPluginOptions } from 'plugins-manager'; import { addPlugin, adjustPluginOptions } from 'plugins-manager';
const systemSetupFunctions = [ const systemSetupFunctions = [addPlugin(first), addPlugin(second)];
addPlugin({ name: 'first', plugin: first }), const userSetupFunctions = [adjustPluginOptions(first, { my: 'options' })];
addPlugin({ name: 'second', plugin: second }),
];
const userSetupFunctions = [adjustPluginOptions('first', { my: 'options' })];
``` ```
Arrays of functions can by merged like so Arrays of functions can by merged like so
@@ -115,9 +213,9 @@ const finalSetupFunctions = [...systemSetupFunctions, ...userSetupFunctions];
and then converted to the final output. and then converted to the final output.
```js ```js
import { metaPluginsToRollupPlugins } from 'plugins-manager'; import { applyPlugins } from 'plugins-manager';
const plugins = metaPluginsToRollupPlugins(finalSetupFunctions, metaPlugins); const plugins = applyPlugins(finalSetupFunctions, metaPlugins);
``` ```
## Adding a Plugin ## Adding a Plugin
@@ -133,18 +231,27 @@ By default it adds at the bottom.
import json from '@rollup/plugin-json'; import json from '@rollup/plugin-json';
import { addPlugin } from 'plugins-manager'; import { addPlugin } from 'plugins-manager';
const userSetupFunctions = [ const userSetupFunctions = [addPlugin(json, { preferConst: true })];
addPlugin({ name: 'json', plugin: json, options: { preferConst: true } }),
];
``` ```
Example usage: Example usage:
```js ```js
addPlugin({ name: 'json', plugin: json }); // Add at the bottom (default) addPlugin(json); // Add at the bottom (default)
addPlugin({ name: 'json', plugin: json, location: 'top' }); // Add at the top/beginning of the array addPlugin(json, {}, { location: 'top' }); // Add at the top/beginning of the array
addPlugin({ name: 'json', plugin: json, location: 'beep' }); // Add after (default) plugin 'beep' addPlugin(json, {}, { location: beep }); // Add after (default) plugin 'beep'
addPlugin({ name: 'json', plugin: json, location: 'beep', how: 'before' }); // Add before 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 ## Adjusting Plugin Options
@@ -154,12 +261,14 @@ Adjusting options means to either
- flatly merge objects (e.g. only the first level will be preserved) - flatly merge objects (e.g. only the first level will be preserved)
- calling a function to do the merge yourself - calling a function to do the merge yourself
- setting the raw value (if not an object or function) - 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 ```js
import json from '@rollup/plugin-json';
import { adjustPluginOptions } from 'plugins-manager'; import { adjustPluginOptions } from 'plugins-manager';
const userSetupFunctions = [ const userSetupFunctions = [
adjustPluginOptions('json', { preferConst: false, anotherOption: 'format' }), adjustPluginOptions(json, { preferConst: false, anotherOption: 'format' }),
]; ];
``` ```
@@ -167,36 +276,53 @@ Example usage:
```js ```js
// given // given
addPlugin({ addPlugin(json, {
name: 'json', other: {
plugin: json, nested: 'other.nested',
options: { nested2: 'other.nested2',
other: {
nested: 'other.nested',
nested2: 'other.nested2',
},
main: true,
}, },
main: true,
}); });
// merge objects flately // merge objects flately
adjustPluginOptions('json', { other: { nested: '--overwritten--' } }); adjustPluginOptions(json, { other: { nested: '--overwritten--' } });
// resulting options = { other: { nested: '--overwritten--' }, main: true } // resulting options = { other: { nested: '--overwritten--' }, main: true }
// NOTE: nested2 is removed // NOTE: nested2 is removed
// merge via function // 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 } // resulting options = { other: { nested: '--overwritten--', nested2: 'other.nested2' }, main: true }
// merge via function to override full options // merge via function to override full options
adjustPluginOptions('json', config => ({ only: 'this' })); adjustPluginOptions(json, config => ({ only: 'this' }));
// resulting options = { only: 'this' } // resulting options = { only: 'this' }
// setting a raw value // setting a raw value
adjustPluginOptions('json', false); adjustPluginOptions(json, false);
// resulting options = 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 ## Converting metaPlugins to an Actual Plugin
To execute all setup function you can use this little helper To execute all setup function you can use this little helper
@@ -227,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` Note: if you provide `config.plugins` then it will return that directly ignoring `setupPlugins`
```js ```js
import { metaConfigToRollupConfig } from 'plugins-manager'; import { applyPlugins } from 'plugins-manager';
const finalConfig = metaConfigToRollupConfig(currentConfig, defaultMetaPlugins); const finalConfig = applyPlugins(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,
});
``` ```
Eleventy Eleventy

View File

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

View File

@@ -29,14 +29,15 @@
"postinstall": "npm run setup", "postinstall": "npm run setup",
"release": "changeset publish && yarn format", "release": "changeset publish && yarn format",
"rocket:build": "node packages/cli/src/cli.js build", "rocket:build": "node packages/cli/src/cli.js build",
"rocket:upgrade": "node packages/cli/src/cli.js upgrade",
"search": "node packages/cli/src/cli.js search", "search": "node packages/cli/src/cli.js search",
"setup": "npm run setup:ts-configs && npm run build:packages", "setup": "npm run setup:ts-configs && npm run build:packages",
"setup:patches": "npx patch-package", "setup:patches": "npx patch-package",
"setup:ts-configs": "node scripts/generate-ts-configs.mjs", "setup:ts-configs": "node scripts/generate-ts-configs.mjs",
"prestart": "yarn analyze", "xprestart": "yarn analyze",
"start": "node packages/cli/src/cli.js start", "start": "node --trace-warnings packages/cli/src/cli.js start",
"test": "yarn test:node && yarn test:web", "test": "yarn test:node && yarn test:web",
"test:node": "mocha \"packages/*/test-node/**/*.test.{ts,js,mjs,cjs}\" --timeout 5000 --reporter dot --exit", "test:node": "mocha \"packages/*/test-node/**/*.test.{ts,js,mjs,cjs}\" -- --timeout 5000 --reporter dot --exit",
"test:web": "web-test-runner", "test:web": "web-test-runner",
"types": "run-s types:clear types:copy types:build", "types": "run-s types:clear types:copy types:build",
"types:build": "tsc --build", "types:build": "tsc --build",
@@ -62,7 +63,7 @@
"@typescript-eslint/parser": "^4.13.0", "@typescript-eslint/parser": "^4.13.0",
"@web/test-runner": "^0.12.2", "@web/test-runner": "^0.12.2",
"@web/test-runner-commands": "^0.4.0", "@web/test-runner-commands": "^0.4.0",
"@web/test-runner-playwright": "^0.8.0", "@web/test-runner-playwright": "^0.8.8",
"cem-plugin-readme": "^0.1.3", "cem-plugin-readme": "^0.1.3",
"chai": "^4.2.0", "chai": "^4.2.0",
"concurrently": "^5.3.0", "concurrently": "^5.3.0",
@@ -80,6 +81,7 @@
"onchange": "^7.1.0", "onchange": "^7.1.0",
"prettier": "^2.2.1", "prettier": "^2.2.1",
"prettier-plugin-package": "^1.3.0", "prettier-plugin-package": "^1.3.0",
"publish-docs": "^0.1.2",
"puppeteer": "^9.0.0", "puppeteer": "^9.0.0",
"remark-emoji": "^2.1.0", "remark-emoji": "^2.1.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",

View File

@@ -1,5 +1,44 @@
# @rocket/blog # @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 ## 0.3.1
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@rocket/blog", "name": "@rocket/blog",
"version": "0.3.1", "version": "0.4.0",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -38,6 +38,6 @@
"testing" "testing"
], ],
"dependencies": { "dependencies": {
"plugins-manager": "^0.2.4" "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; flex-wrap: wrap;
margin: calc(-1 * var(--gap)) 0 0 calc(-1 * var(--gap)); margin: calc(-1 * var(--gap)) 0 0 calc(-1 * var(--gap));
width: calc(100% + var(--gap)); width: calc(100% + var(--gap));
align-items: flex-start;
} }
.articles article { .articles article {
@@ -32,6 +34,12 @@ body[layout='layout-blog-details'] #sidebar-nav li.anchor a:hover::before {
.articles article h2 { .articles article h2 {
margin: 0; margin: 0;
border: none; border: none;
padding-top: 1rem;
}
.articles article .thumbnail {
display: block;
height: 200px;
} }
.articles article .read { .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) { @media screen and (min-width: 1024px) {
body[layout='layout-blog-details'] #sidebar { body[layout='layout-blog-details'] #sidebar {
display: block; display: block;
} }
} }

View File

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

View File

@@ -1,25 +0,0 @@
<rocket-navigation>
<ul>
<li class="current">
<h3>Headings</h3>
{{ collections[section] | rocketPageAnchors({ title: title }) | rocketNavToHtml({
listItemClass: "menu-item",
activeListItemClass: "current",
activeKey: eleventyNavigation.key
}) | safe }}
</li>
</ul>
<div class="sidebar-tags">
<h3>Date</h3>
<div>{{ page.date.toDateString() }}</div>
</div>
<div class="sidebar-tags">
<h3>Tags</h3>
<div class="tags">
{% for tag in tags %}
<span class="tag">{{tag}}</span>
{% endfor %}
</div>
</div>
{% include 'partials/mobile-sidebar-bottom.njk' %}
</rocket-navigation>

View File

@@ -1,20 +1 @@
<div class="articles"> <web-menu name="article-overview"></web-menu>
{% for post in posts %}
{% if post.data.published %}
<article>
{% if post.data.cover_image %}
<a href="{{ post.url | url }}">
<img src="{{ post.data.cover_image | url }}" alt="">
</a>
{% endif %}
<div class="content">
<h2>
<a href="{{ post.url | url }}">{{ post.data.title }}</a>
</h2>
<p>{{ post.data.description }}</p>
<a class="read" href="{{ post.url | url }}">...read more</a>
</div>
</article>
{% endif %}
{% endfor %}
</div>

View File

@@ -1 +1,9 @@
<link rel="stylesheet" href="{{ '/_assets/rocket-blog.css' | asset | url }}"> <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

@@ -1,52 +1,52 @@
import path from 'path'; import path from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import { addPlugin } from 'plugins-manager'; // import { addPlugin } from 'plugins-manager';
const __dirname = path.dirname(fileURLToPath(import.meta.url)); const __dirname = path.dirname(fileURLToPath(import.meta.url));
const SECTION = 'blog'; // const SECTION = 'blog';
const POST_COLLECTION = 'posts'; // const POST_COLLECTION = 'posts';
export function rocketBlog({ section = SECTION, postCollection = POST_COLLECTION } = {}) { export function rocketBlog() {
const isHiddenCollection = item => ['-', '_'].includes(item.charAt(0)); // const isHiddenCollection = item => ['-', '_'].includes(item.charAt(0));
const isVisibleCollection = item => !isHiddenCollection(item); // const isVisibleCollection = item => !isHiddenCollection(item);
const isNotPostCollection = collection => collection !== postCollection; // const isNotPostCollection = collection => collection !== postCollection;
const eleventyPluginRocketBlog = { // const eleventyPluginRocketBlog = {
configFunction: eleventyConfig => { // configFunction: eleventyConfig => {
eleventyConfig.addCollection('posts', collection => { // eleventyConfig.addCollection('posts', collection => {
/* // /*
// It's not working beacuse it's a paginated collection. // // It's not working beacuse it's a paginated collection.
const headerDocs = eleventyConfig.collections.header(collection); // const headerDocs = eleventyConfig.collections.header(collection);
headerDocs.filter(page => page.data.section === section).forEach(page => { // headerDocs.filter(page => page.data.section === section).forEach(page => {
page.data.layout = 'blog'; // page.data.layout = 'blog';
}); // });
*/ // */
if (section === postCollection) { // if (section === postCollection) {
throw new Error("Rocket blog: section and postCollection couldn't be equal"); // throw new Error("Rocket blog: section and postCollection couldn't be equal");
} // }
if (!eleventyConfig.collections[section]) { // if (!eleventyConfig.collections[section]) {
const collectionKeys = Object.keys(eleventyConfig.collections); // const collectionKeys = Object.keys(eleventyConfig.collections);
const availableCollections = collectionKeys // const availableCollections = collectionKeys
.filter(isVisibleCollection) // .filter(isVisibleCollection)
.filter(isNotPostCollection); // .filter(isNotPostCollection);
throw new Error( // throw new Error(
`Rocket blog: Collection '${section}' not found. Aviable colections: ${availableCollections.join( // `Rocket blog: Collection '${section}' not found. Aviable colections: ${availableCollections.join(
', ', // ', ',
)}`, // )}`,
); // );
} // }
const posts = eleventyConfig.collections[section](collection); // const posts = eleventyConfig.collections[section](collection);
posts.forEach(page => { // posts.forEach(page => {
page.data.layout = 'layout-blog-details'; // page.data.layout = 'layout-blog-details';
}); // });
return posts; // return posts;
}); // });
}, // },
}; // };
return { return {
path: path.resolve(__dirname), path: path.resolve(__dirname),
setupEleventyPlugins: [addPlugin({ name: 'rocket-blog', plugin: eleventyPluginRocketBlog })], // setupEleventyPlugins: [addPlugin({ name: 'rocket-blog', plugin: eleventyPluginRocketBlog })],
}; };
} }

View File

@@ -1,5 +1,22 @@
# @rocket/building-rollup # @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 ## 0.3.1
### Patch Changes ### Patch Changes

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,62 @@
# @rocket/cli # @rocket/cli
## 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 ## 0.9.9
### Patch Changes ### Patch Changes

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
{ {
"name": "@rocket/cli", "name": "@rocket/cli",
"version": "0.9.9", "version": "0.10.0",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -57,10 +57,9 @@
"dependencies": { "dependencies": {
"@11ty/eleventy": "^0.11.1", "@11ty/eleventy": "^0.11.1",
"@11ty/eleventy-img": "^0.9.0", "@11ty/eleventy-img": "^0.9.0",
"@rocket/building-rollup": "^0.3.1", "@rocket/building-rollup": "^0.4.0",
"@rocket/core": "^0.1.2", "@rocket/core": "^0.1.2",
"@rocket/eleventy-plugin-mdjs-unified": "^0.5.2", "@rocket/eleventy-plugin-mdjs-unified": "^0.6.0",
"@rocket/eleventy-rocket-nav": "^0.3.0",
"@rollup/plugin-babel": "^5.2.2", "@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-node-resolve": "^11.0.1", "@rollup/plugin-node-resolve": "^11.0.1",
"@web/config-loader": "^0.1.3", "@web/config-loader": "^0.1.3",
@@ -71,8 +70,9 @@
"command-line-args": "^5.1.1", "command-line-args": "^5.1.1",
"command-line-usage": "^6.1.1", "command-line-usage": "^6.1.1",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"gray-matter": "^4.0.3",
"micromatch": "^4.0.2", "micromatch": "^4.0.2",
"plugins-manager": "^0.2.4", "plugins-manager": "^0.3.0",
"slash": "^3.0.0", "slash": "^3.0.0",
"utf8": "^3.0.0", "utf8": "^3.0.0",
"workbox-window": "^6.1.5" "workbox-window": "^6.1.5"

View File

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

View File

@@ -1,4 +1,4 @@
<a class="logo-link" href="{{ '/' | url }}"> <a class="logo-link" href="{{ '/' | url }}">
<img src="{{ '/_assets/logo.svg' | asset | url }}" alt="{{ site.logoAlt }}" /> <img src="{{ '/_assets/logo.svg' | asset | url }}" alt="{{ site.logoAlt }}" />
<span class="sr-only">{{ site.name }}</span> <span>{{ site.name }}</span>
</a> </a>

View File

@@ -1,6 +1,8 @@
<html theme="light" platform="web" lang="en"> <html theme="light" platform="web" lang="en">
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="menu:exclude" content="true">
<meta charset="utf-8">
<style type="text/css"> <style type="text/css">
body { body {
margin: 0; margin: 0;

View File

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

View File

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

View File

@@ -1,11 +1,61 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/ban-ts-comment */
import { startDevServer } from '@web/dev-server'; import { startDevServer } from '@web/dev-server';
import { fromRollup } from '@web/dev-server-rollup'; 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('../types/main').RocketCliOptions} RocketCliOptions */
/** @typedef {import('@web/dev-server').DevServerConfig} DevServerConfig */ /** @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 { export class RocketStart {
static pluginName = 'RocketStart'; static pluginName = 'RocketStart';
commands = ['start']; commands = ['start'];

187
packages/cli/src/RocketUpgrade.js Executable file
View File

@@ -0,0 +1,187 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { readdir, rename, writeFile } from 'fs/promises';
import path from 'path';
import { upgrade202109menu } from './upgrades/upgrade202109menu.js';
import { copy } from 'fs-extra';
/** @typedef {import('../types/main').RocketCliOptions} RocketCliOptions */
/** @typedef {import('../types/upgrade').UpgradeFile} UpgradeFile */
/** @typedef {import('../types/upgrade').FolderRename} FolderRename */
/** @typedef {import('../types/upgrade').upgrade} upgrade */
/**
* @param {UpgradeFile} options
* @returns {boolean}
*/
function filterMerged({ relPath }) {
return relPath.startsWith('_merged');
}
/**
*
* @param {object} options
* @param {string} options.rootDir
* @param {string} options.currentDir
* @param {(options: UpgradeFile) => Boolean} [options.filter]
* @returns
*/
async function getAllFiles(options) {
const { rootDir, currentDir, filter = filterMerged } = options;
const entries = await readdir(currentDir, { withFileTypes: true });
/** @type {UpgradeFile[]} */
let files = [];
for (const entry of entries) {
const { name: folderName } = entry;
const currentPath = path.join(currentDir, folderName);
if (entry.isFile()) {
const relPath = path.relative(rootDir, currentPath);
/** @type {UpgradeFile} */
const data = {
path: currentPath,
relPath,
name: path.basename(relPath),
extName: path.extname(relPath),
};
if (!filter(data)) {
files.push(data);
}
}
}
for (const entry of entries) {
const { name: folderName } = entry;
const currentPath = path.join(currentDir, folderName);
if (entry.isDirectory()) {
files = [...files, ...(await getAllFiles({ ...options, currentDir: currentPath }))];
}
}
return files;
}
/**
*
* @param {upgrade} options
*/
async function updateFileSystem({ files, folderRenames }) {
// rename files while not touching folders
for (const file of files) {
if (file.updatedName) {
const newPath = path.join(path.dirname(file.path), file.updatedName);
await rename(file.path, newPath);
}
}
// rename folders
for (const renameObj of folderRenames) {
if (renameObj.fromAbsolute && renameObj.toAbsolute) {
await rename(renameObj.fromAbsolute, renameObj.toAbsolute);
}
}
// update file content
for (const file of files) {
if (file.updatedContent) {
await writeFile(file.updatedPath || file.path, file.updatedContent);
}
}
}
/**
* @param {string} relPath
* @param {FolderRename[]} folderRenames
* @returns {string}
*/
function applyFolderRenames(relPath, folderRenames) {
let newRelPath = relPath;
for (const renameObj of folderRenames) {
if (newRelPath.startsWith(renameObj.from)) {
newRelPath = renameObj.to + newRelPath.slice(renameObj.from.length);
}
}
return newRelPath;
}
export class RocketUpgrade {
static pluginName = 'RocketUpgrade';
commands = ['upgrade'];
/**
* @param {object} options
* @param {RocketCliOptions} options.config
* @param {any} options.argv
*/
async setup({ config, argv }) {
this.__argv = argv;
this.config = config;
}
async upgradeCommand() {
if (!this?.config?._inputDirCwdRelative) {
return;
}
const backupPath = path.join(this.config._inputDirCwdRelative, '..', 'docs_backup');
await copy(this.config._inputDirCwdRelative, backupPath);
console.log(`A backup of your docs folder has been created at ${backupPath}.`);
let files = await getAllFiles({
rootDir: this.config._inputDirCwdRelative,
currentDir: this.config._inputDirCwdRelative,
});
/** @type {FolderRename[]} */
let folderRenames = [];
const upgrade = await upgrade202109menu({ files, folderRenames });
files = upgrade.files;
folderRenames = upgrade.folderRenames;
const orderedFolderRenames = [...folderRenames].sort((a, b) => {
return b.from.split('/').length - a.from.split('/').length;
});
// adjust relPath if there is a new filename
let i = 0;
for (const fileData of files) {
if (fileData.updatedName) {
files[i].updatedRelPath = `${path.dirname(fileData.relPath)}/${fileData.updatedName}`;
}
i += 1;
}
// adjust relPath to consider renamed folders
i = 0;
for (const fileData of files) {
const modifiedPath = applyFolderRenames(
fileData.updatedRelPath || fileData.relPath,
orderedFolderRenames,
);
if (modifiedPath !== fileData.relPath) {
files[i].updatedRelPath = modifiedPath;
}
i += 1;
}
// add an updatedPath if needed
i = 0;
for (const file of files) {
if (file.updatedRelPath) {
files[i].updatedPath = path.join(this.config._inputDirCwdRelative, file.updatedRelPath);
}
i += 1;
}
// create absolute paths for renames
i = 0;
for (const renameObj of folderRenames) {
folderRenames[i].fromAbsolute = path.join(this.config._inputDirCwdRelative, renameObj.from);
folderRenames[i].toAbsolute = path.join(this.config._inputDirCwdRelative, renameObj.to);
i += 1;
}
await updateFileSystem({
files,
folderRenames: orderedFolderRenames,
});
}
}

View File

@@ -21,7 +21,7 @@ parser.prepareWasm(saxWasmBuffer);
* @param {string} link * @param {string} link
*/ */
function isRelativeLink(link) { function isRelativeLink(link) {
if (link.startsWith('http') || link.startsWith('/')) { if (link.startsWith('http') || link.startsWith('/') || link.includes(':')) {
return false; return false;
} }
return true; return true;

View File

@@ -14,8 +14,11 @@ import { readConfig } from '@web/config-loader';
import { RocketStart } from './RocketStart.js'; import { RocketStart } from './RocketStart.js';
import { RocketBuild } from './RocketBuild.js'; import { RocketBuild } from './RocketBuild.js';
import { RocketUpgrade } from './RocketUpgrade.js';
import { RocketLint } from './RocketLint.js'; import { RocketLint } from './RocketLint.js';
import { webMenu } from '@web/menu';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url)); const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -42,7 +45,7 @@ function ignore({ src }) {
*/ */
export async function normalizeConfig(inConfig) { export async function normalizeConfig(inConfig) {
let config = { let config = {
presets: [], presets: [webMenu()],
setupUnifiedPlugins: [], setupUnifiedPlugins: [],
setupDevAndBuildPlugins: [], setupDevAndBuildPlugins: [],
setupDevPlugins: [], setupDevPlugins: [],
@@ -50,6 +53,7 @@ export async function normalizeConfig(inConfig) {
setupEleventyPlugins: [], setupEleventyPlugins: [],
setupEleventyComputedConfig: [], setupEleventyComputedConfig: [],
setupCliPlugins: [], setupCliPlugins: [],
setupMenus: [],
eleventy: () => {}, eleventy: () => {},
command: 'help', command: 'help',
watch: true, watch: true,
@@ -98,7 +102,7 @@ export async function normalizeConfig(inConfig) {
try { try {
const fileConfig = await readConfig('rocket.config', userConfigFile, path.resolve(__configDir)); const fileConfig = await readConfig('rocket.config', userConfigFile, path.resolve(__configDir));
if (fileConfig) { if (fileConfig) {
config = { const updatedConfig = {
...config, ...config,
...fileConfig, ...fileConfig,
build: { build: {
@@ -111,12 +115,16 @@ export async function normalizeConfig(inConfig) {
}, },
imagePresets: config.imagePresets, imagePresets: config.imagePresets,
}; };
if (fileConfig.presets) {
updatedConfig.presets = [...config.presets, ...fileConfig.presets];
}
if (fileConfig.imagePresets && fileConfig.imagePresets.responsive) { if (fileConfig.imagePresets && fileConfig.imagePresets.responsive) {
config.imagePresets.responsive = { updatedConfig.imagePresets.responsive = {
...config.imagePresets.responsive, ...config.imagePresets.responsive,
...fileConfig.imagePresets.responsive, ...fileConfig.imagePresets.responsive,
}; };
} }
config = updatedConfig;
} }
} catch (error) { } catch (error) {
console.error('Could not read rocket config file', error); console.error('Could not read rocket config file', error);
@@ -165,6 +173,9 @@ export async function normalizeConfig(inConfig) {
if (preset.setupCliPlugins) { if (preset.setupCliPlugins) {
config.setupCliPlugins = [...config.setupCliPlugins, ...preset.setupCliPlugins]; config.setupCliPlugins = [...config.setupCliPlugins, ...preset.setupCliPlugins];
} }
if (preset.setupMenus) {
config.setupMenus = [...config.setupMenus, ...preset.setupMenus];
}
if (typeof preset.before11ty === 'function') { if (typeof preset.before11ty === 'function') {
config.__before11tyFunctions.push(preset.before11ty); config.__before11tyFunctions.push(preset.before11ty);
@@ -174,11 +185,7 @@ export async function normalizeConfig(inConfig) {
config._presetPaths.push(path.resolve(_inputDirCwdRelative)); config._presetPaths.push(path.resolve(_inputDirCwdRelative));
/** @type {MetaPlugin[]} */ /** @type {MetaPlugin[]} */
let pluginsMeta = [ let pluginsMeta = [{ plugin: RocketStart }, { plugin: RocketBuild }, { plugin: RocketLint }, { plugin: RocketUpgrade}];
{ name: 'RocketStart', plugin: RocketStart },
{ name: 'RocketBuild', plugin: RocketBuild },
{ name: 'RocketLint', plugin: RocketLint },
];
if (Array.isArray(config.setupCliPlugins)) { if (Array.isArray(config.setupCliPlugins)) {
for (const setupFn of 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 { getComputedConfig } = require('./computedConfig.cjs');
const { executeSetupFunctions } = require('plugins-manager'); const { executeSetupFunctions } = require('plugins-manager');
function titleMetaPlugin() { class TitleMetaPlugin {
return async data => { static dataName = 'titleMeta';
async execute(data) {
if (data.titleMeta) { if (data.titleMeta) {
return data.titleMeta; return data.titleMeta;
} }
@@ -17,29 +19,24 @@ function titleMetaPlugin() {
return titleMetaFromContent; return titleMetaFromContent;
} }
return {}; return {};
}; }
} }
function titlePlugin() { class TitlePlugin {
return async data => { static dataName = 'title';
async execute(data) {
if (data.title) { if (data.title) {
return data.title; return data.title;
} }
return data.titleMeta?.title; return data.titleMeta?.title;
}; }
} }
function eleventyNavigationPlugin() { class SectionPlugin {
return async data => { static dataName = 'section';
if (data.eleventyNavigation) {
return data.eleventyNavigation;
}
return data.titleMeta?.eleventyNavigation;
};
}
function sectionPlugin() { async execute(data) {
return async data => {
if (data.section) { if (data.section) {
return data.section; return data.section;
} }
@@ -52,11 +49,17 @@ function sectionPlugin() {
return parts[1]; return parts[1];
} }
} }
}; }
} }
function layoutPlugin({ defaultLayout = 'layout-default' } = {}) { class LayoutPlugin {
return async data => { static dataName = 'layout';
constructor({ defaultLayout = 'layout-default' } = {}) {
this.defaultLayout = defaultLayout;
}
async execute(data) {
if (data.layout) { if (data.layout) {
return data.layout; return data.layout;
} }
@@ -66,22 +69,29 @@ function layoutPlugin({ defaultLayout = 'layout-default' } = {}) {
return 'layout-index'; return 'layout-index';
} }
} }
return defaultLayout; return this.defaultLayout;
}; }
} }
function socialMediaImagePlugin(args = {}) { class SocialMediaImagePlugin {
const { createSocialImage = defaultCreateSocialImage, rocketConfig = {} } = args; static dataName = 'socialMediaImage';
const cleanedUpArgs = { ...args }; constructor(args = {}) {
delete cleanedUpArgs.createSocialImage; 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) { if (data.socialMediaImage) {
return data.socialMediaImage; return data.socialMediaImage;
} }
if (rocketConfig.createSocialMediaImages === false) { if (this.rocketConfig.createSocialMediaImages === false) {
return; return;
} }
@@ -95,15 +105,15 @@ function socialMediaImagePlugin(args = {}) {
const section = data.section ? ' ' + data.section[0].toUpperCase() + data.section.slice(1) : ''; const section = data.section ? ' ' + data.section[0].toUpperCase() + data.section.slice(1) : '';
const footer = `${data.site.name}${section}`; const footer = `${data.site.name}${section}`;
const imgUrl = await createSocialImage({ const imgUrl = await this.createSocialImage({
title, title,
subTitle, subTitle,
footer, footer,
section, section,
...cleanedUpArgs, ...this.cleanedUpArgs,
}); });
return imgUrl; return imgUrl;
}; }
} }
function sortByOrder(a, b) { function sortByOrder(a, b) {
@@ -146,26 +156,64 @@ async function dirToTree(sourcePath, extra = '') {
return sortedTree; return sortedTree;
} }
function joiningBlocksPlugin(rocketConfig) { class JoiningBlocksPlugin {
const { _inputDirCwdRelative } = rocketConfig; static dataName = '_joiningBlocks';
const partialsSource = path.resolve(_inputDirCwdRelative, '_merged_includes');
return async () => { constructor(rocketConfig) {
const joiningBlocks = await dirToTree(partialsSource, '_joiningBlocks'); const { _inputDirCwdRelative } = rocketConfig;
this.partialsSource = path.resolve(_inputDirCwdRelative, '_merged_includes');
}
async execute() {
const joiningBlocks = await dirToTree(this.partialsSource, '_joiningBlocks');
return joiningBlocks; return joiningBlocks;
}; }
}
/**
* Removes the `xx--` prefix that is used for ordering
*
* @returns {string}
*/
class PermalinkPlugin {
static dataName = 'permalink';
execute(data) {
if (data.permalink) {
return data.permalink;
}
let filePath = data.page.filePathStem.replace(/[0-9]+--/g, '');
return filePath.endsWith('index') ? `${filePath}.html` : `${filePath}/index.html`;
}
}
/**
* @returns {Number}
*/
class MenuOrderPlugin {
static dataName = 'menu.order';
execute(data) {
const matches = data.page.fileSlug.match(/([0-9]+)--/);
if (matches) {
return parseInt(matches[1]);
}
return 0;
}
} }
function generateEleventyComputed() { function generateEleventyComputed() {
const rocketConfig = getComputedConfig(); const rocketConfig = getComputedConfig();
let metaPlugins = [ let metaPlugins = [
{ name: 'titleMeta', plugin: titleMetaPlugin }, { plugin: TitleMetaPlugin, options: {} }, // TODO: remove after search & social media are standalone
{ name: 'title', plugin: titlePlugin }, { plugin: TitlePlugin, options: {} }, // TODO: remove after search & social media are standalone
{ name: 'eleventyNavigation', plugin: eleventyNavigationPlugin }, { plugin: SectionPlugin, options: {} }, // TODO: remove this
{ name: 'section', plugin: sectionPlugin }, { plugin: SocialMediaImagePlugin, options: { rocketConfig } }, // TODO: convert to standalone tool that can work with html
{ name: 'socialMediaImage', plugin: socialMediaImagePlugin, options: { rocketConfig } }, { plugin: JoiningBlocksPlugin, options: rocketConfig },
{ name: '_joiningBlocks', plugin: joiningBlocksPlugin, options: rocketConfig }, { plugin: LayoutPlugin, options: {} },
{ name: 'layout', plugin: layoutPlugin }, { plugin: PermalinkPlugin, options: {} },
{ plugin: MenuOrderPlugin, options: {} },
]; ];
const finalMetaPlugins = executeSetupFunctions( const finalMetaPlugins = executeSetupFunctions(
@@ -176,13 +224,23 @@ function generateEleventyComputed() {
const eleventyComputed = {}; const eleventyComputed = {};
for (const pluginObj of finalMetaPlugins) { for (const pluginObj of finalMetaPlugins) {
if (pluginObj.options) { 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 { } else {
eleventyComputed[pluginObj.name] = pluginObj.plugin(); const inst = new pluginObj.plugin();
eleventyComputed[inst.constructor.dataName] = inst.execute.bind(inst);
} }
} }
return eleventyComputed; return eleventyComputed;
} }
module.exports = { generateEleventyComputed }; module.exports = {
generateEleventyComputed,
LayoutPlugin,
PermalinkPlugin,
MenuOrderPlugin,
SectionPlugin,
SocialMediaImagePlugin,
JoiningBlocksPlugin,
};

View File

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

View File

@@ -0,0 +1,169 @@
import { readFile } from 'fs/promises';
import matter from 'gray-matter';
/** @typedef {import('@rocket/cli/types/upgrade').upgrade} upgrade */
/**
*
* @param {upgrade} options
*/
export async function upgrade202109menu({ files, folderRenames }) {
let i = 0;
const updatedFolderRenames = [...folderRenames];
for (const fileData of files) {
if (fileData.extName === '.md') {
const content = (await readFile(fileData.path)).toString();
const lines = content.split('\n');
const { title, lineNumber } = extractTitle(content);
let order = 0;
if (title && lineNumber >= 0) {
const parsedTitle = parseTitle(title);
order = parsedTitle.order;
lines[lineNumber] = `# ${parsedTitle.title}`;
files[i].updatedContent = lines.join('\n');
}
if (lines[0] === '---') {
const fmObj = matter(content);
if (fmObj.data.eleventyNavigation) {
const eleventyNav = fmObj.data.eleventyNavigation;
if (eleventyNav.order) {
order = eleventyNav.order;
delete fmObj.data.eleventyNavigation.order;
}
if (eleventyNav.key) {
fmObj.data.menu = { ...fmObj.data.menu, linkText: eleventyNav.key };
delete fmObj.data.eleventyNavigation.key;
}
if (eleventyNav.parent) {
delete fmObj.data.eleventyNavigation.parent;
}
if (Object.keys(eleventyNav).length === 0) {
delete fmObj.data.eleventyNavigation;
}
}
if (!title && fmObj.data.title) {
fmObj.content = `\n# ${fmObj.data.title}\n${fmObj.content}`;
delete fmObj.data.title;
}
if (fmObj.data.eleventyExcludeFromCollections) {
fmObj.data.menu = { ...fmObj.data.menu, exclude: true };
delete fmObj.data.eleventyExcludeFromCollections;
}
if (Object.keys(fmObj.data).length > 0) {
files[i].updatedContent = matter.stringify(fmObj.content, fmObj.data);
}
}
if (order !== 0) {
if (fileData.relPath.toLowerCase().endsWith('index.md')) {
const pathParts = fileData.relPath.split('/');
const originDirParts = [...pathParts];
originDirParts.pop();
pathParts[pathParts.length - 2] = `${order}--${pathParts[pathParts.length - 2]}`;
const dirParts = [...pathParts];
dirParts.pop();
updatedFolderRenames.push({ from: originDirParts.join('/'), to: dirParts.join('/') });
} else {
files[i].updatedName = `${order}--${fileData.name}`;
}
}
}
i += 1;
}
return { files, folderRenames: updatedFolderRenames };
}
/**
* Reads a text and extracts a title from it
*
* @param {string} content The text where to extract the title from
* @param {string} engine
*/
export function extractTitle(content, engine = 'md') {
if (engine === 'md') {
let captureHeading = true;
let i = 0;
for (const line of content.split('\n')) {
if (line.startsWith('```')) {
captureHeading = !captureHeading;
}
if (captureHeading && line.startsWith('# ')) {
return { title: line.substring(2), lineNumber: i };
}
i += 1;
}
}
return { title: '', lineNumber: -1 };
}
/**
* Parses a title and extracts the relevante data for it.
* A title can contain
* - ">>" to define a parent => child relationship
* - "||" to define the order for this page
*
* @example
* Foo ||3
* Foo >> Bar ||10
*
* @param {string} inTitle
* @return {{ title: string, order: number }}
*/
export function parseTitle(inTitle) {
if (typeof inTitle !== 'string') {
throw new Error('You need to provide a string to `parseTitle`');
}
let title = inTitle;
let order = 0;
let navigationTitle = title;
if (title.includes('>>')) {
const parts = title
.split('>>')
.map(part => part.trim())
.filter(Boolean);
title = parts.join(' ');
navigationTitle = parts[parts.length - 1];
if (parts.length >= 2) {
title = `${parts[0]}: ${parts[1]}`;
const parentParts = [...parts];
parentParts.pop();
if (parts.length >= 3) {
title = `${parts[parts.length - 2]}: ${parts[parts.length - 1]}`;
}
}
}
if (title.includes('||')) {
const parts = title
.split('||')
.map(part => part.trim())
.filter(Boolean);
if (parts.length !== 2) {
throw new Error('You can use || only once in `parseTitle`');
}
navigationTitle = navigationTitle.split('||').map(part => part.trim())[0];
title = parts[0];
order = parseInt(parts[1]);
}
return {
title: navigationTitle,
order,
};
// data.parts = titleParts;
// data.title = title;
// data.eleventyNavigation = {
// key,
// title: navigationTitle,
// order,
// };
// if (parent) {
// data.eleventyNavigation.parent = parent;
// }
// return data;
}

View File

@@ -2,9 +2,10 @@ import chai from 'chai';
import { RocketCli } from '../src/RocketCli.js'; import { RocketCli } from '../src/RocketCli.js';
import path from 'path'; import path from 'path';
import globby from 'globby'; import globby from 'globby';
import fs from 'fs-extra'; import fs, { move, remove } from 'fs-extra';
import prettier from 'prettier'; import prettier from 'prettier';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import { existsSync } from 'fs';
const { expect } = chai; const { expect } = chai;
@@ -91,86 +92,109 @@ export async function readOutput(
return text; return text;
} }
export function startOutputExist(cli, fileName) {
const outputDir = cli.config.outputDevDir;
return fs.existsSync(path.join(outputDir, fileName));
}
export function buildOutputExist(cli, fileName) {
const outputDir = cli.config.outputDir;
return fs.existsSync(path.join(outputDir, fileName));
}
/**
* @param {*} cli
* @param {string} fileName
* @param {readOutputOptions} options
*/
export async function readStartOutput(cli, fileName, options = {}) {
options.type = 'start';
return readOutput(cli, fileName, options);
}
/**
* @param {*} cli
* @param {string} fileName
* @param {readOutputOptions} options
*/
export async function readBuildOutput(cli, fileName, options = {}) {
options.type = 'build';
return readOutput(cli, fileName, options);
}
export async function getfixtureExpectedFiles(pathToDir) { export async function getfixtureExpectedFiles(pathToDir) {
const cwd = path.join(fixtureDir, pathToDir); const cwd = path.join(fixtureDir, pathToDir);
const paths = await globby('**/*', { cwd, absolute: true, dot: true }); const paths = await globby('**/*', { cwd, absolute: true, dot: true });
return paths; return paths;
} }
export async function execute(cli, configFileDir) { export async function execute(pathToConfig, { type = 'start', captureLog = false } = {}) {
let log = [];
const origLog = console.log;
if (captureLog) {
console.log = (...args) => {
log = [...log, ...args];
};
}
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
const configFileDir = path.dirname(configFile);
const cli = new RocketCli({
argv: [type, '--config-file', configFile],
});
await cli.setup(); await cli.setup();
cli.config.outputDevDir = path.join(configFileDir, '__output-dev'); cli.config.outputDevDir = path.join(configFileDir, '__output-dev');
cli.config.devServer.open = false; cli.config.devServer.open = false;
cli.config.devServer.port = 8080; cli.config.devServer.port = 8080;
cli.config.watch = false; cli.config.watch = false;
cli.config.outputDir = path.join(configFileDir, '__output'); cli.config.outputDir = path.join(configFileDir, '__output');
await fs.emptyDir(cli.config.outputDevDir);
await fs.emptyDir(cli.config.outputDir);
await cli.run(); await cli.run();
return cli;
/**
* @param {*} cli
* @param {string} fileName
* @param {readOutputOptions} options
*/
async function readOutput2(fileName, options = {}) {
options.type = type;
return readOutput(cli, fileName, options);
}
function outputExists(fileName) {
const outputDir = type === 'build' ? cli.config.outputDir : cli.config.outputDevDir;
const filePath = path.join(outputDir, fileName);
return fs.existsSync(filePath);
}
if (captureLog) {
console.log = origLog;
}
return { log, readOutput: readOutput2, cli, outputExists };
} }
export async function executeBootstrap(pathToDir) { export async function executeBootstrap(pathToDir) {
const configFileDir = path.join(fixtureDir, pathToDir.split('/').join(path.sep)); const configFileDir = path.join(fixtureDir, pathToDir.split('/').join(path.sep));
const cli = new RocketCli({ argv: ['bootstrap'] }); const cli = new RocketCli({ argv: ['bootstrap'] });
await cli.setup();
cli.config.outputDevDir = path.join(configFileDir, '__output-dev');
cli.config.devServer.open = false;
cli.config.devServer.port = 8080;
cli.config.watch = false;
cli.config.outputDir = path.join(configFileDir, '__output');
await fs.emptyDir(configFileDir); await fs.emptyDir(configFileDir);
await execute(cli, configFileDir); await cli.run();
return cli;
return { cli };
} }
export async function executeStart(pathToConfig) { export async function executeUpgrade(pathToConfig) {
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep)); const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
const cli = new RocketCli({ const cli = new RocketCli({
argv: ['start', '--config-file', configFile], argv: ['upgrade', '--config-file', configFile],
}); });
await execute(cli, path.dirname(configFile)); await cli.setup();
return cli;
}
export async function executeBuild(pathToConfig) { // restore from backup if available - in cases the test did stop in the middle
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep)); if (cli.config._inputDirCwdRelative) {
const cli = new RocketCli({ const backupDir = path.join(cli.config._inputDirCwdRelative, '..', 'docs_backup');
argv: ['build', '--config-file', configFile], if (existsSync(backupDir)) {
}); await remove(cli.config._inputDirCwdRelative);
await execute(cli, path.dirname(configFile)); await move(backupDir, cli.config._inputDirCwdRelative);
return cli; }
} }
await cli.run();
export async function executeLint(pathToConfig) { return {
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep)); cli,
const cli = new RocketCli({ fileExists: fileName => {
argv: ['lint', '--config-file', configFile], const outputDir = cli.config._inputDirCwdRelative;
}); return fs.existsSync(path.join(outputDir, fileName));
await execute(cli, path.dirname(configFile)); },
return cli; readFile: async fileName => {
// TODO: use readOutput once it's changed to read full file paths
const filePath = path.join(cli.config._inputDirCwdRelative, fileName);
const text = await fs.promises.readFile(filePath);
return text.toString();
},
};
} }
export function trimWhiteSpace(inString) { export function trimWhiteSpace(inString) {

View File

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

View File

@@ -2,13 +2,9 @@ import chai from 'chai';
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import chalk from 'chalk'; import chalk from 'chalk';
import { import {
execute,
executeBootstrap, executeBootstrap,
executeBuild,
executeLint,
executeStart,
expectThrowsAsync, expectThrowsAsync,
readBuildOutput,
readStartOutput,
getfixtureExpectedFiles, getfixtureExpectedFiles,
setFixtureDir, setFixtureDir,
} from '@rocket/cli/test-helpers'; } from '@rocket/cli/test-helpers';
@@ -17,7 +13,7 @@ import fs from 'fs-extra';
const { expect } = chai; const { expect } = chai;
describe('RocketCli e2e', () => { describe('RocketCli e2e', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -26,20 +22,24 @@ describe('RocketCli e2e', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
it('can add a unified plugin via the config', async () => { it('can add a unified plugin via the config', async () => {
cli = await executeStart('e2e-fixtures/unified-plugin/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/unified-plugin/rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'index.html'); captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal(`<p>See a 🐶</p>`); expect(indexHtml).to.equal(`<p>See a 🐶</p>`);
}); });
describe('bootstrap command', () => { describe('bootstrap command', () => {
it('can bootstrap a project', async () => { it('can bootstrap a project', async () => {
cli = await executeBootstrap('e2e-fixtures/bootstrap/__output'); const { cli } = await executeBootstrap('e2e-fixtures/bootstrap/__output');
cleanupCli = cli;
for (const p of await getfixtureExpectedFiles('e2e-fixtures/bootstrap/expected')) { for (const p of await getfixtureExpectedFiles('e2e-fixtures/bootstrap/expected')) {
const actual = await fs.readFile( const actual = await fs.readFile(
@@ -54,8 +54,11 @@ describe('RocketCli e2e', () => {
describe('eleventy in config', () => { describe('eleventy in config', () => {
it('can modify eleventy via an elventy function in the config', async () => { it('can modify eleventy via an elventy function in the config', async () => {
cli = await executeStart('e2e-fixtures/content/eleventy.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/content/eleventy.rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'index.html'); captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal( expect(indexHtml).to.equal(
['# BEFORE #', '<p>Content inside <code>docs/index.md</code></p>'].join('\n'), ['# BEFORE #', '<p>Content inside <code>docs/index.md</code></p>'].join('\n'),
); );
@@ -63,7 +66,8 @@ describe('RocketCli e2e', () => {
it('will throw if you try to set options by returning an object', async () => { it('will throw if you try to set options by returning an object', async () => {
await expectThrowsAsync( await expectThrowsAsync(
() => executeStart('e2e-fixtures/content/eleventy-return.rocket.config.js'), () =>
execute('e2e-fixtures/content/eleventy-return.rocket.config.js', { captureLog: true }),
{ {
errorMatch: /Error in your Eleventy config file.*/, errorMatch: /Error in your Eleventy config file.*/,
}, },
@@ -73,13 +77,23 @@ describe('RocketCli e2e', () => {
describe('setupDevAndBuildPlugins in config', () => { describe('setupDevAndBuildPlugins in config', () => {
it('can add a rollup plugin via setupDevAndBuildPlugins for build command', async () => { it('can add a rollup plugin via setupDevAndBuildPlugins for build command', async () => {
cli = await executeBuild('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js'); const { cli, readOutput } = await execute(
const inlineModule = await readBuildOutput(cli, 'e97af63d.js'); 'e2e-fixtures/rollup-plugin/devbuild.rocket.config.js',
{
captureLog: true,
type: 'build',
},
);
cleanupCli = cli;
const inlineModule = await readOutput('e97af63d.js');
expect(inlineModule).to.equal('var a={test:"data"};console.log(a);'); expect(inlineModule).to.equal('var a={test:"data"};console.log(a);');
}); });
it('can add a rollup plugin via setupDevAndBuildPlugins for start command', async () => { it('can add a rollup plugin via setupDevAndBuildPlugins for start command', async () => {
cli = await executeStart('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js'); const { cli } = await execute('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const response = await fetch('http://localhost:8080/test-data.json'); const response = await fetch('http://localhost:8080/test-data.json');
expect(response.ok).to.be.true; // no server error expect(response.ok).to.be.true; // no server error
@@ -90,37 +104,56 @@ describe('RocketCli e2e', () => {
}); });
it('can add a rollup plugin for dev & build and modify a build only plugin via the config', async () => { it('can add a rollup plugin for dev & build and modify a build only plugin via the config', async () => {
cli = await executeBuild('e2e-fixtures/rollup-plugin/devbuild-build.rocket.config.js'); const { cli, readOutput } = await execute(
const inlineModule = await readBuildOutput(cli, 'e97af63d.js'); 'e2e-fixtures/rollup-plugin/devbuild-build.rocket.config.js',
{
captureLog: true,
type: 'build',
},
);
cleanupCli = cli;
const inlineModule = await readOutput('e97af63d.js');
expect(inlineModule).to.equal('var a={test:"data"};console.log(a);'); expect(inlineModule).to.equal('var a={test:"data"};console.log(a);');
}); });
it('can adjust the inputDir', async () => { it('can adjust the inputDir', async () => {
cli = await executeStart('e2e-fixtures/change-input-dir/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/change-input-dir/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal('<p>Markdown in <code>docs/page/index.md</code></p>'); expect(indexHtml).to.equal('<p>Markdown in <code>docs/page/index.md</code></p>');
}); });
it('can access main rocket config values via {{rocketConfig.value}}', async () => { it('can access main rocket config values via {{rocketConfig.value}}', async () => {
cli = await executeStart('e2e-fixtures/rocket-config-in-template/rocket.config.js'); const { cli, readOutput } = await execute(
'e2e-fixtures/rocket-config-in-template/rocket.config.js',
{
captureLog: true,
},
);
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.equal( expect(indexHtml).to.equal(
'<p>You can show Rocket config data like rocketConfig.absoluteBaseUrl = <a href="http://test-domain.com/">http://test-domain.com/</a></p>', '<p>You can show Rocket config data like rocketConfig.absoluteBaseUrl = <a href="http://test-domain.com/">http://test-domain.com/</a></p>',
); );
}); });
it('can add a pathPrefix that will not influence the start command', async () => { it('can add a pathPrefix that will not influence the start command', async () => {
cli = await executeStart('e2e-fixtures/content/pathPrefix.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/content/pathPrefix.rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const linkHtml = await readStartOutput(cli, 'link/index.html'); const linkHtml = await readOutput('link/index.html');
expect(linkHtml).to.equal( expect(linkHtml).to.equal(
['<p><a href="../">home</a></p>', '<p><a href="/">absolute home</a></p>'].join('\n'), ['<p><a href="../">home</a></p>', '<p><a href="/">absolute home</a></p>'].join('\n'),
); );
const assetHtml = await readStartOutput(cli, 'use-assets/index.html'); const assetHtml = await readOutput('use-assets/index.html');
expect(assetHtml).to.equal('<link rel="stylesheet" href="/_merged_assets/some.css">'); expect(assetHtml).to.equal('<link rel="stylesheet" href="/_merged_assets/some.css">');
const imageHtml = await readStartOutput(cli, 'image/index.html', { replaceImageHashes: true }); const imageHtml = await readOutput('image/index.html', { replaceImageHashes: true });
expect(imageHtml).to.equal( expect(imageHtml).to.equal(
[ [
'<p>', '<p>',
@@ -147,9 +180,13 @@ describe('RocketCli e2e', () => {
}); });
it('can add a pathPrefix that will be used in the build command', async () => { it('can add a pathPrefix that will be used in the build command', async () => {
cli = await executeBuild('e2e-fixtures/content/pathPrefix.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/content/pathPrefix.rocket.config.js', {
captureLog: true,
type: 'build',
});
cleanupCli = cli;
const linkHtml = await readBuildOutput(cli, 'link/index.html', { const linkHtml = await readOutput('link/index.html', {
stripToBody: true, stripToBody: true,
}); });
expect(linkHtml).to.equal( expect(linkHtml).to.equal(
@@ -157,11 +194,11 @@ describe('RocketCli e2e', () => {
'\n', '\n',
), ),
); );
const assetHtml = await readBuildOutput(cli, 'use-assets/index.html'); const assetHtml = await readOutput('use-assets/index.html');
expect(assetHtml).to.equal( expect(assetHtml).to.equal(
'<html><head><link rel="stylesheet" href="../41297ffa.css">\n\n</head><body>\n\n</body></html>', '<html><head><link rel="stylesheet" href="../41297ffa.css">\n\n</head><body>\n\n</body></html>',
); );
let imageHtml = await readBuildOutput(cli, 'image/index.html'); let imageHtml = await readOutput('image/index.html');
imageHtml = imageHtml.replace(/\.\.\/([a-z0-9]+)\./g, '../__HASH__.'); imageHtml = imageHtml.replace(/\.\.\/([a-z0-9]+)\./g, '../__HASH__.');
expect(imageHtml).to.equal( expect(imageHtml).to.equal(
[ [
@@ -184,8 +221,63 @@ describe('RocketCli e2e', () => {
}); });
it('smoke test for link checking', async () => { it('smoke test for link checking', async () => {
await expectThrowsAsync(() => executeLint('e2e-fixtures/lint-links/rocket.config.js'), { await expectThrowsAsync(
errorMatch: /Found 1 missing reference targets/, () => execute('e2e-fixtures/lint-links/rocket.config.js', { captureLog: true, type: 'lint' }),
{
errorMatch: /Found 1 missing reference targets/,
},
);
});
it('can completely take over the rollup config', async () => {
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 chai from 'chai';
import chalk from 'chalk'; import chalk from 'chalk';
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers'; import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai; const { expect } = chai;
describe('RocketCli images', () => { describe('RocketCli images', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -14,15 +14,18 @@ describe('RocketCli images', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
describe('Images', () => { describe('Images', () => {
it('does render content images responsive', async () => { it('does render content images responsive', async () => {
cli = await executeStart('e2e-fixtures/images/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/images/rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'index.html', { captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -57,7 +60,7 @@ describe('RocketCli images', () => {
].join('\n'), ].join('\n'),
); );
const keepSvgHtml = await readStartOutput(cli, 'ignores/index.html', { const keepSvgHtml = await readOutput('ignores/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -102,7 +105,7 @@ describe('RocketCli images', () => {
].join('\n'), ].join('\n'),
); );
const tableHtml = await readStartOutput(cli, 'table/index.html', { const tableHtml = await readOutput('table/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -150,8 +153,12 @@ describe('RocketCli images', () => {
}); });
it('can configure more patterns to ignore', async () => { it('can configure more patterns to ignore', async () => {
cli = await executeStart('e2e-fixtures/images/ignore-more.rocket.config.js'); const { cli, readOutput } = await execute(
const keepSvgHtml = await readStartOutput(cli, 'ignores/index.html', { 'e2e-fixtures/images/ignore-more.rocket.config.js',
{ captureLog: true },
);
cleanupCli = cli;
const keepSvgHtml = await readOutput('ignores/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -178,16 +185,17 @@ describe('RocketCli images', () => {
}); });
it('renders multiple images in the correct order', async () => { it('renders multiple images in the correct order', async () => {
cli = await executeStart('e2e-fixtures/images/rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/images/rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'two-images/index.html', { captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('two-images/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
expect(indexHtml).to.equal( expect(indexHtml).to.equal(
[ [
'<h2 id="one">', '<p>one</p>',
' <a aria-hidden="true" tabindex="-1" href="#one"><span class="icon icon-link"></span></a>one',
'</h2>',
'<p>', '<p>',
' <picture>', ' <picture>',
' <source', ' <source',
@@ -211,9 +219,7 @@ describe('RocketCli images', () => {
' />', ' />',
' </picture>', ' </picture>',
'</p>', '</p>',
'<h2 id="two">', '<p>two</p>',
' <a aria-hidden="true" tabindex="-1" href="#two"><span class="icon icon-link"></span></a>two',
'</h2>',
'<p>', '<p>',
' <picture>', ' <picture>',
' <source', ' <source',
@@ -242,8 +248,11 @@ describe('RocketCli images', () => {
}); });
it('can configure those responsive images', async () => { it('can configure those responsive images', async () => {
cli = await executeStart('e2e-fixtures/images/small.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/images/small.rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'index.html', { captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -280,8 +289,11 @@ describe('RocketCli images', () => {
}); });
it('will only render a figure & figcaption if there is a caption/title', async () => { it('will only render a figure & figcaption if there is a caption/title', async () => {
cli = await executeStart('e2e-fixtures/images/small.rocket.config.js'); const { cli, readOutput } = await execute('e2e-fixtures/images/small.rocket.config.js', {
const indexHtml = await readStartOutput(cli, 'no-title/index.html', { captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('no-title/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });
@@ -315,8 +327,12 @@ describe('RocketCli images', () => {
}); });
it('will render an img with srcset and sizes if there is only one image format', async () => { it('will render an img with srcset and sizes if there is only one image format', async () => {
cli = await executeStart('e2e-fixtures/images/single-format.rocket.config.js'); const {
const indexHtml = await readStartOutput(cli, 'no-title/index.html', { cli,
readOutput,
} = await execute('e2e-fixtures/images/single-format.rocket.config.js', { captureLog: true });
cleanupCli = cli;
const indexHtml = await readOutput('no-title/index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });

View File

@@ -0,0 +1,77 @@
import chai from 'chai';
import chalk from 'chalk';
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
describe('RocketCli Menu', () => {
let cleanupCli;
before(() => {
// ignore colors in tests as most CIs won't support it
chalk.level = 0;
setFixtureDir(import.meta.url);
});
afterEach(async () => {
if (cleanupCli?.cleanup) {
await cleanupCli.cleanup();
}
});
it('will render a menu', async () => {
const { cli, readOutput } = await execute('e2e-fixtures/menu/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readOutput('index.html', {
formatHtml: true,
});
expect(indexHtml).to.equal(
[
'<html>',
' <head> </head>',
' <body>',
' <web-menu name="site">',
' <nav aria-label="site">',
' <a href="/components/">Components</a>',
' <a href="/getting-started/">Getting Started</a>',
' <a href="/blog/">Blog</a>',
' </nav>',
' </web-menu>',
' <h1 id="menu-page">',
' <a aria-hidden="true" tabindex="-1" href="#menu-page"><span class="icon icon-link"></span></a',
' >Menu Page',
' </h1>',
' </body>',
'</html>',
].join('\n'),
);
const accordion = await readOutput('components/content/accordion/index.html', {
formatHtml: true,
});
expect(accordion).to.equal(
[
'<html>',
' <head>',
' <meta name="menu:order" content="10" />',
' </head>',
' <body>',
' <web-menu name="site">',
' <nav aria-label="site">',
' <a href="/components/">Components</a>',
' <a href="/getting-started/">Getting Started</a>',
' <a href="/blog/">Blog</a>',
' </nav>',
' </web-menu>',
' <h1 id="accordion">',
' <a aria-hidden="true" tabindex="-1" href="#accordion"><span class="icon icon-link"></span></a',
' >Accordion',
' </h1>',
' </body>',
'</html>',
].join('\n'),
);
});
});

View File

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

View File

@@ -1,11 +1,11 @@
import chai from 'chai'; import chai from 'chai';
import chalk from 'chalk'; import chalk from 'chalk';
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers'; import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai; const { expect } = chai;
describe('RocketCli preset', () => { describe('RocketCli preset', () => {
let cli; let cleanupCli;
before(() => { before(() => {
// ignore colors in tests as most CIs won't support it // ignore colors in tests as most CIs won't support it
@@ -14,21 +14,24 @@ describe('RocketCli preset', () => {
}); });
afterEach(async () => { afterEach(async () => {
if (cli?.cleanup) { if (cleanupCli?.cleanup) {
await cli.cleanup(); await cleanupCli.cleanup();
} }
}); });
it('offers a default layout (with head, header, content, footer, bottom) and raw layout', async () => { it('offers a default layout (with head, header, content, footer, bottom) and raw layout', async () => {
cli = await executeStart('preset-fixtures/default/rocket.config.js'); const { cli, readOutput } = await execute('preset-fixtures/default/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const rawHtml = await readStartOutput(cli, 'raw/index.html'); const rawHtml = await readOutput('raw/index.html');
expect(rawHtml).to.equal('<p>Just raw</p>'); expect(rawHtml).to.equal('<p>Just raw</p>');
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.include('<body layout="layout-index">'); expect(indexHtml).to.include('<body layout="layout-index">');
const pageHtml = await readStartOutput(cli, 'page/index.html', { const pageHtml = await readOutput('page/index.html', {
stripScripts: true, stripScripts: true,
formatHtml: true, formatHtml: true,
}); });
@@ -69,7 +72,7 @@ describe('RocketCli preset', () => {
' <div class="content-area">', ' <div class="content-area">',
' <a class="logo-link" href="/">', ' <a class="logo-link" href="/">',
' <img src="/_merged_assets/logo.svg" alt="" />', ' <img src="/_merged_assets/logo.svg" alt="" />',
' <span class="sr-only">Rocket</span>', ' <span>Rocket</span>',
' </a>', ' </a>',
' </div>', ' </div>',
' </header>', ' </header>',
@@ -86,12 +89,6 @@ describe('RocketCli preset', () => {
' </div>', ' </div>',
'', '',
' <footer id="main-footer"></footer>', ' <footer id="main-footer"></footer>',
'',
' <script',
' type="module"',
' inject-service-worker=""',
' src="/_merged_assets/scripts/registerServiceWorker.js"',
' ></script>',
' </body>', ' </body>',
'</html>', '</html>',
].join('\n'), ].join('\n'),
@@ -99,16 +96,22 @@ describe('RocketCli preset', () => {
}); });
it('allows to add content to the head without overriding', async () => { it('allows to add content to the head without overriding', async () => {
cli = await executeStart('preset-fixtures/add-to-head/rocket.config.js'); const { cli, readOutput } = await execute('preset-fixtures/add-to-head/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readOutput('index.html');
expect(indexHtml).to.include('<meta name="added" content="at the top" />'); expect(indexHtml).to.include('<meta name="added" content="at the top" />');
}); });
it('a preset can provide an adjustImagePresets() function', async () => { it('a preset can provide an adjustImagePresets() function', async () => {
cli = await executeStart('preset-fixtures/use-preset/rocket.config.js'); const { cli, readOutput } = await execute('preset-fixtures/use-preset/rocket.config.js', {
captureLog: true,
});
cleanupCli = cli;
const indexHtml = await readStartOutput(cli, 'index.html', { const indexHtml = await readOutput('index.html', {
formatHtml: true, formatHtml: true,
replaceImageHashes: true, replaceImageHashes: true,
}); });

View File

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

View File

@@ -0,0 +1,57 @@
import chai from 'chai';
import chalk from 'chalk';
import path from 'path';
import { executeUpgrade, setFixtureDir } from '@rocket/cli/test-helpers';
import { move, remove } from 'fs-extra';
import { existsSync } from 'fs';
const { expect } = chai;
describe('Upgrade System', () => {
let cli;
before(() => {
// ignore colors in tests as most CIs won't support it
chalk.level = 0;
setFixtureDir(import.meta.url);
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
}
if (cli?.config._inputDirCwdRelative) {
const backupDir = path.join(cli.config._inputDirCwdRelative, '..', 'docs_backup');
if (existsSync(backupDir)) {
await remove(cli.config._inputDirCwdRelative);
await move(backupDir, cli.config._inputDirCwdRelative);
}
}
});
it('2021-09-menu', async () => {
const run = await executeUpgrade('fixtures-upgrade/2021-09-menu/rocket.config.js');
cli = run.cli;
expect(run.fileExists('index.md')).to.be.true;
expect(run.fileExists('31--components/index.md')).to.be.true;
expect(await run.readFile('31--components/index.md')).to.equal(
[
'---',
'menu:',
' linkText: Components',
'---',
'',
'# Component Directory',
'',
'Here you get started.',
'',
].join('\n'),
);
expect(run.fileExists('31--components/10--content/20--accordion/overview.md')).to.be.false;
expect(run.fileExists('31--components/10--content/20--accordion/10--overview.md')).to.be.true;
expect(await run.readFile('31--components/10--content/20--accordion/10--overview.md')).to.equal(
'# Overview\n',
);
});
});

View File

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

View File

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

View File

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

View File

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

@@ -2,10 +2,10 @@
layout: layout-raw layout: layout-raw
--- ---
## one one
![one](./_assets/my-image.jpg) ![one](./_assets/my-image.jpg)
## two two
![two](./_assets/my-image.jpg) ![two](./_assets/my-image.jpg)

View File

@@ -0,0 +1 @@
# Components

View File

@@ -0,0 +1 @@
# Getting Started

View File

@@ -0,0 +1 @@
# Blog

View File

@@ -0,0 +1,11 @@
<html>
<head>
{% if menu.order %}
<meta name="menu:order" content="{{ menu.order }}" />
{% endif %}
</head>
<body>
<web-menu name="site"></web-menu>
{{ content | safe }}
</body>
</html>

View File

@@ -0,0 +1 @@
# Menu Page

View File

@@ -0,0 +1 @@
export default {};

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

View File

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

View File

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

View File

@@ -0,0 +1,11 @@
<html>
<head>
{% if menuOrder %}
<meta name="menu:order" content="{{ menuOrder }}"/>
{% endif %}
</head>
<body>
<web-menu name="site"></web-menu>
{{ content | safe }}
</body>
</html>

View File

@@ -0,0 +1 @@
# Components >> Content >> Accordion >> Api || 20

View File

@@ -0,0 +1 @@
# Components >> Content >> Accordion || 20

View File

@@ -0,0 +1 @@
# Components >> Content >> Accordion >> Overview || 10

View File

@@ -0,0 +1 @@
# Components >> Content || 10

View File

@@ -0,0 +1 @@
# Components >> Content >> Tabs || 10

View File

@@ -0,0 +1,8 @@
---
title: Component Directory
eleventyNavigation:
key: Components
order: 31
---
Here you get started.

View File

@@ -0,0 +1,3 @@
---
title: Rocket
---

View File

@@ -0,0 +1,3 @@
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {};
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

@@ -14,19 +14,32 @@ function cleanup(config) {
delete configNoPaths.eleventy; delete configNoPaths.eleventy;
delete configNoPaths.outputDevDir; delete configNoPaths.outputDevDir;
delete configNoPaths.imagePresets.responsive.ignore; delete configNoPaths.imagePresets.responsive.ignore;
delete configNoPaths.presets;
delete configNoPaths.setupCliPlugins;
return configNoPaths; return configNoPaths;
} }
const plugins = [
{ commands: ['start'] },
{ commands: ['build'] },
{ commands: ['start', 'build', 'lint'] }, // lint
{ commands: ['upgrade'] },
{ commands: ['start', 'build', 'lint'] }, // web-menu
];
describe('normalizeConfig', () => { describe('normalizeConfig', () => {
it('makes sure essential settings are there', async () => { it('makes sure essential settings are there', async () => {
const configFile = path.join(__dirname, 'fixtures', 'empty', 'rocket.config.js'); const configFile = path.join(__dirname, 'fixtures', 'empty', 'rocket.config.js');
const config = await normalizeConfig({ configFile }); const config = await normalizeConfig({ configFile });
// testing pathes is always a little more complicted 😅 // testing pathes is always a little more complicated 😅
expect(config._inputDirCwdRelative).to.match(/empty\/docs$/); expect(config._inputDirCwdRelative).to.match(/empty\/docs$/);
expect(config._presetPaths[0]).to.match(/cli\/preset$/); expect(config._presetPaths[0]).to.match(/cli\/preset$/);
expect(config._presetPaths[1]).to.match(/empty\/docs$/); expect(config._presetPaths[1]).to.match(/web-menu\/preset$/);
expect(config._presetPaths[2]).to.match(/empty\/docs$/);
expect(config.outputDevDir).to.match(/_site-dev$/); expect(config.outputDevDir).to.match(/_site-dev$/);
expect(config.presets.length).to.equal(1);
expect(config.setupCliPlugins.length).to.equal(1);
expect(cleanup(config)).to.deep.equal({ expect(cleanup(config)).to.deep.equal({
__before11tyFunctions: [], __before11tyFunctions: [],
@@ -41,14 +54,9 @@ describe('normalizeConfig', () => {
setupDevPlugins: [], setupDevPlugins: [],
setupEleventyPlugins: [], setupEleventyPlugins: [],
setupEleventyComputedConfig: [], setupEleventyComputedConfig: [],
setupCliPlugins: [], setupMenus: [],
presets: [],
serviceWorkerName: 'service-worker.js', serviceWorkerName: 'service-worker.js',
plugins: [ plugins,
{ commands: ['start'] },
{ commands: ['build'] },
{ commands: ['start', 'build', 'lint'] },
],
imagePresets: { imagePresets: {
responsive: { responsive: {
formats: ['avif', 'jpeg'], formats: ['avif', 'jpeg'],
@@ -84,9 +92,8 @@ describe('normalizeConfig', () => {
setupDevAndBuildPlugins: [], setupDevAndBuildPlugins: [],
setupDevPlugins: [], setupDevPlugins: [],
setupEleventyPlugins: [], setupEleventyPlugins: [],
setupCliPlugins: [],
setupEleventyComputedConfig: [], setupEleventyComputedConfig: [],
presets: [], setupMenus: [],
imagePresets: { imagePresets: {
responsive: { responsive: {
formats: ['avif', 'jpeg'], formats: ['avif', 'jpeg'],
@@ -95,11 +102,7 @@ describe('normalizeConfig', () => {
}, },
}, },
serviceWorkerName: 'service-worker.js', serviceWorkerName: 'service-worker.js',
plugins: [ plugins,
{ commands: ['start'] },
{ commands: ['build'] },
{ commands: ['start', 'build', 'lint'] },
],
inputDir: 'docs', inputDir: 'docs',
outputDir: '_site', outputDir: '_site',
}); });
@@ -125,9 +128,8 @@ describe('normalizeConfig', () => {
setupDevAndBuildPlugins: [], setupDevAndBuildPlugins: [],
setupDevPlugins: [], setupDevPlugins: [],
setupEleventyPlugins: [], setupEleventyPlugins: [],
setupCliPlugins: [],
setupEleventyComputedConfig: [], setupEleventyComputedConfig: [],
presets: [], setupMenus: [],
imagePresets: { imagePresets: {
responsive: { responsive: {
formats: ['avif', 'jpeg'], formats: ['avif', 'jpeg'],
@@ -136,11 +138,7 @@ describe('normalizeConfig', () => {
}, },
}, },
serviceWorkerName: 'service-worker.js', serviceWorkerName: 'service-worker.js',
plugins: [ plugins,
{ commands: ['start'] },
{ commands: ['build'] },
{ commands: ['start', 'build', 'lint'] },
],
inputDir: 'docs', inputDir: 'docs',
outputDir: '_site', outputDir: '_site',
}); });
@@ -169,9 +167,8 @@ describe('normalizeConfig', () => {
setupDevAndBuildPlugins: [], setupDevAndBuildPlugins: [],
setupDevPlugins: [], setupDevPlugins: [],
setupEleventyPlugins: [], setupEleventyPlugins: [],
setupCliPlugins: [],
setupEleventyComputedConfig: [], setupEleventyComputedConfig: [],
presets: [], setupMenus: [],
imagePresets: { imagePresets: {
responsive: { responsive: {
formats: ['avif', 'jpeg'], formats: ['avif', 'jpeg'],
@@ -180,11 +177,7 @@ describe('normalizeConfig', () => {
}, },
}, },
serviceWorkerName: 'service-worker.js', serviceWorkerName: 'service-worker.js',
plugins: [ plugins,
{ commands: ['start'] },
{ commands: ['build'] },
{ commands: ['start', 'build', 'lint'] },
],
inputDir: 'docs', inputDir: 'docs',
outputDir: '_site', outputDir: '_site',
}); });

View File

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

22
packages/cli/types/upgrade.d.ts vendored Normal file
View File

@@ -0,0 +1,22 @@
export interface UpgradeFile {
path: string;
relPath: string;
name: string;
extName: string;
updatedContent?: string;
updatedPath?: string;
updatedRelPath?: string;
updatedName?: string;
}
export interface FolderRename {
from: string;
to: string;
fromAbsolute?: string;
toAbsolute?: string;
}
export interface upgrade {
files: UpgradeFile[];
folderRenames: FolderRename[];
}

View File

@@ -1,5 +1,16 @@
# @rocket/eleventy-plugin-mdjs-unified # @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 ## 0.5.2
### Patch Changes ### Patch Changes

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,28 @@
# @rocket/launch # @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 ## 0.5.5
### Patch Changes ### Patch Changes

View File

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

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