mirror of
https://github.com/modernweb-dev/rocket.git
synced 2026-03-21 15:54:57 +00:00
Compare commits
1 Commits
@rocket/bu
...
feature/ge
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b16c5b6f3 |
@@ -43,7 +43,7 @@
|
||||
|
||||
## The Goal for Rocket
|
||||
|
||||
> Our goal is to provide developers with a meta framework for static websites with a sprinkle of JavaScript.
|
||||
> Our goal is to provide developers with a meta framework for static websites with a spricle of JavaScript.
|
||||
|
||||
Get a site up and running in no time and focus on the content.
|
||||
You can still tweak every detail of every underlying tool that gets used.
|
||||
@@ -54,7 +54,7 @@ Rocket is part of the [Modern Web Family](https://twitter.com/modern_web_dev).
|
||||
|
||||
We are always looking for contributors of all skill levels! If you're looking to ease your way into the project, try out a [good first issue](https://github.com/modernweb-dev/rocket/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22).
|
||||
|
||||
If you are interested in helping contribute to Modern Web, please take a look at our [Contributing Guide](https://github.com/modernweb-dev/rocket/blob/main/CONTRIBUTING.md). Also, feel free to drop into [slack](https://rocket.modern-web.dev/about/slack/) and say hi. 👋
|
||||
If you are interested in helping contribute to Modern Web, please take a look at our [Contributing Guide](https://github.com/modernweb-dev/rocket/blob/main/CONTRIBUTING.md). Also, feel free to drop into [slack](https://rocket.modern-web.dev/discover/slack/) and say hi. 👋
|
||||
|
||||
### Financial Contributors
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
html {
|
||||
--demo-background-color: #eee;
|
||||
--demo-color: #222;
|
||||
}
|
||||
|
||||
html[theme="dark"] body {
|
||||
background: #333;
|
||||
--demo-background-color: #888;
|
||||
--demo-color: #eee;
|
||||
}
|
||||
@@ -7,5 +7,3 @@
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<meta name="twitter:creator" content="@modern_web_dev" />
|
||||
|
||||
<link rel="stylesheet" href="{{ '/_assets/body.css' | asset | url }}" mdjs-use>
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
# Configuration >> Service Worker ||30
|
||||
|
||||
Rocket does come with a default service worker that will
|
||||
|
||||
- cache already visited pages
|
||||
- cache assets of visited pages (up to 100 files then it replaces older entries)
|
||||
- reload the page if a newer html page version is available on service worker activation
|
||||
|
||||
## Adjusting the file name
|
||||
|
||||
Changing the service worker file name can be quite a hassle so you can adjust generate file name via a config.
|
||||
|
||||
👉 `rocket.config.js`
|
||||
|
||||
```js
|
||||
export default {
|
||||
serviceWorkerName: 'my-service-worker-name.js',
|
||||
};
|
||||
```
|
||||
|
||||
## Meet the Service Worker
|
||||
|
||||
The default service worker will work for many scenarios however your needs my vary.
|
||||
To enable different service worker strategies you can replace the default service worker code by providing a file at `_assets/service-worker.js`.
|
||||
This file will be auto transformed and generated in the root of the website using the defined `serviceWorkerName`.
|
||||
|
||||
For inspiration, you can take a look at the default config.
|
||||
|
||||
[https://github.com/modernweb-dev/rocket/blob/main/packages/cli/preset/\_assets/service-worker.js](https://github.com/modernweb-dev/rocket/blob/main/packages/cli/preset/_assets/service-worker.js)
|
||||
|
||||
Be sure to check out [workbox](https://developers.google.com/web/tools/workbox) for more service worker magic.
|
||||
|
||||
And if you wanna have a 30 minutes crash course we highly recommend the talk [Service Workers For The Rest Of Us](https://vimeo.com/362260166) by [Philip Walton](https://twitter.com/philwalton).
|
||||
|
||||
## Registration
|
||||
|
||||
The registration happens via another file that you can also overwrite at `_assets/scripts/registerServiceWorker.js`.
|
||||
|
||||
Below you find the default implementation.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
{{ '/_assets/scripts/registerServiceWorker.js' | asset | toAbsPath | inlineFilePath; }}
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -1,69 +0,0 @@
|
||||
class DemoElement extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
|
||||
this.platform = 'the web';
|
||||
this.language = 'en-US';
|
||||
this.theme = 'light';
|
||||
|
||||
this.observer = new MutationObserver(this.updateData);
|
||||
}
|
||||
|
||||
updateData = () => {
|
||||
this.platform = document.documentElement.getAttribute('platform') || 'the web';
|
||||
this.language = document.documentElement.getAttribute('data-lang') || 'en-US';
|
||||
this.theme = document.documentElement.getAttribute('theme') || 'light';
|
||||
this.requestUpdate();
|
||||
};
|
||||
|
||||
connectedCallback() {
|
||||
this.updateData();
|
||||
|
||||
this.observer.observe(document.documentElement, { attributes: true });
|
||||
}
|
||||
|
||||
requestUpdate() {
|
||||
this.shadowRoot.innerHTML = this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
return `
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
background: var(--demo-background-color);
|
||||
color: var(--demo-color);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
:host[platform~="web"] {
|
||||
border-bottom: 2px solid #333;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 640px) {
|
||||
.about {
|
||||
display: flex;
|
||||
}
|
||||
.about ul {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Hello I am DemoElement 👋</p>
|
||||
<div class="about">
|
||||
<ul>
|
||||
<li>My purpose is to demonstrate how an element can adopt to different environments</li>
|
||||
<li>I like <strong>${this.platform}</strong></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>My mother languages is <strong>${this.language}</strong></li>
|
||||
<li>I feel very comfortable in the <strong>${this.theme}</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('demo-element', DemoElement);
|
||||
@@ -56,8 +56,8 @@ mdjs comes with some additional helpers you can choose to import:
|
||||
|
||||
````md
|
||||
```js script
|
||||
import '@mdjs/mdjs-story/define';
|
||||
import '@mdjs/mdjs-preview/define';
|
||||
import '@mdjs/mdjs-story/mdjs-story.js';
|
||||
import '@mdjs/mdjs-preview/mdjs-preview.js';
|
||||
```
|
||||
````
|
||||
|
||||
@@ -65,8 +65,8 @@ Once loaded you can use them like so:
|
||||
|
||||
````md
|
||||
```js script
|
||||
import '@mdjs/mdjs-story/define';
|
||||
import '@mdjs/mdjs-preview/define';
|
||||
import '@mdjs/mdjs-story/mdjs-story.js';
|
||||
import '@mdjs/mdjs-preview/mdjs-preview.js';
|
||||
```
|
||||
````
|
||||
|
||||
@@ -118,8 +118,8 @@ export const JsPreviewStory = () => html` <demo-wc-card>JS Preview Story</demo-w
|
||||
Here is a live example from [demo-wc-card](https://www.npmjs.com/package/demo-wc-card).
|
||||
|
||||
```js script
|
||||
import '@mdjs/mdjs-story/define';
|
||||
import '@mdjs/mdjs-preview/define';
|
||||
import '@mdjs/mdjs-story/mdjs-story.js';
|
||||
import '@mdjs/mdjs-preview/mdjs-preview.js';
|
||||
import { html } from 'lit-html';
|
||||
```
|
||||
|
||||
@@ -132,6 +132,31 @@ export const header = () => {
|
||||
|
||||
## Supported Systems
|
||||
|
||||
### es-dev-server
|
||||
|
||||
Preview your mdjs readme with live demos and auto reload.
|
||||
|
||||
- Add to your `package.json`:
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"start": "es-dev-server",
|
||||
}
|
||||
```
|
||||
|
||||
- Create a `es-dev-server.config.js` in the root of your repository.
|
||||
|
||||
```js
|
||||
const { mdjsTransformer } = require('@mdjs/core');
|
||||
|
||||
module.exports = {
|
||||
nodeResolve: true,
|
||||
open: 'README.md',
|
||||
watch: true,
|
||||
responseTransformers: [mdjsTransformer],
|
||||
};
|
||||
```
|
||||
|
||||
### Storybook
|
||||
|
||||
Please check out [@open-wc/demoing-storybook](https://open-wc.org/demoing/) for a fully integrated setup.
|
||||
|
||||
@@ -2,165 +2,18 @@
|
||||
|
||||
You can showcase live running code by annotating a code block with `js preview-story`.
|
||||
|
||||
## Features
|
||||
|
||||
- Shows components inside the page as they are
|
||||
- You can enable “Simulation Mode” to break them out
|
||||
- Simulation mode renders in an iframe to supporting media queries and isolated Simulation settings
|
||||
- Simulation Settings
|
||||
- Style (windows, mac, android, iOS)
|
||||
- Size (small, medium, large, Galaxy S5, iPhone X, iPad …)
|
||||
- Automatic Height
|
||||
- Theme (light, dark)
|
||||
- Language (en, nl, …)
|
||||
- Settings are ”global” for all Simulators (e.g. changing one will change all)
|
||||
- Settings can be remembered for other pages / return visits
|
||||
|
||||
```js script
|
||||
import { html } from 'lit-html';
|
||||
import './assets/demo-element.js';
|
||||
```
|
||||
|
||||
## JavaScript Story
|
||||
|
||||
````md
|
||||
```js script
|
||||
import { html } from 'lit-html';
|
||||
import './assets/demo-element.js';
|
||||
```
|
||||
|
||||
```js preview-story
|
||||
export const foo = () => html`<demo-element></demo-element>`;
|
||||
import { html } from 'lit-html';
|
||||
|
||||
export const foo = () => html` <p>my html</p> `;
|
||||
```
|
||||
````
|
||||
|
||||
will result in
|
||||
|
||||
```js preview-story
|
||||
export const foo = () => html` <demo-element></demo-element> `;
|
||||
```
|
||||
|
||||
## HTML Story
|
||||
|
||||
````md
|
||||
```html preview-story
|
||||
<demo-element></demo-element>
|
||||
```
|
||||
````
|
||||
|
||||
will result in
|
||||
|
||||
```html preview-story
|
||||
<demo-element></demo-element>
|
||||
```
|
||||
|
||||
## Setup Simulation Mode
|
||||
|
||||
For simulation mode we need a dedicated html file that will be used as an iframe target while loading stories.
|
||||
|
||||
The fastest way to create such a file is to use the `layout-simulator` layout.
|
||||
|
||||
Create a file `docs/simulator.md` with the following content.
|
||||
|
||||
```md
|
||||
---
|
||||
layout: layout-simulator
|
||||
eleventyExcludeFromCollections: true
|
||||
excludeFromSearch: true
|
||||
---
|
||||
```
|
||||
|
||||
Once you have that you need to configure it for the story renderer by setting it in your `rocket.config.js`.
|
||||
|
||||
```js
|
||||
export default {
|
||||
setupUnifiedPlugins: [
|
||||
adjustPluginOptions('mdjsSetupCode', {
|
||||
simulationSettings: { simulatorUrl: '/simulator/' },
|
||||
}),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
<inline-notification type="tip">
|
||||
|
||||
You can freely choose the path for the "simulator" by creating the md file in a different folder and adjusting the path in the config.
|
||||
|
||||
</inline-notification>
|
||||
|
||||
## Simulator states
|
||||
|
||||
To simulate these stats that usually come from the device itself we put those infos on the document tag.
|
||||
|
||||
We can simulate the following settings
|
||||
|
||||
1. `platform`
|
||||
Adopting styles and behavior depending on which device platform you are.
|
||||
```html
|
||||
<html platform="web"></html>
|
||||
<html platform="android"></html>
|
||||
<html platform="ios"></html>
|
||||
<!-- potentially later -->
|
||||
<html platform="web-windows"></html>
|
||||
<html platform="web-mac"></html>
|
||||
```
|
||||
2. `theme`
|
||||
Adjust your styles based on a theme - light/dark are the default but you can add as many as you want.
|
||||
```html
|
||||
<html theme="light"></html>
|
||||
<html theme="dark"></html>
|
||||
```
|
||||
3. `language`
|
||||
Best to relay on `data-lang` as `lang` often gets changes by translations services which may interfere with your translation loading system.
|
||||
```html
|
||||
<html lang="en-US" data-lang="en-US"></html>
|
||||
<html lang="de-DE" data-lang="de-DE"></html>
|
||||
```
|
||||
|
||||
If you want to react to such document changes you can use an [MutationObserver](https://developer.mozilla.org/de/docs/Web/API/MutationObserver).
|
||||
|
||||
For a vanilla web component it could look something like this:
|
||||
|
||||
```js
|
||||
class DemoElement extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
|
||||
this.platform = 'the web';
|
||||
this.language = 'en-US';
|
||||
this.theme = 'light';
|
||||
|
||||
this.observer = new MutationObserver(this.updateData);
|
||||
}
|
||||
|
||||
updateData = () => {
|
||||
this.platform = document.documentElement.getAttribute('platform') || 'the web';
|
||||
this.language = document.documentElement.getAttribute('data-lang') || 'en-US';
|
||||
this.theme = document.documentElement.getAttribute('theme') || 'light';
|
||||
this.requestUpdate();
|
||||
};
|
||||
|
||||
connectedCallback() {
|
||||
this.updateData();
|
||||
|
||||
this.observer.observe(document.documentElement, { attributes: true });
|
||||
}
|
||||
|
||||
requestUpdate() {
|
||||
this.shadowRoot.innerHTML = this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
return `
|
||||
...
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('demo-element', DemoElement);
|
||||
```
|
||||
|
||||
```js script
|
||||
import '@rocket/launch/inline-notification/inline-notification.js';
|
||||
import { html } from 'lit-html';
|
||||
|
||||
export const foo = () => html` <p>my html</p> `;
|
||||
```
|
||||
|
||||
@@ -2,16 +2,10 @@
|
||||
|
||||
You can showcase live running code by annotating a code block with `js story`.
|
||||
|
||||
```js script
|
||||
import { html } from 'lit-html';
|
||||
```
|
||||
|
||||
````md
|
||||
```js script
|
||||
import { html } from 'lit-html';
|
||||
```
|
||||
|
||||
```js story
|
||||
import { html } from 'lit-html';
|
||||
|
||||
export const foo = () => html` <p>my html</p> `;
|
||||
```
|
||||
````
|
||||
@@ -19,5 +13,7 @@ export const foo = () => html` <p>my html</p> `;
|
||||
will result in
|
||||
|
||||
```js story
|
||||
import { html } from 'lit-html';
|
||||
|
||||
export const foo = () => html` <p>my html</p> `;
|
||||
```
|
||||
|
||||
@@ -8,6 +8,7 @@ You write modern JavaScript using the latest browser features. Rollup will optim
|
||||
- Set HTML or JavaScript as input and/or output
|
||||
- Optimized for browsers which support modules
|
||||
- Loads polyfills using feature detection
|
||||
- Generates a service worker
|
||||
- Minifies JavaScript
|
||||
- Minifies lit-html templates
|
||||
|
||||
|
||||
@@ -47,9 +47,3 @@ export const headlineConverter = () => html`
|
||||
```
|
||||
|
||||
How it then works is very similar to https://www.11ty.dev/docs/plugins/navigation/
|
||||
|
||||
## Sidebar redirects
|
||||
|
||||
By default, the sidebar nav redirects clicks on category headings to the first child page in that category.
|
||||
|
||||
To disable those redirects, override `_includes/_joiningBlocks/_layoutSidebar/sidebar/20-navigation.njk` and add the `no-redirects` attribute to the `<rocket-navigation>` element.
|
||||
|
||||
@@ -5,7 +5,7 @@ For that reason Rocket creates those automatically with the title, parent title,
|
||||
|
||||
It will look like this but with your logo:
|
||||
|
||||
<img src="{{ socialMediaImage | url }}" width="1200" height="630" alt="Social Media Image of this page" style="border: 1px solid #000" />
|
||||
<img src="{{ socialMediaImage }}" width="1200" height="630" alt="Social Media Image of this page" style="border: 1px solid #000" />
|
||||
|
||||
There are multiple ways you can modify it.
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
layout: layout-simulator
|
||||
eleventyExcludeFromCollections: true
|
||||
excludeFromSearch: true
|
||||
---
|
||||
@@ -38,6 +38,6 @@
|
||||
"testing"
|
||||
],
|
||||
"dependencies": {
|
||||
"plugins-manager": "^0.2.1"
|
||||
"plugins-manager": "^0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,5 @@
|
||||
# @rocket/building-rollup
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 2724f07: Stop auto generating a service worker from a template. Setup your own and then bundle via `createServiceWorkerConfig`.
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- bad4686: Preserve attributes on script tags. Preserve export names.
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- be0d0b3: fix: add missing main entry to the packages
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -6,7 +6,3 @@
|
||||
export { createBasicConfig, createBasicMetaConfig } from './src/createBasicConfig.js';
|
||||
export { createSpaConfig, createSpaMetaConfig } from './src/createSpaConfig.js';
|
||||
export { createMpaConfig, createMpaMetaConfig } from './src/createMpaConfig.js';
|
||||
export {
|
||||
createServiceWorkerConfig,
|
||||
createServiceWorkerMetaConfig,
|
||||
} from './src/createServiceWorkerConfig.js';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/building-rollup",
|
||||
"version": "0.3.0",
|
||||
"version": "0.1.2",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -13,7 +13,6 @@
|
||||
},
|
||||
"author": "Modern Web <hello@modern-web.dev> (https://modern-web.dev/)",
|
||||
"homepage": "https://rocket.modern-web.dev/docs/tools/building-rollup/",
|
||||
"main": "./index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.js"
|
||||
@@ -55,16 +54,11 @@
|
||||
"@babel/preset-env": "^7.12.11",
|
||||
"@rollup/plugin-babel": "^5.2.2",
|
||||
"@rollup/plugin-node-resolve": "^11.0.1",
|
||||
"@rollup/plugin-replace": "^2.4.2",
|
||||
"@web/rollup-plugin-html": "^1.6.0",
|
||||
"@web/rollup-plugin-html": "^1.4.0",
|
||||
"@web/rollup-plugin-import-meta-assets": "^1.0.4",
|
||||
"@web/rollup-plugin-polyfills-loader": "^1.1.0",
|
||||
"@web/rollup-plugin-polyfills-loader": "^1.0.3",
|
||||
"browserslist": "^4.16.1",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"workbox-broadcast-update": "^6.1.5",
|
||||
"workbox-cacheable-response": "^6.1.5",
|
||||
"workbox-expiration": "^6.1.5",
|
||||
"workbox-routing": "^6.1.5",
|
||||
"workbox-strategies": "^6.1.5"
|
||||
"rollup-plugin-workbox": "^6.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ export function createBasicMetaConfig(userConfig = { output: {} }) {
|
||||
const assetName = `[${developmentMode ? 'name' : 'hash'}][extname]`;
|
||||
|
||||
const config = {
|
||||
preserveEntrySignatures: 'strict',
|
||||
preserveEntrySignatures: false,
|
||||
treeshake: !developmentMode,
|
||||
setupPlugins: [],
|
||||
...userConfig,
|
||||
|
||||
@@ -15,6 +15,10 @@ export function createMpaMetaConfig(userConfig = { output: {}, setupPlugins: []
|
||||
adjustPluginOptions('html', {
|
||||
flattenOutput: false,
|
||||
}),
|
||||
adjustPluginOptions('workbox', config => {
|
||||
delete config.navigateFallback;
|
||||
return config;
|
||||
}),
|
||||
...config.setupPlugins,
|
||||
];
|
||||
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import babelPkg from '@rollup/plugin-babel';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
|
||||
import { metaConfigToRollupConfig } from 'plugins-manager';
|
||||
|
||||
const { babel } = babelPkg;
|
||||
|
||||
export function createServiceWorkerConfig(userConfig) {
|
||||
const { config, metaPlugins } = createServiceWorkerMetaConfig(userConfig);
|
||||
return metaConfigToRollupConfig(config, metaPlugins);
|
||||
}
|
||||
|
||||
export function createServiceWorkerMetaConfig(userConfig = { output: {} }) {
|
||||
const developmentMode =
|
||||
typeof userConfig.developmentMode !== undefined
|
||||
? userConfig.developmentMode
|
||||
: !!process.env.ROLLUP_WATCH;
|
||||
delete userConfig.developmentMode;
|
||||
|
||||
const config = {
|
||||
treeshake: !developmentMode,
|
||||
setupPlugins: [],
|
||||
...userConfig,
|
||||
|
||||
output: {
|
||||
format: 'iife',
|
||||
file: 'service-worker.js',
|
||||
...userConfig.output,
|
||||
},
|
||||
};
|
||||
|
||||
let metaPlugins = [
|
||||
{
|
||||
name: 'node-resolve',
|
||||
plugin: resolve,
|
||||
options: {
|
||||
moduleDirectories: ['node_modules', 'web_modules'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'replace',
|
||||
plugin: replace,
|
||||
options: {
|
||||
'process.env.NODE_ENV': JSON.stringify(developmentMode ? 'development' : 'production'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'babel',
|
||||
plugin: babel,
|
||||
options: {
|
||||
babelHelpers: 'bundled',
|
||||
compact: true,
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: [
|
||||
'last 3 Chrome major versions',
|
||||
'last 3 ChromeAndroid major versions',
|
||||
'last 3 Firefox major versions',
|
||||
'last 3 Edge major versions',
|
||||
'last 3 Safari major versions',
|
||||
'last 3 iOS major versions',
|
||||
],
|
||||
useBuiltIns: false,
|
||||
shippedProposals: true,
|
||||
modules: false,
|
||||
bugfixes: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'terser',
|
||||
plugin: terser,
|
||||
options: {
|
||||
mangle: {
|
||||
toplevel: true,
|
||||
properties: {
|
||||
regex: /(^_|_$)/,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return { config, metaPlugins, developmentMode };
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
import path from 'path';
|
||||
import { rollupPluginHTML } from '@web/rollup-plugin-html';
|
||||
import { generateSW } from 'rollup-plugin-workbox';
|
||||
import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets';
|
||||
import { polyfillsLoader } from '@web/rollup-plugin-polyfills-loader';
|
||||
import { metaConfigToRollupConfig } from 'plugins-manager';
|
||||
@@ -35,6 +37,31 @@ export function createSpaMetaConfig(userConfig = { output: {} }) {
|
||||
options: {
|
||||
rootDir,
|
||||
absoluteBaseUrl,
|
||||
injectServiceWorker: true,
|
||||
serviceWorkerPath: path.join(config.output.dir, 'service-worker.js'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'workbox',
|
||||
plugin: generateSW,
|
||||
options: {
|
||||
// Keep 'legacy-*.js' just for retro compatibility
|
||||
globIgnores: ['polyfills/*.js', 'legacy-*.js', 'nomodule-*.js'],
|
||||
navigateFallback: '/index.html',
|
||||
// where to output the generated sw
|
||||
swDest: path.join(config.output.dir, 'service-worker.js'),
|
||||
// directory to match patterns against to be precached
|
||||
globDirectory: path.join(config.output.dir),
|
||||
// cache any html js and css by default
|
||||
globPatterns: ['**/*.{html,js,css,webmanifest}'],
|
||||
skipWaiting: true,
|
||||
clientsClaim: true,
|
||||
runtimeCaching: [
|
||||
{
|
||||
urlPattern: 'polyfills/*.js',
|
||||
handler: 'CacheFirst',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -9,13 +9,13 @@ describe('plugin count', () => {
|
||||
expect(config.plugins.length).to.equal(3);
|
||||
});
|
||||
|
||||
it('createSpaConfig has 6 plugins', () => {
|
||||
it('createSpaConfig has 7 plugins', () => {
|
||||
const config = createSpaConfig();
|
||||
expect(config.plugins.length).to.equal(6);
|
||||
expect(config.plugins.length).to.equal(7);
|
||||
});
|
||||
|
||||
it('createMpaConfig has 6 plugins', () => {
|
||||
it('createMpaConfig has 7 plugins', () => {
|
||||
const config = createMpaConfig();
|
||||
expect(config.plugins.length).to.equal(6);
|
||||
expect(config.plugins.length).to.equal(7);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,7 +26,10 @@ async function execute(configString) {
|
||||
const config = (await import(configPath)).default;
|
||||
await buildAndWrite(config);
|
||||
|
||||
return async (fileName, { stripToBody = false, stripStartEndWhitespace = true } = {}) => {
|
||||
return async (
|
||||
fileName,
|
||||
{ stripServiceWorker = false, stripToBody = false, stripStartEndWhitespace = true } = {},
|
||||
) => {
|
||||
let text = await fs.promises.readFile(
|
||||
path.join(config.output.dir, fileName.split('/').join(path.sep)),
|
||||
);
|
||||
@@ -36,6 +39,11 @@ async function execute(configString) {
|
||||
const bodyCloseTagStart = text.indexOf('</body>');
|
||||
text = text.substring(bodyOpenTagEnd, bodyCloseTagStart);
|
||||
}
|
||||
if (stripServiceWorker) {
|
||||
const scriptOpenTagEnd = text.indexOf('<script inject-service-worker');
|
||||
const scriptCloseTagStart = text.indexOf('</script>', scriptOpenTagEnd) + 9;
|
||||
text = text.substring(0, scriptOpenTagEnd) + text.substring(scriptCloseTagStart);
|
||||
}
|
||||
if (stripStartEndWhitespace) {
|
||||
text = text.trim();
|
||||
}
|
||||
@@ -49,26 +57,25 @@ describe('createMapConfig', () => {
|
||||
|
||||
const indexHtml = await readOutput('index.html', {
|
||||
stripToBody: true,
|
||||
stripServiceWorker: true,
|
||||
});
|
||||
expect(indexHtml).to.equal('<h1>Only static HTML content in index.html</h1>');
|
||||
|
||||
const subHtmlIndexHtml = await readOutput('sub-html/index.html', {
|
||||
stripToBody: true,
|
||||
stripServiceWorker: true,
|
||||
});
|
||||
expect(subHtmlIndexHtml).to.equal('<h1>Only static HTML content in sub-html/index.html</h1>');
|
||||
|
||||
const subJsIndexHtml = await readOutput('sub-js/index.html', {
|
||||
stripToBody: true,
|
||||
stripServiceWorker: true,
|
||||
});
|
||||
expect(subJsIndexHtml).to.equal(
|
||||
'<h1>Has js in sub-js/index.html</h1>\n\n\n<script type="module" src="../sub-js.js"></script>',
|
||||
);
|
||||
|
||||
const subJsAbsoluteIndexHtml = await readOutput('sub-js-absolute/index.html', {
|
||||
stripToBody: true,
|
||||
});
|
||||
expect(subJsAbsoluteIndexHtml).to.equal(
|
||||
'<h1>Has js in sub-js-absolute/index.html</h1>\n\n\n<script type="module" src="../sub-js-absolute.js"></script>',
|
||||
);
|
||||
const serviceWorkerJs = await readOutput('service-worker.js');
|
||||
expect(serviceWorkerJs).to.include('Promise'); // not empty string might be enough...
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<h1>Has js in sub-js-absolute/index.html</h1>
|
||||
<script type="module" src="/sub-js-absolute/sub-js-absolute.js"></script>
|
||||
@@ -1,17 +1,5 @@
|
||||
# check-html-links
|
||||
|
||||
## 0.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 66c2d78: fix: windows path issue
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- be0d0b3: fix: add missing main entry to the packages
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "check-html-links",
|
||||
"version": "0.2.2",
|
||||
"version": "0.2.0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -13,7 +13,6 @@
|
||||
},
|
||||
"author": "Modern Web <hello@modern-web.dev> (https://modern-web.dev/)",
|
||||
"homepage": "https://rocket.modern-web.dev/docs/tools/check-html-links/",
|
||||
"main": "./index.js",
|
||||
"bin": {
|
||||
"check-html-links": "src/cli.js"
|
||||
},
|
||||
|
||||
@@ -6,7 +6,6 @@ import { createRequire } from 'module';
|
||||
|
||||
import { listFiles } from './listFiles.js';
|
||||
import path from 'path';
|
||||
import slash from 'slash';
|
||||
|
||||
/** @typedef {import('../types/main').Link} Link */
|
||||
/** @typedef {import('../types/main').LocalFile} LocalFile */
|
||||
@@ -46,7 +45,7 @@ function extractReferences(htmlFilePath) {
|
||||
if (ev === SaxEventType.Attribute) {
|
||||
const data = /** @type {Attribute} */ (/** @type {any} */ (_data));
|
||||
const attributeName = data.name.toString();
|
||||
const value = slash(data.value.toString());
|
||||
const value = data.value.toString();
|
||||
const entry = {
|
||||
attribute: attributeName,
|
||||
value,
|
||||
|
||||
@@ -1,68 +1,5 @@
|
||||
# @rocket/cli
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 2724f07: The service worker no longer precaches all urls and assets. It now
|
||||
|
||||
- caches already visited pages
|
||||
- caches assets of visited pages (up to 100 files then it replaces older entries)
|
||||
- on service worker activation it will reload the page if a newer version is available
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [2724f07]
|
||||
- @rocket/building-rollup@0.3.0
|
||||
|
||||
## 0.6.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 2b7f1ee: Add support for pathprefix
|
||||
- Updated dependencies [2b7f1ee]
|
||||
- @rocket/eleventy-plugin-mdjs-unified@0.4.1
|
||||
|
||||
## 0.6.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ed86ff2: Do not set `data-localize-lang` in the simulator iframe html tag
|
||||
- f4a0ab5: Pass document shadowRoot to iframe
|
||||
- c675820: fix: windows path issue avoid filtering of index section of collections
|
||||
|
||||
## 0.6.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- abc8a02: You can now use an absolute path for the rootDir
|
||||
- Updated dependencies [bad4686]
|
||||
- Updated dependencies [2267e72]
|
||||
- @rocket/building-rollup@0.2.0
|
||||
- @rocket/eleventy-plugin-mdjs-unified@0.4.0
|
||||
|
||||
## 0.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 5edc40f: Make sure each rocket instance has it's own eleventy config'
|
||||
- ef8ebb0: To support dynamically created content to be part of the anchor navigation of the page we now analyze the final html output instead of `entry.templateContent`.
|
||||
|
||||
BREAKING CHANGE:
|
||||
|
||||
- only add anchors for the currently active pages (before it added anchor for every page)
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- be0d0b3: fix: add missing main entry to the packages
|
||||
- Updated dependencies [be0d0b3]
|
||||
- Updated dependencies [ef8ebb0]
|
||||
- @rocket/building-rollup@0.1.3
|
||||
- check-html-links@0.2.1
|
||||
- @rocket/core@0.1.2
|
||||
- plugins-manager@0.2.1
|
||||
- @rocket/eleventy-rocket-nav@0.3.0
|
||||
|
||||
## 0.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/cli",
|
||||
"version": "0.7.0",
|
||||
"version": "0.5.2",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -13,7 +13,6 @@
|
||||
},
|
||||
"author": "Modern Web <hello@modern-web.dev> (https://modern-web.dev/)",
|
||||
"homepage": "https://rocket.modern-web.dev/",
|
||||
"main": "./index.cjs",
|
||||
"bin": {
|
||||
"rocket": "src/cli.js"
|
||||
},
|
||||
@@ -57,25 +56,23 @@
|
||||
"dependencies": {
|
||||
"@11ty/eleventy": "^0.11.1",
|
||||
"@11ty/eleventy-img": "^0.7.4",
|
||||
"@rocket/building-rollup": "^0.3.0",
|
||||
"@rocket/core": "^0.1.2",
|
||||
"@rocket/eleventy-plugin-mdjs-unified": "^0.4.1",
|
||||
"@rocket/eleventy-rocket-nav": "^0.3.0",
|
||||
"@rocket/building-rollup": "^0.1.2",
|
||||
"@rocket/core": "^0.1.1",
|
||||
"@rocket/eleventy-plugin-mdjs-unified": "^0.3.1",
|
||||
"@rocket/eleventy-rocket-nav": "^0.2.1",
|
||||
"@rollup/plugin-babel": "^5.2.2",
|
||||
"@rollup/plugin-node-resolve": "^11.0.1",
|
||||
"@web/config-loader": "^0.1.3",
|
||||
"@web/dev-server": "^0.1.4",
|
||||
"@web/dev-server-rollup": "^0.3.2",
|
||||
"@web/rollup-plugin-copy": "^0.2.0",
|
||||
"check-html-links": "^0.2.2",
|
||||
"check-html-links": "^0.2.0",
|
||||
"command-line-args": "^5.1.1",
|
||||
"command-line-usage": "^6.1.1",
|
||||
"fs-extra": "^9.0.1",
|
||||
"micromatch": "^4.0.2",
|
||||
"plugins-manager": "^0.2.1",
|
||||
"slash": "^3.0.0",
|
||||
"utf8": "^3.0.0",
|
||||
"workbox-window": "^6.1.5"
|
||||
"plugins-manager": "^0.2.0",
|
||||
"utf8": "^3.0.0"
|
||||
},
|
||||
"types": "dist-types/index.d.ts"
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
(async () => {
|
||||
if ('serviceWorker' in navigator) {
|
||||
const { Workbox } = await import('workbox-window');
|
||||
|
||||
const url = window.__rocketServiceWorkerUrl || '/service-worker.js';
|
||||
const wb = new Workbox(url);
|
||||
wb.addEventListener('message', event => {
|
||||
if (event.data.type === 'CACHE_UPDATED') {
|
||||
const { updatedURL } = event.data.payload;
|
||||
console.log(`Reloading as a newer version of ${updatedURL} became available!`);
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
wb.register()
|
||||
.then(function () {
|
||||
console.log('ServiceWorker registered.');
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.log('ServiceWorker registration failed: ', err);
|
||||
});
|
||||
}
|
||||
})();
|
||||
@@ -1,29 +0,0 @@
|
||||
import { registerRoute } from 'workbox-routing';
|
||||
import { CacheFirst, StaleWhileRevalidate } from 'workbox-strategies';
|
||||
import { BroadcastUpdatePlugin } from 'workbox-broadcast-update';
|
||||
import { ExpirationPlugin } from 'workbox-expiration';
|
||||
|
||||
addEventListener('install', () => {
|
||||
// eslint-disable-next-line no-undef
|
||||
skipWaiting();
|
||||
});
|
||||
|
||||
// addEventListener('activate', () => {
|
||||
// console.log('activate');
|
||||
// });
|
||||
|
||||
const cacheFirst = new CacheFirst({
|
||||
cacheName: 'assets',
|
||||
plugins: [
|
||||
new ExpirationPlugin({
|
||||
maxEntries: 100,
|
||||
}),
|
||||
],
|
||||
});
|
||||
const staleWhileRevalidate = new StaleWhileRevalidate({
|
||||
cacheName: 'pages',
|
||||
plugins: [new BroadcastUpdatePlugin()],
|
||||
});
|
||||
|
||||
registerRoute(/(\/|\.html)$/, staleWhileRevalidate);
|
||||
registerRoute(/\.(css|m?js|svg|woff2|png|jpg|gif|json|xml)$/, cacheFirst);
|
||||
@@ -1,5 +0,0 @@
|
||||
<script>
|
||||
window.__rocketServiceWorkerUrl = '/{{ rocketConfig.serviceWorkerName }}';
|
||||
</script>
|
||||
|
||||
<script type="module" inject-service-worker="" src="{{ '/_assets/scripts/registerServiceWorker.js' | asset | url }}"></script>
|
||||
@@ -0,0 +1,3 @@
|
||||
<script>
|
||||
{{ '_assets/_inline-scripts/serviceWorkerUpdate.js' | asset | toAbsPath | inlineFilePath | safe }}
|
||||
</script>
|
||||
@@ -1,7 +1,7 @@
|
||||
<meta property="og:site_name" content="{{ site.name }}"/>
|
||||
<meta property="og:type" content="website"/>
|
||||
|
||||
<meta property="og:image" content="{{ socialMediaImage | url }}"/>
|
||||
<meta property="og:url" content="{{ page.url | url }}"/>
|
||||
<meta property="og:image" content="{{ socialMediaImage }}"/>
|
||||
<meta property="og:url" content="{{ page.url }}"/>
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image"/>
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<html theme="light" platform="web" lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
height: fit-content;
|
||||
}
|
||||
html[edge-distance] body {
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
<script type="module">
|
||||
import { render } from 'lit-html';
|
||||
|
||||
async function onHashChange() {
|
||||
const urlParts = new URLSearchParams(document.location.hash.substr(1));
|
||||
|
||||
if (urlParts.get('stylesheets')) {
|
||||
for (const stylesheet of urlParts.getAll('stylesheets')) {
|
||||
if (!document.querySelector(`link[rel="stylesheet"][href="${stylesheet}"]`)) {
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = stylesheet;
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (urlParts.get('theme')) {
|
||||
document.documentElement.setAttribute('theme', urlParts.get('theme'));
|
||||
}
|
||||
if (urlParts.get('platform')) {
|
||||
document.documentElement.setAttribute('platform', urlParts.get('platform'));
|
||||
}
|
||||
if (urlParts.get('language')) {
|
||||
document.documentElement.setAttribute('lang', urlParts.get('language'));
|
||||
document.documentElement.setAttribute('data-lang', urlParts.get('language'));
|
||||
}
|
||||
if (urlParts.get('story-key')) {
|
||||
document.documentElement.setAttribute('story-key', urlParts.get('story-key'));
|
||||
}
|
||||
if (urlParts.get('edge-distance') === 'true') {
|
||||
document.documentElement.setAttribute('edge-distance', '');
|
||||
} else {
|
||||
document.documentElement.removeAttribute('edge-distance');
|
||||
}
|
||||
|
||||
const mod = await import(urlParts.get('story-file'));
|
||||
render(mod[urlParts.get('story-key')]({ shadowRoot: document }), document.body);
|
||||
}
|
||||
|
||||
window.addEventListener('hashchange', onHashChange, false);
|
||||
onHashChange();
|
||||
|
||||
const observer = new ResizeObserver(() => {
|
||||
const dimensions = document.body.getBoundingClientRect();
|
||||
const data = {
|
||||
action: 'mdjs-viewer-resize',
|
||||
storyKey: document.documentElement.getAttribute('story-key'),
|
||||
width: dimensions.width,
|
||||
height: dimensions.height,
|
||||
};
|
||||
parent.postMessage(JSON.stringify(data), '*');
|
||||
});
|
||||
observer.observe(document.body);
|
||||
</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
@@ -3,10 +3,9 @@
|
||||
|
||||
import { rollup } from 'rollup';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { copy } from '@web/rollup-plugin-copy';
|
||||
|
||||
import { createMpaConfig, createServiceWorkerConfig } from '@rocket/building-rollup';
|
||||
import { createMpaConfig } from '@rocket/building-rollup';
|
||||
import { addPlugin, adjustPluginOptions } from 'plugins-manager';
|
||||
|
||||
/**
|
||||
@@ -46,7 +45,7 @@ async function productionBuild(config) {
|
||||
dir: config.outputDir,
|
||||
},
|
||||
// custom
|
||||
rootDir: path.resolve(config.outputDevDir),
|
||||
rootDir: config.outputDevDir,
|
||||
absoluteBaseUrl: config.absoluteBaseUrl,
|
||||
setupPlugins: [
|
||||
...defaultSetupPlugins,
|
||||
@@ -56,18 +55,6 @@ async function productionBuild(config) {
|
||||
});
|
||||
|
||||
await buildAndWrite(mpaConfig);
|
||||
|
||||
const serviceWorkerSourcePath = path.resolve('docs/_merged_assets/service-worker.js');
|
||||
if (fs.existsSync(serviceWorkerSourcePath)) {
|
||||
const serviceWorkerConfig = createServiceWorkerConfig({
|
||||
input: serviceWorkerSourcePath,
|
||||
output: {
|
||||
file: path.join(path.resolve(config.outputDir), config.serviceWorkerName),
|
||||
},
|
||||
});
|
||||
|
||||
await buildAndWrite(serviceWorkerConfig);
|
||||
}
|
||||
}
|
||||
|
||||
export class RocketBuild {
|
||||
|
||||
@@ -10,7 +10,6 @@ import computedConfigPkg from './public/computedConfig.cjs';
|
||||
|
||||
import path from 'path';
|
||||
import Eleventy from '@11ty/eleventy';
|
||||
import TemplateConfig from '@11ty/eleventy/src/TemplateConfig.js';
|
||||
import { fileURLToPath } from 'url';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
@@ -100,16 +99,11 @@ export class RocketCli {
|
||||
await this.mergePresets();
|
||||
|
||||
const elev = new RocketEleventy(_inputDirCwdRelative, outputDevDir, this);
|
||||
elev.isVerbose = false;
|
||||
// 11ty always wants a relative path to cwd - why?
|
||||
const rel = path.relative(process.cwd(), path.join(__dirname));
|
||||
const relCwdPathToConfig = path.join(rel, 'shared', '.eleventy.cjs');
|
||||
|
||||
const config = new TemplateConfig(null, relCwdPathToConfig);
|
||||
elev.config = config.getConfig();
|
||||
elev.resetConfig();
|
||||
elev.setConfigPathOverride(relCwdPathToConfig);
|
||||
|
||||
elev.isVerbose = false;
|
||||
await elev.init();
|
||||
|
||||
this.eleventy = elev;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const slash = require('slash');
|
||||
const { readdirSync } = require('fs');
|
||||
|
||||
function getDirectories(source) {
|
||||
@@ -24,7 +23,7 @@ const rocketCollections = {
|
||||
let docs = [
|
||||
...collection.getFilteredByGlob(`${_inputDirCwdRelative}/${section}/**/*.md`),
|
||||
];
|
||||
docs = docs.filter(page => page.inputPath !== `./${slash(indexSection)}`);
|
||||
docs = docs.filter(page => page.inputPath !== `./${indexSection}`);
|
||||
|
||||
return docs;
|
||||
});
|
||||
|
||||
@@ -40,7 +40,6 @@ export async function normalizeConfig(inConfig) {
|
||||
inputDir: 'docs',
|
||||
outputDir: '_site',
|
||||
outputDevDir: '_site-dev',
|
||||
serviceWorkerName: 'service-worker.js',
|
||||
build: {},
|
||||
devServer: {},
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ export function setFixtureDir(importMetaUrl) {
|
||||
|
||||
/**
|
||||
* @typedef {object} readOutputOptions
|
||||
* @property {boolean} stripServiceWorker
|
||||
* @property {boolean} stripToBody
|
||||
* @property {boolean} stripStartEndWhitespace
|
||||
* @property {boolean} stripScripts
|
||||
@@ -46,6 +47,7 @@ export async function readOutput(
|
||||
cli,
|
||||
fileName,
|
||||
{
|
||||
stripServiceWorker = false,
|
||||
stripToBody = false,
|
||||
stripStartEndWhitespace = true,
|
||||
stripScripts = false,
|
||||
@@ -65,6 +67,11 @@ export async function readOutput(
|
||||
const bodyCloseTagStart = text.indexOf('</body>');
|
||||
text = text.substring(bodyOpenTagEnd, bodyCloseTagStart);
|
||||
}
|
||||
if (stripServiceWorker) {
|
||||
const scriptOpenTagEnd = text.indexOf('<script inject-service-worker');
|
||||
const scriptCloseTagStart = text.indexOf('</script>', scriptOpenTagEnd) + 9;
|
||||
text = text.substring(0, scriptOpenTagEnd) + text.substring(scriptCloseTagStart);
|
||||
}
|
||||
if (stripScripts) {
|
||||
const scriptOpenTagEnd = text.indexOf('<script>');
|
||||
const scriptCloseTagStart = text.indexOf('</script>', scriptOpenTagEnd) + 9;
|
||||
|
||||
@@ -66,6 +66,7 @@ describe('RocketCli computedConfig', () => {
|
||||
|
||||
const indexHtml = await readBuildOutput(cli, 'index.html', {
|
||||
stripToBody: true,
|
||||
stripServiceWorker: true,
|
||||
});
|
||||
expect(indexHtml).to.equal('/_merged_assets/11ty-img/5893749-1200.png');
|
||||
});
|
||||
|
||||
@@ -35,7 +35,8 @@ describe('RocketCli e2e', () => {
|
||||
});
|
||||
|
||||
describe('eleventy in config', () => {
|
||||
it('can modify eleventy via an elventy function in the config', async () => {
|
||||
// TODO: find out while this has a side effect and breaks other tests
|
||||
it.skip('can modify eleventy via an elventy function in the config', async () => {
|
||||
cli = await executeStart('e2e-fixtures/content/eleventy.rocket.config.js');
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
expect(indexHtml).to.equal(
|
||||
@@ -75,6 +76,9 @@ describe('RocketCli e2e', () => {
|
||||
cli = await executeBuild('e2e-fixtures/rollup-plugin/devbuild-build.rocket.config.js');
|
||||
const inlineModule = await readBuildOutput(cli, 'e97af63d.js');
|
||||
expect(inlineModule).to.equal('var a={test:"data"};console.log(a);');
|
||||
|
||||
const swCode = await readBuildOutput(cli, 'my-service-worker.js');
|
||||
expect(swCode).to.not.be.undefined;
|
||||
});
|
||||
|
||||
it('can adjust the inputDir', async () => {
|
||||
@@ -108,6 +112,7 @@ describe('RocketCli e2e', () => {
|
||||
cli = await executeBuild('e2e-fixtures/content/pathPrefix.rocket.config.js');
|
||||
|
||||
const linkHtml = await readBuildOutput(cli, 'link/index.html', {
|
||||
stripServiceWorker: true,
|
||||
stripToBody: true,
|
||||
});
|
||||
expect(linkHtml).to.equal(
|
||||
@@ -115,7 +120,9 @@ describe('RocketCli e2e', () => {
|
||||
'\n',
|
||||
),
|
||||
);
|
||||
const assetHtml = await readBuildOutput(cli, 'use-assets/index.html');
|
||||
const assetHtml = await readBuildOutput(cli, 'use-assets/index.html', {
|
||||
stripServiceWorker: true,
|
||||
});
|
||||
expect(assetHtml).to.equal(
|
||||
'<html><head><link rel="stylesheet" href="../41297ffa.css">\n\n</head><body>\n\n</body></html>',
|
||||
);
|
||||
|
||||
@@ -86,12 +86,6 @@ describe('RocketCli preset', () => {
|
||||
' </div>',
|
||||
'',
|
||||
' <footer id="main-footer"></footer>',
|
||||
'',
|
||||
' <script',
|
||||
' type="module"',
|
||||
' inject-service-worker=""',
|
||||
' src="/_merged_assets/scripts/registerServiceWorker.js"',
|
||||
' ></script>',
|
||||
' </body>',
|
||||
'</html>',
|
||||
].join('\n'),
|
||||
|
||||
@@ -34,7 +34,12 @@ describe('RocketCli use cases', () => {
|
||||
expect(aboutHtml).to.equal(
|
||||
[
|
||||
'<p><code>about.md</code></p>',
|
||||
'<script type="module" src="/about/__mdjs-stories.js" mdjs-setup></script>',
|
||||
'<script type="module">',
|
||||
' import { myData } from "../sub/assets/myData.js";',
|
||||
' import("../sub/assets/myData.js");',
|
||||
' const name = "myData";',
|
||||
' import(`../sub/assets/${name}.js`);',
|
||||
'</script>',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
@@ -42,7 +47,12 @@ describe('RocketCli use cases', () => {
|
||||
expect(subHtml).to.equal(
|
||||
[
|
||||
'<p><code>sub/index.md</code></p>',
|
||||
'<script type="module" src="/sub/__mdjs-stories.js" mdjs-setup></script>',
|
||||
'<script type="module">',
|
||||
' import { myData } from "./assets/myData.js";',
|
||||
' import("./assets/myData.js");',
|
||||
' const name = "myData";',
|
||||
' import(`./assets/${name}.js`);',
|
||||
'</script>',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
@@ -52,7 +62,12 @@ describe('RocketCli use cases', () => {
|
||||
expect(subDetailsHtml).to.equal(
|
||||
[
|
||||
'<p><code>sub/details.md</code></p>',
|
||||
'<script type="module" src="/sub/details/__mdjs-stories.js" mdjs-setup></script>',
|
||||
'<script type="module">',
|
||||
' import { myData } from "../assets/myData.js";',
|
||||
' import("../assets/myData.js");',
|
||||
' const name = "myData";',
|
||||
' import(`../assets/${name}.js`);',
|
||||
'</script>',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
@@ -60,7 +75,12 @@ describe('RocketCli use cases', () => {
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p><code>index.md</code></p>',
|
||||
'<script type="module" src="/__mdjs-stories.js" mdjs-setup></script>',
|
||||
'<script type="module">',
|
||||
' import { myData } from "./sub/assets/myData.js";',
|
||||
' import("./sub/assets/myData.js");',
|
||||
' const name = "myData";',
|
||||
' import(`./sub/assets/${name}.js`);',
|
||||
'</script>',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
// @ts-no-check
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import json from '@rollup/plugin-json';
|
||||
import { addPlugin, adjustPluginOptions } from 'plugins-manager';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const outputDir = path.join(__dirname, '__output');
|
||||
|
||||
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
|
||||
const config = {
|
||||
setupDevAndBuildPlugins: [addPlugin({ name: 'json', plugin: json, location: 'top' })],
|
||||
setupBuildPlugins: [adjustPluginOptions('html', { absoluteBaseUrl: 'https://test-me.com' })],
|
||||
setupBuildPlugins: [
|
||||
adjustPluginOptions('workbox', { swDest: path.join(outputDir, 'my-service-worker.js') }),
|
||||
],
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
@@ -31,7 +31,12 @@ export async function expectThrowsAsync(method, { errorMatch, errorMessage } = {
|
||||
export async function readOutput(
|
||||
cli,
|
||||
fileName,
|
||||
{ stripToBody = false, stripStartEndWhitespace = true, type = 'build' } = {},
|
||||
{
|
||||
stripServiceWorker = false,
|
||||
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));
|
||||
@@ -41,6 +46,11 @@ export async function readOutput(
|
||||
const bodyCloseTagStart = text.indexOf('</body>');
|
||||
text = text.substring(bodyOpenTagEnd, bodyCloseTagStart);
|
||||
}
|
||||
if (stripServiceWorker) {
|
||||
const scriptOpenTagEnd = text.indexOf('<script inject-service-worker');
|
||||
const scriptCloseTagStart = text.indexOf('</script>', scriptOpenTagEnd) + 9;
|
||||
text = text.substring(0, scriptOpenTagEnd) + text.substring(scriptCloseTagStart);
|
||||
}
|
||||
if (stripStartEndWhitespace) {
|
||||
text = text.trim();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ describe('normalizeConfig', () => {
|
||||
setupEleventyComputedConfig: [],
|
||||
setupCliPlugins: [],
|
||||
presets: [],
|
||||
serviceWorkerName: 'service-worker.js',
|
||||
plugins: [
|
||||
{ commands: ['start'] },
|
||||
{ commands: ['build'] },
|
||||
@@ -77,7 +76,6 @@ describe('normalizeConfig', () => {
|
||||
setupCliPlugins: [],
|
||||
setupEleventyComputedConfig: [],
|
||||
presets: [],
|
||||
serviceWorkerName: 'service-worker.js',
|
||||
plugins: [
|
||||
{ commands: ['start'] },
|
||||
{ commands: ['build'] },
|
||||
@@ -110,7 +108,6 @@ describe('normalizeConfig', () => {
|
||||
setupCliPlugins: [],
|
||||
setupEleventyComputedConfig: [],
|
||||
presets: [],
|
||||
serviceWorkerName: 'service-worker.js',
|
||||
plugins: [
|
||||
{ commands: ['start'] },
|
||||
{ commands: ['build'] },
|
||||
@@ -146,7 +143,6 @@ describe('normalizeConfig', () => {
|
||||
setupCliPlugins: [],
|
||||
setupEleventyComputedConfig: [],
|
||||
presets: [],
|
||||
serviceWorkerName: 'service-worker.js',
|
||||
plugins: [
|
||||
{ commands: ['start'] },
|
||||
{ commands: ['build'] },
|
||||
|
||||
1
packages/cli/types/main.d.ts
vendored
1
packages/cli/types/main.d.ts
vendored
@@ -20,7 +20,6 @@ interface RocketStartConfig {
|
||||
export interface RocketCliOptions {
|
||||
presets: Array<RocketPreset>;
|
||||
pathPrefix?: string;
|
||||
serviceWorkerName?: string;
|
||||
inputDir: string;
|
||||
outputDir: string;
|
||||
emptyOutputDir?: boolean;
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
# @rocket/core
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- be0d0b3: fix: add missing main entry to the packages
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/core",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -13,7 +13,6 @@
|
||||
},
|
||||
"author": "Modern Web <hello@modern-web.dev> (https://modern-web.dev/)",
|
||||
"homepage": "https://rocket.modern-web.dev/",
|
||||
"main": "./dist/title.cjs",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./title": {
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
# @rocket/drawer
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0b64116: Update @lion dependencies
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/drawer",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.2",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -33,7 +33,7 @@
|
||||
"testing"
|
||||
],
|
||||
"dependencies": {
|
||||
"@lion/overlays": "^0.26.1",
|
||||
"@lion/overlays": "^0.23.2",
|
||||
"lit-element": "^2.4.0"
|
||||
},
|
||||
"types": "dist-types/index.d.ts"
|
||||
|
||||
@@ -18,7 +18,6 @@ export class RocketDrawer extends OverlayMixin(LitElement) {
|
||||
return {
|
||||
useOverlay: { type: Boolean, reflect: true },
|
||||
useOverlayMediaQuery: { type: String },
|
||||
mediaMatcher: { type: Object },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,20 +89,6 @@ export class RocketDrawer extends OverlayMixin(LitElement) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changedProperties.has('useOverlayMediaQuery')) {
|
||||
this.mediaMatcher.removeEventListener('change', this.onMatchMedia);
|
||||
|
||||
this.mediaMatcher = window.matchMedia(this.useOverlayMediaQuery);
|
||||
this.mediaMatcher.addEventListener('change', this.onMatchMedia);
|
||||
this.useOverlay = !!this.mediaMatcher.matches;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param { MediaQueryListEvent } query
|
||||
*/
|
||||
onMatchMedia(query) {
|
||||
this.useOverlay = !!query.matches;
|
||||
}
|
||||
|
||||
_setupOpenCloseListeners() {
|
||||
@@ -133,15 +118,11 @@ export class RocketDrawer extends OverlayMixin(LitElement) {
|
||||
|
||||
this.__toggle = this.__toggle.bind(this);
|
||||
|
||||
this.onMatchMedia = this.onMatchMedia.bind(this);
|
||||
this.onGestureStart = this.onGestureStart.bind(this);
|
||||
this.onGestureMove = this.onGestureMove.bind(this);
|
||||
this.onGestureEnd = this.onGestureEnd.bind(this);
|
||||
this.updateFromTouch = this.updateFromTouch.bind(this);
|
||||
|
||||
this.mediaMatcher = window.matchMedia(this.useOverlayMediaQuery);
|
||||
this.mediaMatcher.addEventListener('change', this.onMatchMedia);
|
||||
|
||||
this._startX = 0;
|
||||
this._currentX = 0;
|
||||
this._velocity = 0;
|
||||
@@ -152,7 +133,10 @@ export class RocketDrawer extends OverlayMixin(LitElement) {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.useOverlay = !!this.mediaMatcher.matches;
|
||||
this.useOverlay = !!window.matchMedia(this.useOverlayMediaQuery).matches;
|
||||
window.matchMedia(this.useOverlayMediaQuery).addListener(query => {
|
||||
this.useOverlay = !!query.matches;
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -1,26 +1,5 @@
|
||||
# @rocket/eleventy-plugin-mdjs-unified
|
||||
|
||||
## 0.4.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 2b7f1ee: Add support for pathprefix
|
||||
- Updated dependencies [2b7f1ee]
|
||||
- @mdjs/core@0.7.1
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 2267e72: Write the mdjs JavaScript code to a file and load it from there instead of an inline script
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a8e66d8]
|
||||
- Updated dependencies [fe6a929]
|
||||
- Updated dependencies [a8e66d8]
|
||||
- @mdjs/core@0.7.0
|
||||
|
||||
## 0.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/eleventy-plugin-mdjs-unified",
|
||||
"version": "0.4.1",
|
||||
"version": "0.3.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -31,7 +31,7 @@
|
||||
"mdjs"
|
||||
],
|
||||
"dependencies": {
|
||||
"@mdjs/core": "^0.7.1",
|
||||
"@mdjs/core": "^0.6.2",
|
||||
"es-module-lexer": "^0.3.26",
|
||||
"unist-util-visit": "^2.0.3"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
const path = require('path');
|
||||
const slash = require('slash');
|
||||
const fs = require('fs');
|
||||
const { mdjsProcess } = require('@mdjs/core');
|
||||
const visit = require('unist-util-visit');
|
||||
const { init, parse } = require('es-module-lexer');
|
||||
@@ -10,7 +7,7 @@ const { init, parse } = require('es-module-lexer');
|
||||
const { parseTitle } = require('@rocket/core/title');
|
||||
|
||||
/** @typedef {import('@mdjs/core').MdjsProcessPlugin} MdjsProcessPlugin */
|
||||
/** @typedef {import('../types/code').EleventyPluginMdjsUnified} EleventyPluginMdjsUnified */
|
||||
/** @typedef {import('../types/code').EleventPluginMdjsUnified} EleventPluginMdjsUnified */
|
||||
/** @typedef {import('../types/code').NodeChildren} NodeChildren */
|
||||
/** @typedef {import('../types/code').NodeElement} NodeElement */
|
||||
/** @typedef {import('unist').Node} Node */
|
||||
@@ -96,7 +93,7 @@ async function processImports(source, inputPath) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EleventyPluginMdjsUnified} pluginOptions
|
||||
* @param {EleventPluginMdjsUnified} pluginOptions
|
||||
*/
|
||||
function eleventyUnified(pluginOptions) {
|
||||
/**
|
||||
@@ -122,12 +119,8 @@ function eleventyUnified(pluginOptions) {
|
||||
return plugins.map(plugin => {
|
||||
if (plugin.options) {
|
||||
plugin.options.page = eleventySettings.page;
|
||||
plugin.options.rocketConfig = eleventySettings.rocketConfig;
|
||||
} else {
|
||||
plugin.options = {
|
||||
page: eleventySettings.page,
|
||||
rocketConfig: eleventySettings.rocketConfig,
|
||||
};
|
||||
plugin.options = { page: eleventySettings.page };
|
||||
}
|
||||
return plugin;
|
||||
});
|
||||
@@ -146,23 +139,10 @@ function eleventyUnified(pluginOptions) {
|
||||
|
||||
let code = result.html;
|
||||
if (result.jsCode) {
|
||||
const newFolder = path.dirname(eleventySettings.page.outputPath);
|
||||
const newName = path.join(newFolder, '__mdjs-stories.js');
|
||||
await fs.promises.mkdir(newFolder, { recursive: true });
|
||||
await fs.promises.writeFile(newName, result.jsCode, 'utf8');
|
||||
|
||||
let scriptUrl = eleventySettings.page.url;
|
||||
if (
|
||||
eleventySettings.rocketConfig &&
|
||||
eleventySettings.rocketConfig.command === 'build' &&
|
||||
eleventySettings.rocketConfig.pathPrefix
|
||||
) {
|
||||
scriptUrl = slash(
|
||||
path.join(eleventySettings.rocketConfig.pathPrefix, eleventySettings.page.url),
|
||||
);
|
||||
}
|
||||
code += `
|
||||
<script type="module" src="${scriptUrl}__mdjs-stories.js" mdjs-setup></script>
|
||||
<script type="module">
|
||||
${result.jsCode}
|
||||
</script>
|
||||
`;
|
||||
}
|
||||
return code;
|
||||
@@ -177,15 +157,15 @@ function eleventyUnified(pluginOptions) {
|
||||
|
||||
/**
|
||||
* @param {*} eleventyConfig
|
||||
* @param {EleventyPluginMdjsUnified} [pluginOptions]
|
||||
* @param {EleventPluginMdjsUnified} [pluginOptions]
|
||||
*/
|
||||
function configFunction(eleventyConfig, pluginOptions = {}) {
|
||||
eleventyConfig.setLibrary('md', eleventyUnified(pluginOptions));
|
||||
}
|
||||
|
||||
const EleventyPluginMdjsUnified = {
|
||||
const eleventPluginMdjsUnified = {
|
||||
initArguments: {},
|
||||
configFunction,
|
||||
};
|
||||
|
||||
module.exports = EleventyPluginMdjsUnified;
|
||||
module.exports = eleventPluginMdjsUnified;
|
||||
|
||||
@@ -53,12 +53,13 @@ describe('eleventy-plugin-mdjs-unified', () => {
|
||||
|
||||
it('renders markdown with javascript', async () => {
|
||||
const files = await renderEleventy('./test-node/fixtures/mdjs');
|
||||
|
||||
expect(files.length).to.equal(1);
|
||||
expect(files[0].name).to.equal('first/index.html');
|
||||
|
||||
expect(files[0].html).to.include('<script type="module"');
|
||||
expect(files[0].html).to.include('mdjs-setup>');
|
||||
expect(files).to.deep.equal([
|
||||
{
|
||||
html:
|
||||
'<h1 id="first"><a aria-hidden="true" tabindex="-1" href="#first"><span class="icon icon-link"></span></a>First</h1>\n<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> foo <span class="token operator">=</span> <span class="token string">\'bar\'</span><span class="token punctuation">;</span>\n<span class="token keyword module">import</span> <span class="token punctuation">{</span> html <span class="token punctuation">}</span> <span class="token keyword module">from</span> <span class="token string">\'lit-html\'</span><span class="token punctuation">;</span>\n</code></pre>\n<mdjs-story mdjs-story-name="inline"></mdjs-story>\n<mdjs-preview mdjs-story-name="withBorder"></mdjs-preview>\n <script type="module">\n \nexport const inline = () => html` <p>main</p> `;\nexport const withBorder = () => html` <p>main</p> `;\nconst rootNode = document;\nconst stories = [{ key: \'inline\', story: inline, code: `<pre class="language-js"><code class="language-js"><span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function">inline</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> html<span class="token template-string"><span class="token template-punctuation string">\\`</span><span class="token html language-html"> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>main<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span> </span><span class="token template-punctuation string">\\`</span></span><span class="token punctuation">;</span>\n</code></pre>` }, { key: \'withBorder\', story: withBorder, code: `<pre class="language-js"><code class="language-js"><span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function">withBorder</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> html<span class="token template-string"><span class="token template-punctuation string">\\`</span><span class="token html language-html"> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>main<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span> </span><span class="token template-punctuation string">\\`</span></span><span class="token punctuation">;</span>\n</code></pre>` }];\nfor (const story of stories) {\n const storyEl = rootNode.querySelector(`[mdjs-story-name="${story.key}"]`);\n storyEl.codeHasHtml = true;\n storyEl.story = story.story;\n storyEl.code = story.code;\n};\nif (!customElements.get(\'mdjs-preview\')) { import(\'@mdjs/mdjs-preview/mdjs-preview.js\'); }\nif (!customElements.get(\'mdjs-story\')) { import(\'@mdjs/mdjs-story/mdjs-story.js\'); }\n </script>\n ',
|
||||
name: 'first/index.html',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('rewrites relative import pathes', async () => {
|
||||
@@ -66,7 +67,7 @@ describe('eleventy-plugin-mdjs-unified', () => {
|
||||
expect(files).to.deep.equal([
|
||||
{
|
||||
html:
|
||||
'<p>first</p>\n <script type="module" src="/first/__mdjs-stories.js" mdjs-setup></script>\n ',
|
||||
"<p>first</p>\n <script type=\"module\">\n import '../import-me.js';\nimport('../import-me-too.js');\n </script>\n ",
|
||||
name: 'first/index.html',
|
||||
},
|
||||
]);
|
||||
@@ -77,7 +78,7 @@ describe('eleventy-plugin-mdjs-unified', () => {
|
||||
expect(files).to.deep.equal([
|
||||
{
|
||||
html:
|
||||
'<p>first</p>\n <script type="module" src="/subpage/first/__mdjs-stories.js" mdjs-setup></script>\n ',
|
||||
"<p>first</p>\n <script type=\"module\">\n import '../../import-me.js';\nimport('../../import-me-too.js');\n </script>\n ",
|
||||
name: 'subpage/first/index.html',
|
||||
},
|
||||
]);
|
||||
@@ -88,7 +89,7 @@ describe('eleventy-plugin-mdjs-unified', () => {
|
||||
expect(files).to.deep.equal([
|
||||
{
|
||||
html:
|
||||
'<p>index</p>\n <script type="module" src="/__mdjs-stories.js" mdjs-setup></script>\n ',
|
||||
"<p>index</p>\n <script type=\"module\">\n import './import-me.js';\nimport('./import-me-too.js');\n </script>\n ",
|
||||
name: 'index.html',
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Node } from 'unist';
|
||||
|
||||
export const setupUnifiedPluginsFn: (plugins: MdjsProcessPlugin[]) => MdjsProcessPlugin[];
|
||||
|
||||
export interface EleventyPluginMdjsUnified {
|
||||
export interface EleventPluginMdjsUnified {
|
||||
setupUnifiedPlugins?: setupUnifiedPluginsFn[];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const RocketNav = require('./eleventy-rocket-nav');
|
||||
const { addPageAnchors } = require('./src/addPageAnchors.js');
|
||||
|
||||
// export the configuration function for plugin
|
||||
module.exports = function (eleventyConfig) {
|
||||
@@ -9,10 +8,6 @@ module.exports = function (eleventyConfig) {
|
||||
eleventyConfig.addNunjucksFilter('rocketNavToHtml', function (pages, options) {
|
||||
return RocketNav.toHtml.call(eleventyConfig, pages, options);
|
||||
});
|
||||
eleventyConfig.addTransform('rocket-nav-add-page-anchors', async function (content) {
|
||||
const newContent = await addPageAnchors(content);
|
||||
return newContent;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.navigation = {
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
# @rocket/eleventy-rocket-nav
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- ef8ebb0: To support dynamically created content to be part of the anchor navigation of the page we now analyze the final html output instead of `entry.templateContent`.
|
||||
|
||||
BREAKING CHANGE:
|
||||
|
||||
- only add anchors for the currently active pages (before it added anchor for every page)
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -94,8 +94,21 @@ function findNavigationEntries(nodes = [], key = '') {
|
||||
entry.title = entry.key;
|
||||
}
|
||||
if (entry.key) {
|
||||
if (!headingsCache.has(entry.templateContent)) {
|
||||
headingsCache.set(entry.templateContent, getHeadingsOfHtml(entry.templateContent));
|
||||
}
|
||||
const headings = /** @type {Heading[]} */ (headingsCache.get(entry.templateContent));
|
||||
const anchors = headings.map(heading => ({
|
||||
key: heading.text + Math.random(),
|
||||
parent: entry.key,
|
||||
url: `${entry.url}#${heading.id}`,
|
||||
pluginType: 'eleventy-navigation',
|
||||
parentKey: entry.key,
|
||||
title: heading.text,
|
||||
anchor: true,
|
||||
}));
|
||||
// @ts-ignore
|
||||
entry.children = findNavigationEntries(nodes, entry.key);
|
||||
entry.children = [...anchors, ...findNavigationEntries(nodes, entry.key)];
|
||||
}
|
||||
return entry;
|
||||
});
|
||||
@@ -214,36 +227,43 @@ function navigationToHtml(pages, _options = {}) {
|
||||
}>${pages
|
||||
.map(entry => {
|
||||
const liClass = [];
|
||||
const aClass = [];
|
||||
if (options.listItemClass) {
|
||||
liClass.push(options.listItemClass);
|
||||
}
|
||||
if (options.activeKey === entry.key && options.activeListItemClass) {
|
||||
liClass.push(options.activeListItemClass);
|
||||
if (options.anchorClass) {
|
||||
aClass.push(options.anchorClass);
|
||||
}
|
||||
if (options.activeKey === entry.key) {
|
||||
if (options.activeListItemClass) {
|
||||
liClass.push(options.activeListItemClass);
|
||||
}
|
||||
if (options.activeAnchorClass) {
|
||||
aClass.push(options.activeAnchorClass);
|
||||
}
|
||||
}
|
||||
if (options.activeTreeListClass && activePages && activePages.includes(entry.key)) {
|
||||
liClass.push(options.activeTreeListClass);
|
||||
}
|
||||
if (options.activeAnchorListClass && activePages && activePages.includes(entry.key)) {
|
||||
aClass.push(options.activeAnchorListClass);
|
||||
}
|
||||
if (options.listItemHasChildrenClass && entry.children && entry.children.length) {
|
||||
liClass.push(options.listItemHasChildrenClass);
|
||||
}
|
||||
|
||||
const output = [];
|
||||
output.push(
|
||||
`<${options.listItemElement}${liClass.length ? ` class="${liClass.join(' ')}"` : ''}>`,
|
||||
);
|
||||
output.push(`<a href="${urlFilter(entry.url)}">${entry.title}</a>`);
|
||||
if (options.showExcerpt && entry.excerpt) {
|
||||
output.push(`: ${entry.excerpt}`);
|
||||
if (entry.anchor) {
|
||||
liClass.push('anchor');
|
||||
aClass.push('anchor');
|
||||
}
|
||||
if (options.activeKey === entry.key && options.activeListItemClass) {
|
||||
output.push('<!-- ADD PAGE ANCHORS -->');
|
||||
}
|
||||
if (entry.children) {
|
||||
output.push(navigationToHtml(entry.children, options));
|
||||
}
|
||||
output.push(`</${options.listItemElement}>`);
|
||||
|
||||
return output.join('\n');
|
||||
return `<${options.listItemElement}${
|
||||
liClass.length ? ` class="${liClass.join(' ')}"` : ''
|
||||
}><a href="${urlFilter(entry.url)}"${
|
||||
aClass.length ? ` class="${aClass.join(' ')}"` : ''
|
||||
}>${entry.title}</a>${options.showExcerpt && entry.excerpt ? `: ${entry.excerpt}` : ''}${
|
||||
entry.children ? navigationToHtml(entry.children, options) : ''
|
||||
}</${options.listItemElement}>`;
|
||||
})
|
||||
.join('\n')}</${options.listElement}>`
|
||||
: '';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/eleventy-rocket-nav",
|
||||
"version": "0.3.0",
|
||||
"version": "0.2.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
"main": ".eleventy.js",
|
||||
"scripts": {
|
||||
"test": "mocha test-node/**/*.test.js test-node/*.test.js --timeout 5000",
|
||||
"test": "mocha test-node/**/*.test.js test-node/*.test.js",
|
||||
"test:watch": "mocha test-node/**/*.test.js test-node/*.test.js --watch"
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
const fs = require('fs');
|
||||
const { SaxEventType, SAXParser } = require('sax-wasm');
|
||||
|
||||
const saxPath = require.resolve('sax-wasm/lib/sax-wasm.wasm');
|
||||
const saxWasmBuffer = fs.readFileSync(saxPath);
|
||||
|
||||
/** @typedef {import('../types').Heading} Heading */
|
||||
|
||||
/** @typedef {import('sax-wasm').Text} Text */
|
||||
/** @typedef {import('sax-wasm').Tag} Tag */
|
||||
/** @typedef {import('sax-wasm').Position} Position */
|
||||
|
||||
// Instantiate
|
||||
const parser = new SAXParser(
|
||||
SaxEventType.CloseTag | SaxEventType.Comment,
|
||||
{ highWaterMark: 256 * 1024 }, // 256k chunks
|
||||
);
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
* @param {string} options.content
|
||||
* @param {Position} options.start
|
||||
* @param {Position} options.end
|
||||
* @param {string} options.insert
|
||||
*/
|
||||
function removeBetween({ content, start, end, insert = '' }) {
|
||||
const lines = content.split('\n');
|
||||
const i = start.line;
|
||||
const line = lines[i];
|
||||
const upToChange = line.slice(0, start.character - 1);
|
||||
const afterChange = line.slice(end.character + 2);
|
||||
|
||||
lines[i] = `${upToChange}${insert}${afterChange}`;
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Tag} data
|
||||
* @param {string} name
|
||||
*/
|
||||
function getAttribute(data, name) {
|
||||
if (data.attributes) {
|
||||
const { attributes } = data;
|
||||
const foundIndex = attributes.findIndex(entry => entry.name.value === name);
|
||||
if (foundIndex !== -1) {
|
||||
return attributes[foundIndex].value.value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Tag} data
|
||||
*/
|
||||
function getText(data) {
|
||||
if (data.textNodes) {
|
||||
return data.textNodes.map(textNode => textNode.value).join('');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} html
|
||||
*/
|
||||
function getHeadingsOfHtml(html) {
|
||||
/** @type {Heading[]} */
|
||||
const headings = [];
|
||||
/** @type {Text} */
|
||||
let insertPoint;
|
||||
parser.eventHandler = (ev, _data) => {
|
||||
if (ev === SaxEventType.Comment) {
|
||||
const data = /** @type {Text} */ (/** @type {any} */ (_data));
|
||||
// NOTE: we NEED to access data internal value so sax-wasm does not reuse it's value
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const tmp = data.start.line + data.end.line;
|
||||
if (data.value.trim() === 'ADD PAGE ANCHORS' || data.value.trim() === '-->ADD PAGE ANCHORS') {
|
||||
insertPoint = data;
|
||||
}
|
||||
}
|
||||
|
||||
if (ev === SaxEventType.CloseTag) {
|
||||
const data = /** @type {Tag} */ (/** @type {any} */ (_data));
|
||||
if (data.name === 'h2') {
|
||||
const id = getAttribute(data, 'id');
|
||||
const text = getText(data);
|
||||
if (id && text) {
|
||||
headings.push({ text, id });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
parser.write(Buffer.from(html, 'utf8'));
|
||||
parser.end();
|
||||
|
||||
// @ts-ignore
|
||||
return { headings, insertPoint };
|
||||
}
|
||||
|
||||
let isSetup = false;
|
||||
|
||||
/**
|
||||
* @param {string} content
|
||||
*/
|
||||
async function addPageAnchors(content) {
|
||||
if (!isSetup) {
|
||||
await parser.prepareWasm(saxWasmBuffer);
|
||||
isSetup = true;
|
||||
}
|
||||
|
||||
const { headings, insertPoint } = getHeadingsOfHtml(content);
|
||||
const pageAnchorsHtml = [];
|
||||
if (headings.length > 0) {
|
||||
pageAnchorsHtml.push('<ul>');
|
||||
for (const heading of headings) {
|
||||
pageAnchorsHtml.push(' <li class="menu-item anchor">');
|
||||
pageAnchorsHtml.push(` <a href="#${heading.id}" class="anchor">${heading.text}</a>`);
|
||||
pageAnchorsHtml.push(' </li>');
|
||||
}
|
||||
pageAnchorsHtml.push('</ul>');
|
||||
}
|
||||
|
||||
if (insertPoint) {
|
||||
return removeBetween({
|
||||
content,
|
||||
start: insertPoint.start,
|
||||
end: insertPoint.end,
|
||||
insert: pageAnchorsHtml.join('\n'),
|
||||
});
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addPageAnchors,
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
const { expect } = require('chai');
|
||||
const prettier = require('prettier');
|
||||
const { addPageAnchors } = require('../src/addPageAnchors.js');
|
||||
|
||||
const format = code => prettier.format(code, { parser: 'html' }).trim();
|
||||
|
||||
describe('addPageAnchors', () => {
|
||||
it('finds and adds anchors for each h2 as an unordered list', async () => {
|
||||
const input = [
|
||||
'<body>',
|
||||
' <!-- ADD PAGE ANCHORS -->',
|
||||
' <div id="content">',
|
||||
' <h2 id="first">👉 First Headline</h2>',
|
||||
' </div>',
|
||||
'</body>',
|
||||
].join('\n');
|
||||
const expected = [
|
||||
'<body>',
|
||||
' <ul>',
|
||||
' <li class="menu-item anchor">',
|
||||
' <a href="#first" class="anchor">👉 First Headline</a>',
|
||||
' </li>',
|
||||
' </ul>',
|
||||
' <div id="content">',
|
||||
' <h2 id="first">👉 First Headline</h2>',
|
||||
' </div>',
|
||||
'</body>',
|
||||
].join('\n');
|
||||
const result = await addPageAnchors(input);
|
||||
expect(format(result)).to.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
const eleventyNavigationPlugin = require('@rocket/eleventy-rocket-nav');
|
||||
|
||||
module.exports = function (eleventyConfig) {
|
||||
eleventyConfig.addPlugin(eleventyNavigationPlugin);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = 'layout.njk';
|
||||
@@ -1,9 +0,0 @@
|
||||
<body>
|
||||
{{ collections.all | rocketNav | rocketNavToHtml({
|
||||
listItemClass: "menu-item",
|
||||
activeListItemClass: "current",
|
||||
activeKey: eleventyNavigation.key
|
||||
}) | safe }}
|
||||
|
||||
{{ content | safe }}
|
||||
</body>
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
title: Bats
|
||||
eleventyNavigation:
|
||||
key: Bats
|
||||
parent: Mammals
|
||||
order: 2
|
||||
---
|
||||
|
||||
🦇 can fly.
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
title: Humans
|
||||
eleventyNavigation:
|
||||
key: Humans
|
||||
parent: Mammals
|
||||
order: 1
|
||||
---
|
||||
|
||||
<h2 id="anatomy">Anatomy</h2>
|
||||
<p>Has arms.</p>
|
||||
<h2 id="age">📖 Age</h2>
|
||||
<p>Up to 130 years.</p>
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: Mammals
|
||||
eleventyNavigation:
|
||||
key: Mammals
|
||||
---
|
||||
|
||||
Mammals need air.
|
||||
@@ -1,96 +0,0 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const { expect } = require('chai');
|
||||
const Eleventy = require('@11ty/eleventy');
|
||||
const TemplateConfig = require('@11ty/eleventy/src/TemplateConfig');
|
||||
const prettier = require('prettier');
|
||||
|
||||
async function execute(fixtureDir) {
|
||||
const relPath = path.relative(process.cwd(), __dirname);
|
||||
const relativeInputPath = path.join(relPath, fixtureDir.split('/').join(path.sep));
|
||||
const relativeOutputPath = path.join(relPath, 'fixtures', '__output');
|
||||
const relativeConfigPath = path.join(relativeInputPath, '.eleventy.js');
|
||||
|
||||
await fs.emptyDir(relativeOutputPath);
|
||||
|
||||
const elev = new Eleventy(relativeInputPath, relativeOutputPath);
|
||||
const config = new TemplateConfig(null, relativeConfigPath);
|
||||
elev.config = config.getConfig();
|
||||
elev.setConfigPathOverride(relativeConfigPath);
|
||||
elev.resetConfig();
|
||||
|
||||
await elev.init();
|
||||
await elev.write();
|
||||
return {
|
||||
readOutput: async readPath => {
|
||||
const relativeReadPath = path.join(relativeOutputPath, readPath);
|
||||
let text = await fs.promises.readFile(relativeReadPath);
|
||||
text = text.toString();
|
||||
text = prettier.format(text, { parser: 'html', printWidth: 100 });
|
||||
return text.trim();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe('eleventy-rocket-nav', () => {
|
||||
it('renders a menu with anchors for h2 content', async () => {
|
||||
const { readOutput } = await execute('fixtures/three-pages');
|
||||
|
||||
const bats = await readOutput('bats/index.html');
|
||||
expect(bats).to.deep.equal(
|
||||
[
|
||||
'<body>',
|
||||
' <ul>',
|
||||
' <li class="menu-item active">',
|
||||
' <a href="/mammals/">Mammals</a>',
|
||||
' <ul>',
|
||||
' <li class="menu-item">',
|
||||
' <a href="/humans/">Humans</a>',
|
||||
' </li>',
|
||||
' <li class="menu-item current">',
|
||||
' <a href="/bats/">Bats</a>',
|
||||
' </li>',
|
||||
' </ul>',
|
||||
' </li>',
|
||||
' </ul>',
|
||||
'',
|
||||
' <p>🦇 can fly.</p>',
|
||||
'</body>',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
const humans = await readOutput('humans/index.html');
|
||||
expect(humans).to.deep.equal(
|
||||
[
|
||||
'<body>',
|
||||
' <ul>',
|
||||
' <li class="menu-item active">',
|
||||
' <a href="/mammals/">Mammals</a>',
|
||||
' <ul>',
|
||||
' <li class="menu-item current">',
|
||||
' <a href="/humans/">Humans</a>',
|
||||
' <ul>',
|
||||
' <li class="menu-item anchor">',
|
||||
' <a href="#anatomy" class="anchor">Anatomy</a>',
|
||||
' </li>',
|
||||
' <li class="menu-item anchor">',
|
||||
' <a href="#age" class="anchor">📖 Age</a>',
|
||||
' </li>',
|
||||
' </ul>',
|
||||
' </li>',
|
||||
' <li class="menu-item">',
|
||||
' <a href="/bats/">Bats</a>',
|
||||
' </li>',
|
||||
' </ul>',
|
||||
' </li>',
|
||||
' </ul>',
|
||||
'',
|
||||
' <h2 id="anatomy">Anatomy</h2>',
|
||||
' <p>Has arms.</p>',
|
||||
' <h2 id="age">📖 Age</h2>',
|
||||
' <p>Up to 130 years.</p>',
|
||||
'</body>',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
});
|
||||
28
packages/generate-import-map/README.md
Normal file
28
packages/generate-import-map/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Check HTML Links
|
||||
|
||||
A fast checker for broken links/references in HTML.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm i -D check-html-links
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
npx check-html-links _site
|
||||
```
|
||||
|
||||
For docs please see our homepage [https://rocket.modern-web.dev/docs/tools/check-html-links/](https://rocket.modern-web.dev/docs/tools/check-html-links/).
|
||||
|
||||
## Comparison
|
||||
|
||||
Checking the output of the [11ty-website](https://github.com/11ty/11ty-website) with 13 missing reference targets (used by 516 links) while checking 501 files. (on January 17, 2021)
|
||||
|
||||
| Tool | Lines printed | Times | Lang | Dependency Tree |
|
||||
| ---------------- | ------------- | ------ | ---- | --------------- |
|
||||
| check-html-links | 38 | ~2.5s | node | 19 |
|
||||
| link-checker | 3000+ | ~11s | node | 106 |
|
||||
| hyperlink | 68 | 4m 20s | node | 481 |
|
||||
| htmltest | 1000+ | ~0.7s | GO | - |
|
||||
1
packages/generate-import-map/index.js
Normal file
1
packages/generate-import-map/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { inspectFolder } from './src/inspectFolder.js';
|
||||
47
packages/generate-import-map/package.json
Normal file
47
packages/generate-import-map/package.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "generate-import-map",
|
||||
"version": "0.0.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"description": "A fast low dependency generator of import map",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/modernweb-dev/rocket.git",
|
||||
"directory": "packages/generate-import-map"
|
||||
},
|
||||
"author": "Modern Web <hello@modern-web.dev> (https://modern-web.dev/)",
|
||||
"homepage": "https://rocket.modern-web.dev/docs/tools/generate-import-map/",
|
||||
"bin": {
|
||||
"generate-import-map": "src/cli.js"
|
||||
},
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha --timeout 5000 test-node/**/*.test.{js,cjs} test-node/*.test.{js,cjs}",
|
||||
"test:watch": "onchange 'src/**/*.{js,cjs}' 'test-node/**/*.{js,cjs}' -- npm test",
|
||||
"types:copy": "copyfiles \"./types/**/*.d.ts\" dist-types/"
|
||||
},
|
||||
"files": [
|
||||
"*.js",
|
||||
"dist",
|
||||
"dist-types",
|
||||
"src"
|
||||
],
|
||||
"dependencies": {
|
||||
"chalk": "^4.0.0",
|
||||
"es-module-lexer": "^0.3.26",
|
||||
"glob": "^7.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"sax-wasm": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/es-module-lexer": "^0.3.0",
|
||||
"@types/glob": "^7.0.0",
|
||||
"@types/node-fetch": "^2.5.8"
|
||||
},
|
||||
"types": "dist-types/index.d.ts"
|
||||
}
|
||||
54
packages/generate-import-map/src/cli.js
Executable file
54
packages/generate-import-map/src/cli.js
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
import { extractBareImports } from './inspectFolder.js';
|
||||
import { checkRemoteSpecifiers, createImportMap } from './createImportMap.js';
|
||||
import { listFiles } from './listFiles.js';
|
||||
|
||||
async function main() {
|
||||
const userRootDir = process.argv[2];
|
||||
const userImportMapDist = process.argv[3];
|
||||
const remoteUrl = process.argv[4];
|
||||
const rootDir = userRootDir ? path.resolve(userRootDir) : process.cwd();
|
||||
const importMapDist = userImportMapDist
|
||||
? path.resolve(userImportMapDist)
|
||||
: `${process.cwd()}/import-map.json`;
|
||||
|
||||
const performanceInspectStart = process.hrtime();
|
||||
|
||||
console.log('👀 Looking for all imports...');
|
||||
const files = await listFiles('**/*.html', rootDir);
|
||||
|
||||
const filesOutput =
|
||||
files.length == 0
|
||||
? '🧐 No files to check. Did you select the correct folder?'
|
||||
: `🔥 Found a total of ${chalk.green.bold(files.length)} files to check!`;
|
||||
console.log(filesOutput);
|
||||
|
||||
const { localSpecifiers, bareSpecifiers } = await extractBareImports(files, rootDir);
|
||||
const performanceInspectEnd = process.hrtime(performanceInspectStart);
|
||||
|
||||
console.log(
|
||||
`🔗 Found a total of ${chalk.green.bold(
|
||||
localSpecifiers.length,
|
||||
)} local imports and ${chalk.green.bold(bareSpecifiers.length)} bare imports!`,
|
||||
);
|
||||
console.log(
|
||||
`✅ Files inspected. (executed in %ds %dms)`,
|
||||
performanceInspectEnd[0],
|
||||
performanceInspectEnd[1] / 1000000,
|
||||
);
|
||||
|
||||
const performanceRemoteStart = process.hrtime();
|
||||
const foundBareSpecifiers = await checkRemoteSpecifiers(bareSpecifiers, remoteUrl);
|
||||
createImportMap(foundBareSpecifiers, remoteUrl, importMapDist);
|
||||
const performanceRemoteEnd = process.hrtime(performanceRemoteStart);
|
||||
console.log(
|
||||
`✅ Remote CDN check and import map created. (executed in %ds %dms)`,
|
||||
performanceRemoteEnd[0],
|
||||
performanceRemoteEnd[1] / 1000000,
|
||||
);
|
||||
}
|
||||
|
||||
main();
|
||||
48
packages/generate-import-map/src/createImportMap.js
Normal file
48
packages/generate-import-map/src/createImportMap.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
export const defaultRemoteUrl = 'https://cdn.skypack.dev/';
|
||||
export const defaultImportMapDist = path.resolve('./import-map.json');
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string[]} bareSpecifiers
|
||||
* @param {string} remoteUrl
|
||||
*/
|
||||
export async function checkRemoteSpecifiers(bareSpecifiers, remoteUrl = defaultRemoteUrl) {
|
||||
/** @type {Promise<void>[]} */
|
||||
const promises = [];
|
||||
/** @type {string[]} */
|
||||
const result = [];
|
||||
bareSpecifiers.forEach(specifier => {
|
||||
const remoteSpecifier = `${remoteUrl}${specifier}`;
|
||||
const promise = fetch(remoteSpecifier).then(response => {
|
||||
if (response.ok) {
|
||||
result.push(specifier);
|
||||
}
|
||||
});
|
||||
promises.push(promise);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string[]} bareSpecifiers
|
||||
* @param {string} remoteUrl
|
||||
* @param {string} importMapDist
|
||||
*/
|
||||
export function createImportMap(
|
||||
bareSpecifiers,
|
||||
remoteUrl = defaultRemoteUrl,
|
||||
importMapDist = defaultImportMapDist,
|
||||
) {
|
||||
const imports = {};
|
||||
bareSpecifiers.forEach(specifier => {
|
||||
const remoteSpecifier = `${remoteUrl}${specifier}`;
|
||||
imports[specifier] = remoteSpecifier;
|
||||
});
|
||||
fs.writeFileSync(importMapDist, JSON.stringify({ imports }, null, 2));
|
||||
}
|
||||
197
packages/generate-import-map/src/inspectFolder.js
Normal file
197
packages/generate-import-map/src/inspectFolder.js
Normal file
@@ -0,0 +1,197 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import fs from 'fs';
|
||||
import saxWasm from 'sax-wasm';
|
||||
import { createRequire } from 'module';
|
||||
import { init, parse } from 'es-module-lexer';
|
||||
|
||||
import { listFiles } from './listFiles.js';
|
||||
import path from 'path';
|
||||
|
||||
/** @typedef {import('../types/main').Script} Script */
|
||||
/** @typedef {import('../types/main').Import} Import */
|
||||
/** @typedef {import('sax-wasm').Attribute} Attribute */
|
||||
/** @typedef {import('sax-wasm').Tag} Tag */
|
||||
/** @typedef {import('sax-wasm').Text} Text */
|
||||
/** @typedef {import('es-module-lexer').ImportSpecifier} ImportSpecifier */
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const { SaxEventType, SAXParser } = saxWasm;
|
||||
|
||||
const streamOptions = { highWaterMark: 256 * 1024 };
|
||||
|
||||
const saxPath = require.resolve('sax-wasm/lib/sax-wasm.wasm');
|
||||
const saxWasmBuffer = fs.readFileSync(saxPath);
|
||||
const parserSpecifiers = new SAXParser(
|
||||
SaxEventType.OpenTag | SaxEventType.CloseTag | SaxEventType.Attribute | SaxEventType.Text,
|
||||
streamOptions,
|
||||
);
|
||||
|
||||
let localSpecifiers = new Set();
|
||||
let bareSpecifiers = new Set();
|
||||
|
||||
/**
|
||||
* @param {string} filePath
|
||||
* @param {object} option
|
||||
* @param {string} option.rootDir
|
||||
*/
|
||||
function analyzeFile(filePath, { rootDir }) {
|
||||
if (fs.existsSync(filePath) && !fs.lstatSync(filePath).isDirectory()) {
|
||||
const source = fs.readFileSync(filePath, { encoding: 'utf-8' });
|
||||
const importDir = path.dirname(filePath);
|
||||
console.log('Resolving specifier %s', filePath);
|
||||
getSpecifiers(source).forEach(specifier => {
|
||||
addSpecifier(specifier, { importDir, rootDir });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} source
|
||||
*/
|
||||
function getSpecifiers(source) {
|
||||
/** @type {[ImportSpecifier[], string[]]} */
|
||||
const [imports] = parse(source, 'optional-sourcename');
|
||||
return imports.map(specifier => source.substring(specifier.s, specifier.e).replace(/'/g, ''));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} specifier
|
||||
* @param {object} options
|
||||
* @param {string} options.importDir
|
||||
* @param {string} options.rootDir
|
||||
*/
|
||||
function addSpecifier(specifier, { importDir, rootDir }) {
|
||||
let newSpecifier = specifier.trim();
|
||||
if (newSpecifier.endsWith('/')) {
|
||||
newSpecifier += 'index.js';
|
||||
}
|
||||
|
||||
if (newSpecifier.startsWith('/')) {
|
||||
// Absolute path specifier
|
||||
newSpecifier = path.join(rootDir, newSpecifier);
|
||||
} else if (newSpecifier.startsWith('../') || newSpecifier.startsWith('./')) {
|
||||
// Relative path specifier
|
||||
newSpecifier = path.join(importDir, newSpecifier);
|
||||
}
|
||||
|
||||
if (newSpecifier.startsWith('/')) {
|
||||
if (!localSpecifiers.has(newSpecifier)) {
|
||||
localSpecifiers.add(newSpecifier);
|
||||
analyzeFile(newSpecifier, { rootDir });
|
||||
}
|
||||
} else {
|
||||
const [namespace, name] = newSpecifier.split('/');
|
||||
if (namespace.startsWith('@')) {
|
||||
newSpecifier = `${namespace}/${name}`;
|
||||
} else {
|
||||
newSpecifier = namespace;
|
||||
}
|
||||
bareSpecifiers.add(newSpecifier);
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {Script[]} scripts
|
||||
* @param {object} options
|
||||
* @param {string} options.importDir
|
||||
* @param {string} options.rootDir
|
||||
*/
|
||||
async function resolveSpecifiers(scripts, { importDir, rootDir }) {
|
||||
for (const scriptObj of scripts) {
|
||||
if (scriptObj.specifier) {
|
||||
addSpecifier(scriptObj.specifier, { importDir, rootDir });
|
||||
} else {
|
||||
getSpecifiers(scriptObj.content).forEach(specifier => {
|
||||
addSpecifier(specifier, { importDir, rootDir });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} filePath
|
||||
*/
|
||||
function extractScripts(filePath) {
|
||||
/** @type {Script[]} */
|
||||
const scripts = [];
|
||||
|
||||
let captureContent = false;
|
||||
|
||||
parserSpecifiers.eventHandler = (ev, /** @type {any} */ _data) => {
|
||||
const data = /** @type {Tag | Text} */ _data;
|
||||
if (captureContent && ev === SaxEventType.Text) {
|
||||
const scriptObj = scripts[scripts.length - 1];
|
||||
scriptObj.content += data.value;
|
||||
} else if (ev === SaxEventType.CloseTag && data.name.toString() === 'script') {
|
||||
captureContent = false;
|
||||
} else if (ev === SaxEventType.OpenTag) {
|
||||
const tagName = data.name.toString();
|
||||
const type = data.attributes.find(
|
||||
(/** @type Attribute */ attr) => attr.name.toString() === 'type',
|
||||
);
|
||||
if (tagName === 'script' && type?.value.toString() === 'module') {
|
||||
const scriptObj = /** @type {Script} */ {
|
||||
filePath,
|
||||
content: '',
|
||||
specifier: '',
|
||||
};
|
||||
const src = data.attributes.find(
|
||||
(/** @type Attribute */ attr) => attr.name.toString() === 'src',
|
||||
);
|
||||
if (src) {
|
||||
let srcPath = src.value.toString().trim();
|
||||
if (!srcPath.startsWith('.') || !srcPath.startsWith('/')) {
|
||||
srcPath = `./${srcPath}`;
|
||||
}
|
||||
scriptObj.specifier = srcPath;
|
||||
} else {
|
||||
captureContent = true;
|
||||
}
|
||||
scripts.push(scriptObj);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise(resolve => {
|
||||
const readable = fs.createReadStream(filePath, streamOptions);
|
||||
readable.on('data', chunk => {
|
||||
// @ts-expect-error
|
||||
parserSpecifiers.write(chunk);
|
||||
});
|
||||
readable.on('end', () => {
|
||||
parserSpecifiers.end();
|
||||
resolve(scripts);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} files
|
||||
* @param {string} rootDir
|
||||
*/
|
||||
export async function extractBareImports(files, rootDir) {
|
||||
await parserSpecifiers.prepareWasm(saxWasmBuffer);
|
||||
await init;
|
||||
|
||||
localSpecifiers = new Set();
|
||||
bareSpecifiers = new Set();
|
||||
for (const filePath of files) {
|
||||
const importDir = path.dirname(filePath);
|
||||
const scripts = await extractScripts(filePath);
|
||||
await resolveSpecifiers(scripts, { importDir, rootDir });
|
||||
}
|
||||
return {
|
||||
localSpecifiers: Array.from(localSpecifiers),
|
||||
bareSpecifiers: Array.from(bareSpecifiers),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} inRootDir
|
||||
*/
|
||||
export async function inspectFolder(inRootDir, extension = 'html') {
|
||||
const rootDir = path.resolve(inRootDir);
|
||||
const files = await listFiles(`**/*.${extension}`, rootDir);
|
||||
return await extractBareImports(files, rootDir);
|
||||
}
|
||||
34
packages/generate-import-map/src/listFiles.js
Normal file
34
packages/generate-import-map/src/listFiles.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import glob from 'glob';
|
||||
|
||||
/**
|
||||
* Lists all files using the specified glob, starting from the given root directory.
|
||||
*
|
||||
* Will return all matching file paths fully resolved.
|
||||
*
|
||||
* @param {string} fromGlob
|
||||
* @param {string} rootDir
|
||||
*/
|
||||
export function listFiles(fromGlob, rootDir) {
|
||||
return new Promise(resolve => {
|
||||
glob(
|
||||
fromGlob,
|
||||
{ cwd: rootDir },
|
||||
/**
|
||||
* @param {Error | null} er
|
||||
* @param {string[]} files
|
||||
*/
|
||||
(er, files) => {
|
||||
// remember, each filepath returned is relative to rootDir
|
||||
resolve(
|
||||
files
|
||||
// fully resolve the filename relative to rootDir
|
||||
.map(filePath => path.resolve(rootDir, filePath))
|
||||
// filter out directories
|
||||
.filter(filePath => !fs.lstatSync(filePath).isDirectory()),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<script>
|
||||
import "/empty.js";
|
||||
</script>
|
||||
<script>
|
||||
import "./empty.js";
|
||||
</script>
|
||||
<script>
|
||||
import "./empty.js ";
|
||||
</script>
|
||||
<script>
|
||||
import " ./empty.js ";
|
||||
</script>
|
||||
@@ -0,0 +1,4 @@
|
||||
<script src="/empty.js"></script>
|
||||
<script src="./empty.js"></script>
|
||||
<script src="./empty.js "></script>
|
||||
<script src=" ./empty.js "></script>
|
||||
@@ -0,0 +1 @@
|
||||
export { TestComponent } from './src/TestComponent.js';
|
||||
@@ -0,0 +1,3 @@
|
||||
import { LitElement } from 'lit-element';
|
||||
|
||||
export class TestElement extends LitElement {}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { TestComponent } from './src/TestComponent.js';
|
||||
|
||||
window.customElements.define('test-element', TestComponent);
|
||||
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<script src="scripts/main.js" type="module"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,545 @@
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
|
||||
|
||||
<head>
|
||||
|
||||
<link rel="stylesheet" href="/_merged_assets/rocket-blog.css">
|
||||
|
||||
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<meta name="twitter:creator" content="@modern_web_dev" />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Markdown JavaScript: Overview: Rocket</title>
|
||||
<meta property="og:title" content="Markdown JavaScript: Overview: Rocket"/>
|
||||
|
||||
<meta name="generator" content="rocket 0.1">
|
||||
<link rel="canonical" href="/docs/markdown-javascript/overview/"/>
|
||||
|
||||
|
||||
|
||||
<meta name="description" content="Rocket is the way to build fast static websites with a sprinkle of JavaScript"/>
|
||||
<meta property="og:description" content="Rocket is the way to build fast static websites with a sprinkle of JavaScript"/>
|
||||
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/_merged_assets/_static/icons/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/_merged_assets/_static/icons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/_merged_assets/_static/icons/favicon-16x16.png">
|
||||
<link rel="manifest" href="/_merged_assets/webmanifest.json">
|
||||
<link rel="mask-icon" href="/_merged_assets/_static/icons/safari-pinned-tab.svg" color="#3f93ce">
|
||||
<meta name="msapplication-TileColor" content="#1d3557">
|
||||
<meta name="theme-color" content="#1d3557">
|
||||
|
||||
|
||||
<meta property="og:site_name" content="Rocket"/>
|
||||
<meta property="og:type" content="website"/>
|
||||
|
||||
<meta property="og:image" content="/_merged_assets/11ty-img/f8d62426-1200.png"/>
|
||||
<meta property="og:url" content="/docs/markdown-javascript/overview/"/>
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image"/>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/_merged_assets/variables.css">
|
||||
<link rel="stylesheet" href="/_merged_assets/layout.css">
|
||||
<link rel="stylesheet" href="/_merged_assets/markdown.css">
|
||||
<link rel="stylesheet" href="/_merged_assets/style.css">
|
||||
|
||||
|
||||
<noscript><link rel="stylesheet" href="/_merged_assets/_static/noscript.css"/></noscript>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
<body layout="layout-sidebar">
|
||||
|
||||
|
||||
|
||||
<header id="main-header">
|
||||
<div class="content-area">
|
||||
|
||||
<button id="mobile-menu-trigger" data-action="trigger-mobile-menu">
|
||||
<span class="sr-only">Show Menu</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewbox="0 0 448 512" class="icon">
|
||||
<path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path>
|
||||
</svg>
|
||||
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<a class="logo-link" href="/">
|
||||
<img src="/_merged_assets/logo.svg" alt="Rocket Logo" />
|
||||
<span>Rocket</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
|
||||
<rocket-search class="search" json-url="/_merged_assets/_static/rocket-search-index.json">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 129 129" style="width: 25px;">
|
||||
<path d="M51.6 96.7c11 0 21-3.9 28.8-10.5l35 35c.8.8 1.8 1.2 2.9 1.2s2.1-.4 2.9-1.2c1.6-1.6 1.6-4.2 0-5.8l-35-35c6.5-7.8 10.5-17.9 10.5-28.8 0-24.9-20.2-45.1-45.1-45.1-24.8 0-45.1 20.3-45.1 45.1 0 24.9 20.3 45.1 45.1 45.1zm0-82c20.4 0 36.9 16.6 36.9 36.9C88.5 72 72 88.5 51.6 88.5S14.7 71.9 14.7 51.6c0-20.3 16.6-36.9 36.9-36.9z"/>
|
||||
</svg>
|
||||
</rocket-search>
|
||||
|
||||
<script type="module">
|
||||
import '@rocket/search/rocket-search.js';
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<a href="/guides/" class="
|
||||
|
||||
|
||||
">Guides</a>
|
||||
<a href="/docs/" class="
|
||||
|
||||
active
|
||||
">Docs</a>
|
||||
<a href="/blog/" class="
|
||||
|
||||
|
||||
">Blog</a>
|
||||
|
||||
|
||||
<launch-dark-switch class="light-dark-switch" label="Toggle darkmode">Toggle darkmode</launch-dark-switch>
|
||||
|
||||
|
||||
|
||||
|
||||
<a class="social-link" href="https://github.com/modernweb-dev/rocket" aria-label="Rocket on GitHub" rel="noopener noreferrer" target="_blank">
|
||||
<span class="sr-only">GitHub</span>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 17 16" fill="none">
|
||||
<title>GitHub</title>
|
||||
<path fill="currentColor" fill-rule="evenodd" d="M8.18391.249268C3.82241.249268.253906 3.81777.253906 8.17927c0 3.46933 2.279874 6.44313 5.451874 7.53353.3965.0991.49563-.1983.49563-.3965v-1.3878c-2.18075.4956-2.67638-.9912-2.67638-.9912-.3965-.8922-.89212-1.1895-.89212-1.1895-.69388-.4957.09912-.4957.09912-.4957.793.0992 1.1895.793 1.1895.793.69388 1.2887 1.88338.8922 2.27988.6939.09912-.4956.29737-.8921.49562-1.0904-1.78425-.1982-3.5685-.8921-3.5685-3.96496 0-.89212.29738-1.586.793-2.08162-.09912-.19825-.3965-.99125.09913-2.08163 0 0 .69387-.19825 2.18075.793.59475-.19825 1.28862-.29737 1.9825-.29737.69387 0 1.38775.09912 1.98249.29737 1.4869-.99125 2.1808-.793 2.1808-.793.3965 1.09038.1982 1.88338.0991 2.08163.4956.59475.793 1.28862.793 2.08162 0 3.07286-1.8834 3.66766-3.66764 3.86586.29737.3965.59474.8921.59474 1.586v2.1808c0 .1982.0991.4956.5948.3965 3.172-1.0904 5.4518-4.0642 5.4518-7.53353-.0991-4.3615-3.6676-7.930002-8.02909-7.930002z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="content-wrapper">
|
||||
<div class="content-area">
|
||||
|
||||
<rocket-drawer id="sidebar">
|
||||
<nav slot="content" id="sidebar-nav">
|
||||
|
||||
<a class="logo-link" href="/">
|
||||
<img src="/_merged_assets/logo.svg" alt="Rocket Logo" />
|
||||
<span>Rocket</span>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<rocket-navigation>
|
||||
<ul><li class="menu-item"><a href="/docs/configuration/">Configuration</a><ul><li class="menu-item"><a href="/docs/configuration/overview/">Overview</a><ul><li class="menu-item anchor"><a href="/docs/configuration/overview/#adding-rollup-plugins" class="anchor">Adding Rollup Plugins</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/configuration/overview/#modifying-options-of-plugins" class="anchor">Modifying Options of Plugins</a></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/configuration/computed-config/">Computed Config</a><ul><li class="menu-item anchor"><a href="/docs/configuration/computed-config/#set-your-own-data" class="anchor">Set Your Own Data</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/configuration/computed-config/#default-available-configs" class="anchor">Default Available Configs</a></li></ul></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/presets/">Presets</a><ul><li class="menu-item"><a href="/docs/presets/joining-blocks/">Joining Blocks</a><ul><li class="menu-item anchor"><a href="/docs/presets/joining-blocks/#adding-content-without-overriding" class="anchor">Adding content without overriding</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/presets/joining-blocks/#overriding-content" class="anchor">Overriding Content</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/presets/joining-blocks/#reordering-and-overriding" class="anchor">Reordering and Overriding</a></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/presets/launch/">Launch</a><ul><li class="menu-item anchor"><a href="/docs/presets/launch/#installation" class="anchor">Installation</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/presets/launch/#data" class="anchor">Data</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/presets/launch/#inline-notification" class="anchor">Inline Notification</a></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/presets/search/">Search</a><ul><li class="menu-item anchor"><a href="/docs/presets/search/#installation" class="anchor">Installation</a></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/presets/blog/">Blog</a><ul><li class="menu-item anchor"><a href="/docs/presets/blog/#installation" class="anchor">Installation</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/presets/blog/#usage" class="anchor">Usage</a></li></ul></li></ul></li>
|
||||
<li class="menu-item active"><a href="/docs/markdown-javascript/" class="active">Markdown JavaScript</a><ul><li class="menu-item current"><a href="/docs/markdown-javascript/overview/">Overview</a><ul><li class="menu-item anchor"><a href="/docs/markdown-javascript/overview/#web-components" class="anchor">Web Components</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/markdown-javascript/overview/#demo-support-story" class="anchor">Demo Support (Story)</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/markdown-javascript/overview/#supported-systems" class="anchor">Supported Systems</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/markdown-javascript/overview/#build-mdjs" class="anchor">Build mdjs</a></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/markdown-javascript/preview/">Preview</a></li>
|
||||
<li class="menu-item"><a href="/docs/markdown-javascript/story/">Story</a></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/eleventy-plugins/">Eleventy Plugins</a><ul><li class="menu-item"><a href="/docs/eleventy-plugins/mdjs-unified/">Markdown JavaScript (mdjs)</a><ul><li class="menu-item anchor"><a href="/docs/eleventy-plugins/mdjs-unified/#setup" class="anchor">Setup</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/eleventy-plugins/mdjs-unified/#configure-a-unified-or-remark-plugin-with-mdjs" class="anchor">Configure a unified or remark Plugin with mdjs</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/eleventy-plugins/mdjs-unified/#add-a-unified-or-remark-plugin" class="anchor">Add a unified or remark Plugin</a></li></ul></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/tools/">Tools</a><ul><li class="menu-item"><a href="/docs/tools/plugins-manager/">Plugins Manager</a><ul><li class="menu-item anchor"><a href="/docs/tools/plugins-manager/#problem" class="anchor">Problem</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/plugins-manager/#problem-statement" class="anchor">Problem Statement</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/plugins-manager/#solution" class="anchor">Solution</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/plugins-manager/#adding-a-plugin" class="anchor">Adding a Plugin</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/plugins-manager/#adjusting-plugin-options" class="anchor">Adjusting Plugin Options</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/plugins-manager/#converting-metaplugins-to-an-actual-plugin" class="anchor">Converting metaPlugins to an Actual Plugin</a></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/tools/rollup-config/">Rollup Config</a><ul><li class="menu-item anchor"><a href="/docs/tools/rollup-config/#features" class="anchor">Features</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/rollup-config/#setup" class="anchor">Setup</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/rollup-config/#customizations" class="anchor">Customizations</a></li></ul></li>
|
||||
<li class="menu-item"><a href="/docs/tools/check-html-links/">Check HTML Links</a><ul><li class="menu-item anchor"><a href="/docs/tools/check-html-links/#features" class="anchor">Features</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/check-html-links/#installation" class="anchor">Installation</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/check-html-links/#usage" class="anchor">Usage</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/check-html-links/#example-output" class="anchor">Example Output</a></li>
|
||||
<li class="menu-item anchor"><a href="/docs/tools/check-html-links/#comparison" class="anchor">Comparison</a></li></ul></li></ul></li></ul>
|
||||
<div class="sidebar-bottom">
|
||||
<hr>
|
||||
<launch-dark-switch class="light-dark-switch" label="Toggle darkmode">Toggle darkmode</launch-dark-switch>
|
||||
|
||||
|
||||
<a href="https://github.com/modernweb-dev/rocket/issues">Help and Feedback</a>
|
||||
</div>
|
||||
|
||||
</rocket-navigation>
|
||||
|
||||
|
||||
</nav>
|
||||
</rocket-drawer>
|
||||
|
||||
|
||||
|
||||
<main class="markdown-body">
|
||||
|
||||
<h1 id="markdown-javascript-overview"><a class="anchor" href="#markdown-javascript-overview"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Markdown JavaScript: Overview</h1>
|
||||
<p>Markdown JavaScript (mdjs) is a format that allows you to use JavaScript with Markdown, to create interactive demos. It does so by "annotating" JavaScript that should be executed in Markdown.</p>
|
||||
<p>To annotate we use a code block with <code>js script</code>.</p>
|
||||
<pre class="language-md"><code class="language-md"><span class="token code"><span class="token punctuation">```</span><span class="token code-language">js script</span>
|
||||
<span class="token code-block language-js"><span class="token comment">// execute me</span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<h2 id="web-components"><a class="anchor" href="#web-components"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Web Components</h2>
|
||||
<p>One very good use case for that can be web components.
|
||||
HTML already works in Markdown so all you need is to load a web components definition file.</p>
|
||||
<p>You could even do so within the same Markdown file.</p>
|
||||
<pre class="language-md"><code class="language-md"><span class="token title important"><span class="token punctuation">##</span> This is my-card</span>
|
||||
|
||||
Here's an example of the component:
|
||||
|
||||
<span class="token code"><span class="token punctuation">```</span><span class="token code-language">html preview-story</span>
|
||||
<span class="token code-block language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>my-card</span><span class="token punctuation">></span></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>Hello world!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span>Click me!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span>
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>my-card</span><span class="token punctuation">></span></span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<p>You can even execute some JavaScript:</p>
|
||||
<pre class="language-md"><code class="language-md"><span class="token title important"><span class="token punctuation">##</span> This is my-el</span>
|
||||
|
||||
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>my-el</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>my-el</span><span class="token punctuation">></span></span>
|
||||
|
||||
<span class="token code"><span class="token punctuation">```</span><span class="token code-language">js script</span>
|
||||
<span class="token code-block language-js"><span class="token keyword module">import</span> <span class="token punctuation">{</span> <span class="token maybe-class-name">LitElement</span><span class="token punctuation">,</span> html <span class="token punctuation">}</span> <span class="token keyword module">from</span> <span class="token string">'https://unpkg.com/lit-element?module'</span><span class="token punctuation">;</span>
|
||||
|
||||
<span class="token keyword">class</span> <span class="token class-name">MyEl</span> <span class="token keyword">extends</span> <span class="token class-name">LitElement</span> <span class="token punctuation">{</span>
|
||||
<span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
||||
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token property-access">innerHTML</span> <span class="token operator">=</span> <span class="token string">'<p style="color: red">I am alive</p>'</span><span class="token punctuation">;</span>
|
||||
<span class="token punctuation">}</span>
|
||||
<span class="token punctuation">}</span>
|
||||
|
||||
customElements<span class="token punctuation">.</span><span class="token method function property-access">define</span><span class="token punctuation">(</span><span class="token string">'my-el'</span><span class="token punctuation">,</span> <span class="token maybe-class-name">MyEl</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<h2 id="demo-support-story"><a class="anchor" href="#demo-support-story"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Demo Support (Story)</h2>
|
||||
<p>mdjs comes with some additional helpers you can choose to import:</p>
|
||||
<pre class="language-md"><code class="language-md"><span class="token code"><span class="token punctuation">```</span><span class="token code-language">js script</span>
|
||||
<span class="token code-block language-js"><span class="token keyword module">import</span> <span class="token string">'@mdjs/mdjs-story/mdjs-story.js'</span><span class="token punctuation">;</span>
|
||||
<span class="token keyword module">import</span> <span class="token string">'@mdjs/mdjs-preview/mdjs-preview.js'</span><span class="token punctuation">;</span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<p>Once loaded you can use them like so:</p>
|
||||
<pre class="language-md"><code class="language-md"><span class="token code"><span class="token punctuation">```</span><span class="token code-language">js script</span>
|
||||
<span class="token code-block language-js"><span class="token keyword module">import</span> <span class="token string">'@mdjs/mdjs-story/mdjs-story.js'</span><span class="token punctuation">;</span>
|
||||
<span class="token keyword module">import</span> <span class="token string">'@mdjs/mdjs-preview/mdjs-preview.js'</span><span class="token punctuation">;</span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<h3 id="story"><a class="anchor" href="#story"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Story</h3>
|
||||
<p>The code snippet will actually get executed at that place and you will have a live demo</p>
|
||||
<pre class="language-md"><code class="language-md"><span class="token code"><span class="token punctuation">```</span><span class="token code-language">js story</span>
|
||||
<span class="token code-block language-js"><span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">JsStory</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> html<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token embedded-code html"> <demo-wc-card>JS Story</demo-wc-card> </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<pre class="language-md"><code class="language-md"><span class="token code"><span class="token punctuation">```</span><span class="token code-language">html story</span>
|
||||
<span class="token code-block language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>demo-wc-card</span><span class="token punctuation">></span></span>HTML Story<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>demo-wc-card</span><span class="token punctuation">></span></span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<h4 id="full-code-support"><a class="anchor" href="#full-code-support"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Full Code Support</h4>
|
||||
<pre class="language-md"><code class="language-md"><span class="token code"><span class="token punctuation">```</span><span class="token code-language">js story</span>
|
||||
<span class="token code-block language-js"><span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">JsStory</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
|
||||
<span class="token keyword">const</span> calculateSomething <span class="token operator">=</span> <span class="token number">12</span><span class="token punctuation">;</span>
|
||||
<span class="token keyword">return</span> html<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token embedded-code html">
|
||||
<demo-wc-card .header=${`Something: ${calculateSomething}`}>JS Story</demo-wc-card>
|
||||
</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
|
||||
<span class="token punctuation">}</span><span class="token punctuation">;</span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<h3 id="preview-story"><a class="anchor" href="#preview-story"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Preview Story</h3>
|
||||
<p>Will become a live demo wrapped in a container with a show code button.</p>
|
||||
<pre class="language-md"><code class="language-md"><span class="token code"><span class="token punctuation">```</span><span class="token code-language">js preview-story</span>
|
||||
<span class="token code-block language-js"><span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">JsPreviewStory</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> html<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token embedded-code html"> <demo-wc-card>JS Preview Story</demo-wc-card> </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<pre class="language-md"><code class="language-md"><span class="token code"><span class="token punctuation">```</span><span class="token code-language">html preview-story</span>
|
||||
<span class="token code-block language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>demo-wc-card</span><span class="token punctuation">></span></span>HTML Preview Story<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>demo-wc-card</span><span class="token punctuation">></span></span></span>
|
||||
<span class="token punctuation">```</span></span>
|
||||
</code></pre>
|
||||
<p>Here is a live example from <a href="https://www.npmjs.com/package/demo-wc-card">demo-wc-card</a>.</p>
|
||||
<mdjs-preview mdjs-story-name="header"></mdjs-preview>
|
||||
<h2 id="supported-systems"><a class="anchor" href="#supported-systems"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Supported Systems</h2>
|
||||
<h3 id="es-dev-server"><a class="anchor" href="#es-dev-server"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>es-dev-server</h3>
|
||||
<p>Preview your mdjs readme with live demos and auto reload.</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Add to your <code>package.json</code>:</p>
|
||||
<pre class="language-json"><code class="language-json"><span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
|
||||
<span class="token property">"start"</span><span class="token operator">:</span> <span class="token string">"es-dev-server"</span><span class="token punctuation">,</span>
|
||||
<span class="token punctuation">}</span>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Create a <code>es-dev-server.config.js</code> in the root of your repository.</p>
|
||||
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">{</span> mdjsTransformer <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@mdjs/core'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
|
||||
module<span class="token punctuation">.</span><span class="token property-access">exports</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
|
||||
nodeResolve<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
|
||||
open<span class="token punctuation">:</span> <span class="token string">'README.md'</span><span class="token punctuation">,</span>
|
||||
watch<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
|
||||
responseTransformers<span class="token punctuation">:</span> <span class="token punctuation">[</span>mdjsTransformer<span class="token punctuation">]</span><span class="token punctuation">,</span>
|
||||
<span class="token punctuation">}</span><span class="token punctuation">;</span>
|
||||
</code></pre>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 id="storybook"><a class="anchor" href="#storybook"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Storybook</h3>
|
||||
<p>Please check out <a href="https://open-wc.org/demoing/">@open-wc/demoing-storybook</a> for a fully integrated setup.</p>
|
||||
<p>It includes <a href="https://open-wc.org/demoing/storybook-addon-markdown-docs.html">storybook-addon-markdown-docs</a> which uses mdjs under the hood.</p>
|
||||
<h3 id="chrome-extension-currently-only-for-github"><a class="anchor" href="#chrome-extension-currently-only-for-github"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Chrome Extension (currently only for GitHub)</h3>
|
||||
<p>See live demos directly inside GitHub pages, Markdown files, issues, pull requests...</p>
|
||||
<p>Please check out <a href="https://github.com/open-wc/mdjs-viewer">mdjs-viewer</a>.</p>
|
||||
<h2 id="build-mdjs"><a class="anchor" href="#build-mdjs"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Build mdjs</h2>
|
||||
<h3 id="basic"><a class="anchor" href="#basic"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Basic</h3>
|
||||
<p>mdjs offers two more "basic" integrations</p>
|
||||
<h4 id="mdjsdocpage"><a class="anchor" href="#mdjsdocpage"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><code>mdjsDocPage</code></h4>
|
||||
<p>Creates a full blown HTML page by passing in the Markdown.</p>
|
||||
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">{</span> mdjsDocPage <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@mdjs/core'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
|
||||
<span class="token keyword">const</span> page <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">mdjsDocPage</span><span class="token punctuation">(</span>markdownString<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token comment">/*
|
||||
<html>
|
||||
... // load styles/components for mdjs, start stories
|
||||
<body>
|
||||
<h1>Some Markdown</h1>
|
||||
</body>
|
||||
</html>
|
||||
*/</span>
|
||||
</code></pre>
|
||||
<h4 id="mdjsprocess"><a class="anchor" href="#mdjsprocess"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><code>mdjsProcess</code></h4>
|
||||
<p>Pass in multiple Markdown documents and you get back all the JavaScript code and rendered HTML.</p>
|
||||
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">{</span> mdjsProcess <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@mdjs/core'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
|
||||
<span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">mdjsProcess</span><span class="token punctuation">(</span>markdownString<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token console class-name">console</span><span class="token punctuation">.</span><span class="token method function property-access">log</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token comment">/*
|
||||
{
|
||||
jsCode: "
|
||||
import '@mdjs/mdjs-story/mdjs-story.js';
|
||||
...
|
||||
",
|
||||
html: '<h1>Markdown One</h1>',
|
||||
}
|
||||
*/</span>
|
||||
</code></pre>
|
||||
<h3 id="advanced"><a class="anchor" href="#advanced"><svg class="octicon octicon-link" viewBox="0 0 16 16" aria-hidden="true" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Advanced</h3>
|
||||
<p>mdjs is build to be integrated within the <a href="https://unifiedjs.com/">unifiedjs</a> system.</p>
|
||||
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> unified <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'unified'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token keyword">const</span> markdown <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'remark-parse'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token keyword">const</span> htmlStringify <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'remark-html'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token keyword">const</span> mdjsParse <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@mdjs/core'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
|
||||
<span class="token keyword">const</span> parser <span class="token operator">=</span> <span class="token function">unified</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token method function property-access">use</span><span class="token punctuation">(</span>markdown<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token method function property-access">use</span><span class="token punctuation">(</span>mdjsParse<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token method function property-access">use</span><span class="token punctuation">(</span>htmlStringify<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token keyword">await</span> parser<span class="token punctuation">.</span><span class="token method function property-access">process</span><span class="token punctuation">(</span>body<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token keyword">const</span> <span class="token punctuation">{</span> jsCode <span class="token punctuation">}</span> <span class="token operator">=</span> result<span class="token punctuation">.</span><span class="token property-access">data</span><span class="token punctuation">;</span>
|
||||
<span class="token console class-name">console</span><span class="token punctuation">.</span><span class="token method function property-access">log</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span><span class="token property-access">contents</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token comment">// <h1>This is my-el></h1></span>
|
||||
<span class="token comment">// <my-el></my-el></span>
|
||||
<span class="token console class-name">console</span><span class="token punctuation">.</span><span class="token method function property-access">log</span><span class="token punctuation">(</span>jsCode<span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||||
<span class="token comment">// customElements.define('my-el', class extends HTMLElement {</span>
|
||||
<span class="token comment">// ...</span>
|
||||
</code></pre>
|
||||
<script type="module">
|
||||
import '@mdjs/mdjs-story/mdjs-story.js';
|
||||
import '@mdjs/mdjs-preview/mdjs-preview.js';
|
||||
import { html } from 'lit-html';
|
||||
import 'demo-wc-card/demo-wc-card.js';
|
||||
export const header = () => {
|
||||
return html`<demo-wc-card .header=${'my new header'}></demo-wc-card>`;
|
||||
};
|
||||
const rootNode = document;
|
||||
const stories = [{ key: 'header', story: header, code: `<pre class="language-js"><code class="language-js"><span class="token keyword module">import</span> <span class="token string">'demo-wc-card/demo-wc-card.js'</span><span class="token punctuation">;</span>
|
||||
<span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function">header</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
|
||||
<span class="token keyword">return</span> html<span class="token template-string"><span class="token template-punctuation string">\`</span><span class="token html language-html"> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>demo-wc-card</span> <span class="token attr-name">.header</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">\${</span><span class="token string">'my new header'</span><span class="token interpolation-punctuation punctuation">}</span></span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>demo-wc-card</span><span class="token punctuation">></span></span> </span><span class="token template-punctuation string">\`</span></span><span class="token punctuation">;</span>
|
||||
<span class="token punctuation">}</span><span class="token punctuation">;</span>
|
||||
</code></pre>` }];
|
||||
for (const story of stories) {
|
||||
const storyEl = rootNode.querySelector(`[mdjs-story-name="${story.key}"]`);
|
||||
storyEl.codeHasHtml = true;
|
||||
storyEl.story = story.story;
|
||||
storyEl.code = story.code;
|
||||
};
|
||||
if (!customElements.get('mdjs-preview')) { import('@mdjs/mdjs-preview/mdjs-preview.js'); }
|
||||
if (!customElements.get('mdjs-story')) { import('@mdjs/mdjs-story/mdjs-story.js'); }
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<div class="content-footer">
|
||||
<p>
|
||||
Caught a mistake or want to contribute to the documentation?
|
||||
<a href="https://github.com/modernweb-dev/rocket/edit/main/./docs/docs/markdown-javascript/overview.md">Edit this page on GitHub!</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<footer id="main-footer">
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="footer-menu">
|
||||
<div class="content-area">
|
||||
|
||||
<nav>
|
||||
<h3>Discover</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="/blog/">Blog</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="https://github.com/modernweb-dev/rocket/issues">Help and Feedback</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<nav>
|
||||
<h3>Follow</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="https://github.com/modernweb-dev/rocket">GitHub</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="https://twitter.com/modern_web_dev">Twitter</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/about/slack/">Slack</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<nav>
|
||||
<h3>Support</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="/about/sponsor/">Sponsor</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="https://github.com/modernweb-dev/rocket/blob/main/CONTRIBUTING.md">Contribute</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="module">
|
||||
import '@rocket/navigation/rocket-navigation.js';
|
||||
import '@rocket/drawer/rocket-drawer.js';
|
||||
const drawer = document.querySelector('#sidebar');
|
||||
|
||||
// Toggle button
|
||||
const triggers = document.querySelectorAll('[data-action="trigger-mobile-menu"]');
|
||||
for (const trigger of [...triggers]) {
|
||||
trigger.addEventListener('click', function () {
|
||||
drawer.opened = true;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
async function serviceWorkerUpdate() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
const oldReg = await navigator.serviceWorker.getRegistration();
|
||||
let oldSwState;
|
||||
if (oldReg && oldReg.active) {
|
||||
oldSwState = oldReg.active.state;
|
||||
}
|
||||
|
||||
let refreshing;
|
||||
|
||||
navigator.serviceWorker.addEventListener('controllerchange', async () => {
|
||||
if (refreshing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newReg = await navigator.serviceWorker.getRegistration();
|
||||
let newSwState;
|
||||
if (newReg && newReg.active) {
|
||||
newSwState = newReg.active.state;
|
||||
}
|
||||
|
||||
if (oldSwState === 'activated' && newSwState === 'activating') {
|
||||
refreshing = true;
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
serviceWorkerUpdate();
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,4 @@
|
||||
import { html, render } from 'lit-html';
|
||||
import '../components/test-component.js';
|
||||
|
||||
render(html`<test-element></test-element>`, document.body);
|
||||
24
packages/generate-import-map/test-node/inspectFolder.test.js
Normal file
24
packages/generate-import-map/test-node/inspectFolder.test.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import chai from 'chai';
|
||||
import { execute } from './test-helpers.js';
|
||||
|
||||
const { expect } = chai;
|
||||
|
||||
describe('inspectFolder', () => {
|
||||
it.skip('can handle script src', async () => {
|
||||
const { localSpecifiers, bareSpecifiers } = await execute('fixtures/script-src');
|
||||
expect(localSpecifiers).lengthOf(1);
|
||||
expect(bareSpecifiers).lengthOf(0);
|
||||
});
|
||||
|
||||
it.skip('can handle script content', async () => {
|
||||
const { localSpecifiers, bareSpecifiers } = await execute('fixtures/script-content');
|
||||
expect(localSpecifiers).lengthOf(1);
|
||||
expect(bareSpecifiers).lengthOf(0);
|
||||
});
|
||||
|
||||
it('can handle multiple levels', async () => {
|
||||
const { localSpecifiers, bareSpecifiers } = await execute('fixtures/test-case');
|
||||
expect(localSpecifiers).lengthOf(3);
|
||||
expect(bareSpecifiers).lengthOf(2);
|
||||
});
|
||||
});
|
||||
11
packages/generate-import-map/test-node/test-helpers.js
Normal file
11
packages/generate-import-map/test-node/test-helpers.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { inspectFolder } from 'generate-import-map';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export async function execute(inPath) {
|
||||
const testDir = path.join(__dirname, inPath.split('/').join(path.sep));
|
||||
return await inspectFolder(testDir);
|
||||
}
|
||||
24
packages/generate-import-map/tsconfig.json
Normal file
24
packages/generate-import-map/tsconfig.json
Normal file
@@ -0,0 +1,24 @@
|
||||
// Don't edit this file directly. It is generated by /scripts/update-package-configs.ts
|
||||
|
||||
{
|
||||
"extends": "../../tsconfig.node-base.json",
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"outDir": "./dist-types",
|
||||
"rootDir": ".",
|
||||
"composite": true,
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"emitDeclarationOnly": true
|
||||
},
|
||||
"references": [],
|
||||
"include": [
|
||||
"src",
|
||||
"*.js",
|
||||
"types"
|
||||
],
|
||||
"exclude": [
|
||||
"dist",
|
||||
"dist-types"
|
||||
]
|
||||
}
|
||||
10
packages/generate-import-map/types/main.d.ts
vendored
Normal file
10
packages/generate-import-map/types/main.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export interface Script {
|
||||
specifier: string;
|
||||
content: string;
|
||||
filePath: string;
|
||||
}
|
||||
|
||||
export interface Import {
|
||||
s: number;
|
||||
e: number;
|
||||
}
|
||||
@@ -1,17 +1,5 @@
|
||||
# @rocket/launch
|
||||
|
||||
## 0.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 2b7f1ee: Add support for pathprefix
|
||||
|
||||
## 0.4.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 81edf45: Reduce the amount of js files in the build by avoiding inline script tags
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/launch",
|
||||
"version": "0.4.2",
|
||||
"version": "0.4.0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -35,7 +35,7 @@
|
||||
"preset"
|
||||
],
|
||||
"dependencies": {
|
||||
"@rocket/drawer": "^0.1.3",
|
||||
"@rocket/navigation": "^0.2.1"
|
||||
"@rocket/drawer": "^0.1.2",
|
||||
"@rocket/navigation": "^0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,17 @@
|
||||
<script type="module" src="{{ '/_assets/scripts/init-navigation.js' | asset | url }}"></script>
|
||||
{#
|
||||
src leads to the file not being included/executed? bug in rollup-plugin-html?
|
||||
<script type="module" src="{{ '/_assets/scripts/init-navigation.js' | asset }}"></script>
|
||||
#}
|
||||
<script type="module">
|
||||
import '@rocket/navigation/rocket-navigation.js';
|
||||
import '@rocket/drawer/rocket-drawer.js';
|
||||
const drawer = document.querySelector('#sidebar');
|
||||
|
||||
// Toggle button
|
||||
const triggers = document.querySelectorAll('[data-action="trigger-mobile-menu"]');
|
||||
for (const trigger of [...triggers]) {
|
||||
trigger.addEventListener('click', function () {
|
||||
drawer.opened = true;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<meta property="og:site_name" content="{{ site.name }}"/>
|
||||
<meta property="og:type" content="website"/>
|
||||
|
||||
<meta property="og:image" content="{{ socialMediaImage | url }}"/>
|
||||
<meta property="og:url" content="{{ page.url | url }}"/>
|
||||
<meta property="og:image" content="{{ socialMediaImage }}"/>
|
||||
<meta property="og:url" content="{{ page.url }}"/>
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image"/>
|
||||
|
||||
@@ -208,13 +208,19 @@ describe('RocketLaunch preset', () => {
|
||||
' </div>',
|
||||
' </footer>',
|
||||
'',
|
||||
' <script type="module" src="/_merged_assets/scripts/init-navigation.js"></script>',
|
||||
' <script type="module">',
|
||||
' import "@rocket/navigation/rocket-navigation.js";',
|
||||
' import "@rocket/drawer/rocket-drawer.js";',
|
||||
' const drawer = document.querySelector("#sidebar");',
|
||||
'',
|
||||
' <script',
|
||||
' type="module"',
|
||||
' inject-service-worker=""',
|
||||
' src="/_merged_assets/scripts/registerServiceWorker.js"',
|
||||
' ></script>',
|
||||
' // Toggle button',
|
||||
` const triggers = document.querySelectorAll('[data-action="trigger-mobile-menu"]');`,
|
||||
' for (const trigger of [...triggers]) {',
|
||||
' trigger.addEventListener("click", function () {',
|
||||
' drawer.opened = true;',
|
||||
' });',
|
||||
' }',
|
||||
' </script>',
|
||||
' </body>',
|
||||
'</html>',
|
||||
].join('\n'),
|
||||
@@ -437,13 +443,19 @@ describe('RocketLaunch preset', () => {
|
||||
' </div>',
|
||||
' </footer>',
|
||||
'',
|
||||
' <script type="module" src="/_merged_assets/scripts/init-navigation.js"></script>',
|
||||
' <script type="module">',
|
||||
' import "@rocket/navigation/rocket-navigation.js";',
|
||||
' import "@rocket/drawer/rocket-drawer.js";',
|
||||
' const drawer = document.querySelector("#sidebar");',
|
||||
'',
|
||||
' <script',
|
||||
' type="module"',
|
||||
' inject-service-worker=""',
|
||||
' src="/_merged_assets/scripts/registerServiceWorker.js"',
|
||||
' ></script>',
|
||||
' // Toggle button',
|
||||
` const triggers = document.querySelectorAll('[data-action="trigger-mobile-menu"]');`,
|
||||
' for (const trigger of [...triggers]) {',
|
||||
' trigger.addEventListener("click", function () {',
|
||||
' drawer.opened = true;',
|
||||
' });',
|
||||
' }',
|
||||
' </script>',
|
||||
' </body>',
|
||||
'</html>',
|
||||
].join('\n'),
|
||||
|
||||
@@ -1,26 +1,5 @@
|
||||
# Change Log
|
||||
|
||||
## 0.7.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 2b7f1ee: Add support for pathprefix
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- a8e66d8: Extract building of the JavaScript setup code into a unified plugin called mdjsSetupCode
|
||||
- fe6a929: For the story preview keep the original code block around to get code highlighting from the main document. This enables styling and reduces the code complexity.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a8e66d8: You can provide a highlightCode function to the mdjsSetupCode unified plugin
|
||||
- Updated dependencies [edb1abf]
|
||||
- Updated dependencies [604a80e]
|
||||
- @mdjs/mdjs-preview@0.4.0
|
||||
- @mdjs/mdjs-story@0.2.0
|
||||
|
||||
## 0.6.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mdjs/core",
|
||||
"version": "0.7.1",
|
||||
"version": "0.6.2",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -43,12 +43,12 @@
|
||||
"remark"
|
||||
],
|
||||
"dependencies": {
|
||||
"@mdjs/mdjs-preview": "^0.4.2",
|
||||
"@mdjs/mdjs-story": "^0.2.0",
|
||||
"@mdjs/mdjs-preview": "^0.3.0",
|
||||
"@mdjs/mdjs-story": "^0.1.0",
|
||||
"@types/unist": "^2.0.3",
|
||||
"es-module-lexer": "^0.3.26",
|
||||
"github-markdown-css": "^4.0.0",
|
||||
"plugins-manager": "^0.2.1",
|
||||
"plugins-manager": "^0.2.0",
|
||||
"rehype-autolink-headings": "^5.0.1",
|
||||
"rehype-prism-template": "^0.4.1",
|
||||
"rehype-raw": "^5.0.0",
|
||||
|
||||
@@ -18,7 +18,6 @@ const { executeSetupFunctions } = require('plugins-manager');
|
||||
|
||||
const { mdjsParse } = require('./mdjsParse.js');
|
||||
const { mdjsStoryParse } = require('./mdjsStoryParse.js');
|
||||
const { mdjsSetupCode } = require('./mdjsSetupCode.js');
|
||||
|
||||
/** @type {MdjsProcessPlugin[]} */
|
||||
const defaultMetaPlugins = [
|
||||
@@ -26,7 +25,6 @@ const defaultMetaPlugins = [
|
||||
{ name: 'gfm', plugin: gfm },
|
||||
{ name: 'mdjsParse', plugin: mdjsParse },
|
||||
{ name: 'mdjsStoryParse', plugin: mdjsStoryParse },
|
||||
{ name: 'mdjsSetupCode', plugin: mdjsSetupCode },
|
||||
// @ts-ignore
|
||||
{ name: 'remark2rehype', plugin: remark2rehype, options: { allowDangerousHtml: true } },
|
||||
// @ts-ignore
|
||||
@@ -52,15 +50,29 @@ const defaultMetaPlugins = [
|
||||
* @param {function[]} [options.setupUnifiedPlugins]
|
||||
* @param {MdjsProcessPlugin[]} [options.plugins] deprecated option use setupUnifiedPlugins instead
|
||||
*/
|
||||
async function mdjsProcess(mdjs, { setupUnifiedPlugins = [] } = {}) {
|
||||
async function mdjsProcess(
|
||||
mdjs,
|
||||
{ rootNodeQueryCode = 'document', setupUnifiedPlugins = [] } = {},
|
||||
) {
|
||||
const parser = unified();
|
||||
|
||||
const metaPlugins = executeSetupFunctions(setupUnifiedPlugins, defaultMetaPlugins);
|
||||
|
||||
/**
|
||||
* @param {string} code
|
||||
*/
|
||||
async function highlightCode(code) {
|
||||
// @ts-ignore
|
||||
for (const pluginObj of metaPlugins) {
|
||||
parser.use(pluginObj.plugin, pluginObj.options);
|
||||
}
|
||||
|
||||
/** @type {unknown} */
|
||||
const parseResult = await parser.process(mdjs);
|
||||
const result = /** @type {ParseResult} */ (parseResult);
|
||||
|
||||
const { stories, jsCode } = result.data;
|
||||
let fullJsCode = jsCode;
|
||||
|
||||
if (stories && stories.length > 0) {
|
||||
const storiesCode = stories.map(story => story.code).join('\n');
|
||||
|
||||
// @ts-ignore
|
||||
const codePlugins = metaPlugins.filter(pluginObj =>
|
||||
['markdown', 'remark2rehype', 'rehypePrism', 'htmlStringify'].includes(pluginObj.name),
|
||||
@@ -70,30 +82,46 @@ async function mdjsProcess(mdjs, { setupUnifiedPlugins = [] } = {}) {
|
||||
for (const pluginObj of codePlugins) {
|
||||
codeParser.use(pluginObj.plugin, pluginObj.options);
|
||||
}
|
||||
const codeResult = await codeParser.process(code);
|
||||
return codeResult.contents;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
for (const pluginObj of metaPlugins) {
|
||||
if (pluginObj.name === 'mdjsSetupCode') {
|
||||
if (pluginObj.options && !pluginObj.options.highlightCode) {
|
||||
pluginObj.options.highlightCode = highlightCode;
|
||||
}
|
||||
if (!pluginObj.options) {
|
||||
pluginObj.options = { highlightCode };
|
||||
const invokeStoriesCode = [];
|
||||
for (const story of stories) {
|
||||
let code = '';
|
||||
switch (story.type) {
|
||||
case 'html':
|
||||
code = `\`\`\`html\n${story.code.split('`')[1]}\n\`\`\``;
|
||||
break;
|
||||
case 'js':
|
||||
code = `\`\`\`js\n${story.code}\n\`\`\``;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const codeResult = await codeParser.process(code);
|
||||
const highlightedCode = /** @type {string} */ (codeResult.contents)
|
||||
.replace(/`/g, '\\`')
|
||||
.replace(/\$/g, '\\$');
|
||||
invokeStoriesCode.push(
|
||||
`{ key: '${story.key}', story: ${story.key}, code: \`${highlightedCode}\` }`,
|
||||
);
|
||||
}
|
||||
parser.use(pluginObj.plugin, pluginObj.options);
|
||||
|
||||
fullJsCode = [
|
||||
jsCode,
|
||||
storiesCode,
|
||||
`const rootNode = ${rootNodeQueryCode};`,
|
||||
`const stories = [${invokeStoriesCode.join(', ')}];`,
|
||||
`for (const story of stories) {`,
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
' const storyEl = rootNode.querySelector(`[mdjs-story-name="${story.key}"]`);',
|
||||
` storyEl.codeHasHtml = true;`,
|
||||
` storyEl.story = story.story;`,
|
||||
` storyEl.code = story.code;`,
|
||||
`};`,
|
||||
`if (!customElements.get('mdjs-preview')) { import('@mdjs/mdjs-preview/mdjs-preview.js'); }`,
|
||||
`if (!customElements.get('mdjs-story')) { import('@mdjs/mdjs-story/mdjs-story.js'); }`,
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
/** @type {unknown} */
|
||||
const parseResult = await parser.process(mdjs);
|
||||
const result = /** @type {ParseResult} */ (parseResult);
|
||||
|
||||
const { stories, setupJsCode } = result.data;
|
||||
|
||||
return { stories, jsCode: setupJsCode, html: result.contents };
|
||||
return { stories, jsCode: fullJsCode, html: result.contents };
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
const path = require('path');
|
||||
const slash = require('slash');
|
||||
|
||||
/** @typedef {import('vfile').VFileOptions} VFileOptions */
|
||||
/** @typedef {import('unist').Node} Node */
|
||||
/** @typedef {import('@mdjs/core/types/code').Story} Story */
|
||||
|
||||
/**
|
||||
* @typedef {Object} simulationSettings
|
||||
* @property {string} [simulatorUrl]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} rocketConfig
|
||||
* @property {string} [pathPrefix]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
* @param {string} [options.rootNodeQueryCode]
|
||||
* @param {simulationSettings} [options.simulationSettings]
|
||||
* @param {rocketConfig} [options.rocketConfig]
|
||||
* @returns
|
||||
*/
|
||||
function mdjsSetupCode({
|
||||
rootNodeQueryCode = 'document',
|
||||
simulationSettings = {},
|
||||
rocketConfig = {},
|
||||
} = {}) {
|
||||
if (rocketConfig && rocketConfig.pathPrefix) {
|
||||
if (simulationSettings && simulationSettings.simulatorUrl) {
|
||||
const { simulatorUrl } = simulationSettings;
|
||||
if (simulatorUrl[0] === '/' && !simulatorUrl.startsWith(rocketConfig.pathPrefix)) {
|
||||
simulationSettings.simulatorUrl = slash(
|
||||
path.join(rocketConfig.pathPrefix, simulationSettings.simulatorUrl),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} tree
|
||||
* @param {VFileOptions} file
|
||||
*/
|
||||
async function transformer(tree, file) {
|
||||
const { stories, jsCode } = file.data;
|
||||
|
||||
file.data.setupJsCode = jsCode;
|
||||
|
||||
if (stories && stories.length > 0) {
|
||||
const storiesCode = stories.map(/** @param {Story} story */ story => story.code).join('\n');
|
||||
|
||||
const invokeStoriesCode = [];
|
||||
for (const story of stories) {
|
||||
invokeStoriesCode.push(`{ key: '${story.key}', story: ${story.key} }`);
|
||||
}
|
||||
|
||||
file.data.setupJsCode = [
|
||||
'/** script code **/',
|
||||
jsCode,
|
||||
'/** stories code **/',
|
||||
storiesCode,
|
||||
'/** stories setup code **/',
|
||||
`const rootNode = ${rootNodeQueryCode};`,
|
||||
`const stories = [${invokeStoriesCode.join(', ')}];`,
|
||||
'let needsMdjsElements = false;',
|
||||
`for (const story of stories) {`,
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
' const storyEl = rootNode.querySelector(`[mdjs-story-name="${story.key}"]`);',
|
||||
' if (storyEl) {',
|
||||
` storyEl.story = story.story;`,
|
||||
` storyEl.key = story.key;`,
|
||||
` needsMdjsElements = true;`,
|
||||
` Object.assign(storyEl, ${JSON.stringify(simulationSettings)});`,
|
||||
' }',
|
||||
`};`,
|
||||
'if (needsMdjsElements) {',
|
||||
` if (!customElements.get('mdjs-preview')) { import('@mdjs/mdjs-preview/define'); }`,
|
||||
` if (!customElements.get('mdjs-story')) { import('@mdjs/mdjs-story/define'); }`,
|
||||
'}',
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
return transformer;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mdjsSetupCode,
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user