Compare commits

...

52 Commits

Author SHA1 Message Date
Benny Powers
5c3eda35a9 Merge pull request #191 from modernweb-dev/changeset-release/main
Version Packages
2021-07-04 22:57:22 +03:00
github-actions[bot]
6910d50bf5 Version Packages 2021-07-04 19:47:35 +00:00
Dani Garcia
a2dc8656db chore: improve wording in getting-started.md (#196) 2021-07-04 21:46:26 +02:00
Benny Powers
e778cd8a3c Update 30-collection-header.njk
fixes #189
2021-07-04 21:45:21 +02:00
Thomas Allmer
9e3c2f52d9 fix(launch): create help & feedback link only if site.helpUrl is defined 2021-07-04 18:21:19 +02:00
Thomas Allmer
579e8e72a2 fix(cli): Unordered joiningBlocks should generally end up at the end 2021-07-04 16:50:11 +02:00
Thomas Allmer
06ae8693b2 docs: add info that a server needs to handle the 404.html file 2021-07-04 16:50:07 +02:00
Thomas Allmer
cee2b7b04c fix(launch): fix font variables 2021-07-04 16:49:40 +02:00
Thomas Allmer
9625b94d39 fix(launch): remove footer urls that require user creation 2021-07-04 16:48:44 +02:00
Benny Powers
1f79d7a047 feat(launch): move font-family to variables 2021-07-04 12:00:31 +02:00
Benny Powers
bf99541951 fix(cli): copy all static assets on build 2021-07-04 12:00:14 +02:00
github-actions[bot]
8df9a3e9c3 Version Packages 2021-07-02 13:42:36 +02:00
Benny Powers
1b9559f2a5 feat(cli): add async before11ty hook (#183) 2021-07-02 11:58:54 +02:00
github-actions[bot]
8eede4b16b Version Packages 2021-06-30 15:24:07 +02:00
Thomas Allmer
2294ccf4a2 chore: only release patch versions 2021-06-30 15:20:51 +02:00
Benny Powers
3b1a0cf26a feat(cli): expose checkLinks options 2021-06-30 15:18:36 +02:00
Benny Powers
cf442215a9 feat: add slack invite 2021-06-30 15:02:33 +02:00
Thomas Allmer
41049f3908 chore: fix launch tests 2021-06-30 14:36:54 +02:00
Thomas Allmer
2b5c61d19c feat: no responsive images for svgs & option to define ignores 2021-06-30 14:36:54 +02:00
Jorge del Casar
f5d349e256 feat(launch): load used fonts from google fonts 2021-06-28 21:00:13 +02:00
Jorge del Casar
ce0b00e7a1 fix(cli): don't transform external images
Fix #141
2021-06-28 20:59:28 +02:00
github-actions[bot]
83286a99de Version Packages 2021-06-22 18:42:00 +02:00
Thijs Louisse
6cabdba5f6 feat(rocket): upgrade to lit2 2021-06-22 18:27:19 +02:00
github-actions[bot]
f5f2d69d0c Version Packages 2021-06-22 15:00:26 +02:00
Thomas Allmer
795a3613af fix(cli): service worker url respects pathPrefix 2021-06-22 14:57:52 +02:00
github-actions[bot]
bcf8f4fe83 Version Packages 2021-06-21 16:25:40 +02:00
Thomas Allmer
5330740cb3 fix(cli): replace images to be responsive from the bottom up 2021-06-21 16:20:48 +02:00
Thomas Allmer
2edd61beaa chore: remove image hashes from tests 2021-06-21 15:56:41 +02:00
github-actions[bot]
2a5fc08f35 Version Packages 2021-06-21 14:37:07 +02:00
Thomas Allmer
43a7ca10c3 fix(cli): responsive images need to respect pathPrefix 2021-06-21 14:35:51 +02:00
github-actions[bot]
da39fa72f3 Version Packages 2021-06-16 09:08:08 +02:00
Thomas Allmer
a0e8edfbb9 fix(check-html-links): ignore not http schema urls 2021-06-16 09:04:05 +02:00
Thomas Allmer
50434293bb fix(check-html-links): ignore tel links 2021-06-16 09:04:05 +02:00
Thomas Allmer
f08f92615b fix(check-html-links): add missing slash dependency 2021-06-16 09:04:05 +02:00
Thomas Allmer
1949b1e1cb fix(check-html-links): ignore html encoded mailto links 2021-06-16 09:04:05 +02:00
github-actions[bot]
340bf8e653 Version Packages 2021-06-11 17:56:06 +02:00
Thomas Allmer
eae200708d feat: update to mdjs version with lit 2 and render to light dom 2021-06-11 17:52:15 +02:00
github-actions[bot]
f707f636fa Version Packages 2021-06-11 13:15:48 +02:00
Thomas Allmer
814b5d29ad feat: render mdjs stories to light dom 2021-06-11 13:03:24 +02:00
Thomas Allmer
e1e96acceb feat: update mdjs to lit 2021-06-11 13:03:24 +02:00
github-actions[bot]
7543a129cf Version Packages 2021-06-08 22:28:18 +02:00
Thomas Allmer
60e85a17a7 fix: support picture tags with <source srset="..."> 2021-06-08 08:56:43 +02:00
github-actions[bot]
fd8f97859a Version Packages 2021-05-30 15:30:38 +02:00
Thomas Allmer
56fdb0cbd4 fix(plugins-manager): fix types for optional parameters 2021-05-30 15:27:44 +02:00
github-actions[bot]
e6d9c74510 Version Packages 2021-05-28 09:13:38 +02:00
Maarten Stolte
c338696482 chore: add changeset 2021-05-28 09:10:47 +02:00
Maarten Stolte
2ff4b4c542 chore: updated yarn.lock 2021-05-28 09:10:47 +02:00
Maarten Stolte
ba64b45ebf fix: update puppeteer to support M1 2021-05-28 09:10:47 +02:00
Maarten Stolte
e437e02cb9 fix(cli): Update eleventy-img to get M1 support 2021-05-28 09:10:47 +02:00
Thomas Allmer
ce9b12edd4 fix(mdjs-core): support importing via es module 2021-05-28 09:05:25 +02:00
github-actions[bot]
d034f799c0 Version Packages 2021-05-17 21:56:56 +02:00
Thomas Allmer
8bba4a88c8 feat: support for generating responsive images 2021-05-17 21:52:02 +02:00
118 changed files with 2502 additions and 329 deletions

View File

@@ -9,6 +9,11 @@ module.exports = async function () {
name: 'GitHub', name: 'GitHub',
url: 'https://github.com/modernweb-dev/rocket', url: 'https://github.com/modernweb-dev/rocket',
}, },
{
name: 'Slack',
url:
'https://join.slack.com/t/lit-and-friends/shared_invite/zt-llwznvsy-LZwT13R66gOgnrg12PUGqw',
},
], ],
gitSiteUrl: 'https://github.com/modernweb-dev/rocket', gitSiteUrl: 'https://github.com/modernweb-dev/rocket',
gitBranch: 'main', gitBranch: 'main',

View File

@@ -1,11 +1,3 @@
<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 name="twitter:creator" content="@modern_web_dev" />
<link rel="stylesheet" href="{{ '/_assets/body.css' | asset | url }}" mdjs-use> <link rel="stylesheet" href="{{ '/_assets/body.css' | asset | url }}" mdjs-use>

View File

@@ -0,0 +1,299 @@
# Configuration >> Images ||40
Rocket does handle content images automatically by
- producing multiple sizes so users download images that are meant for their resolution
- outputting multiple formats so the device can choose the best image format it supports
And the best thing about is you don't need to do anything.
## Usage
If you are using markdown images you are good to go.
```md
![My Image](path/to/image.jpg)
```
will result in
```html
<picture>
<source
type="image/avif"
srcset="/images/5f03d82-300.avif 300w, /images/5f03d82-820.avif 820w"
sizes="(min-width: 1024px) 820px, calc(100vw - 20px)"
/>
<source
type="image/jpeg"
srcset="/images/5f03d82-300.jpeg 300w, /images/5f03d82-820.jpeg 820w"
sizes="(min-width: 1024px) 820px, calc(100vw - 20px)"
/>
<img
alt="My Image"
rocket-image="responsive"
src="/images/5f03d82-300.jpeg"
width="300"
height="158"
loading="lazy"
decoding="async"
/>
</picture>
```
## Benefits
The main benefit is that we can serve the correct size and optimal image format depending on the browser capabilities leading to optimal loading times on different systems.
- Smaller images for smaller screens
When providing `srcset` and `sizes` the browser can decide which image makes the most sense to download.
This will lead to much faster websites especially on mobile where smaller images can be served.
If you wanna know more check out [The anatomy of responsive images](https://jakearchibald.com/2015/anatomy-of-responsive-images/).
- Serve the best/smallest image format the browser understands
There are currently ~3 formats you may want to consider `avif`, `webp` and `jpg`. The improvements are huge [webp is ~30% and avif ~50%](https://www.ctrl.blog/entry/webp-avif-comparison.html) smaller then the original jpg.
## Adding a caption
If you want to describe your image in more detail you can add a caption
```md
![My Image](path/to/image.jpg 'My caption text')
```
will result in
```html
<figure>
<picture>
<!-- picture code the same as above -->
</picture>
<figcaption>My caption text</figcaption>
</figure>
```
## Adjusting options
Under the hood it is using [11ty/image](https://www.11ty.dev/docs/plugins/image/) and all it's options are available.
<inline-notification type="tip">
If you are using a layout preset like `@rocket/launch` then you probably don't want to touch/change these options as the preset will set it for you accordion to its layout needs.
The default preset for regular markdown content is available as `responsive`.
</inline-notification>
👉 `rocket.config.js`
```js
export default {
imagePresets: {
responsive: {
widths: [300, 820],
formats: ['avif', 'jpeg'],
sizes: '(min-width: 1024px) 820px, calc(100vw - 20px)',
},
},
};
```
## Ignoring Images
Files ending in `.svg` or that include `rocket-ignore.` will remain untouched.
For example
```md
![Logo stays svg](logo.svg)
![Ignore by file name](my-image.rocket-unresponsive.jpg)
![My Image Alternative Text](my-image.jpeg)
```
becomes
```html
<img src="logo.svg" alt="Logo stays svg" rocket-image="responsive" />
<img src="my-image.rocket-unresponsive.jpg" alt="Ignore by file name" rocket-image="responsive" />
<picture>[...] </picture>
```
### Adjusting ignore function
The default ignore function looks like this
```js
/**
* The default responsive ignore function will ignore files
* - ending in `.svg`
* - containing `rocket-unresponsive.`
*
* @param {object} opts
* @param {string} opts.src
* @param {string} opts.title
* @param {string} opts.alt
* @param {{name: string, value: string}[]} opts.attributes
* @returns {boolean}
*/
function ignore({ src }) {
return src.endsWith('svg') || src.includes('rocket-unresponsive.');
}
```
and you can adjust it by setting it via the `imagePreset`.
For this example we want to also ignore `.jpeg` files.
👉 `rocket.config.js`
```js
export default {
imagePresets: {
responsive: {
// ...
ignore: ({ src }) =>
src.endsWith('.jpeg') || src.endsWith('svg') || src.includes('rocket-unresponsive.'),
},
},
};
```
With that setting we get the following behavior
```md
![Logo stays svg](logo.svg)
![Ignore by file name](my-image.rocket-unresponsive.jpg)
![My Image Alternative Text](my-image.jpeg)
```
becomes
```html
<img src="logo.svg" alt="Logo stays svg" rocket-image="responsive" />
<img src="my-image.rocket-unresponsive.jpg" alt="Ignore by file name" rocket-image="responsive" />
<img src="my-image.jpeg" alt="My Image Alternative Text" rocket-image="responsive" />
```
## Defining your own presets
You can add your own image preset like so
```js
export default {
imagePresets: {
'my-image-preset': {
widths: [30, 60],
formats: ['avif', 'jpeg'],
sizes: '(min-width: 1024px) 30px, 60px',
},
},
};
```
Once that `imagePreset` is defined you can use it by adding it to any `img` tag.
```html
<img src="./path/to/image.jpg" alt="my alt" rocket-image="my-image-preset" />
```
## How does it work?
1. Each markdown image `![my image](path/to/image.jpg)` gets rendered as `<img src="path/to/image.jpg" alt="my image" rocket-image="responsive">`
2. We parse the html output and process every image which has `rocket-image`
3. Get the image preset settings from the name e.g. `rocket-image="my-image-preset"` reads `imagePreset['my-image-preset']`
4. Pass the settings onto `@11ty/image` to generate the image sizes and formats
5. With the metadata we render the html
## Default Formats
An [image file format](https://en.wikipedia.org/wiki/Image_file_formats) is a way of storing common image formats. Each format varies in capabilities like compression algorithm, availability, progressive rendering, encode and decode time, ...
Ultimately newer formats are usually smaller while retaining image quality which leads to faster websites.
By default, we generate `avif` and `jpg` because
- we only want to generate two versions to limit CI time and html size
- `avif` is significantly smaller than `webp`
- `avif` is available in
- Chrome since August 2020
- Firefox since June 2021
- `jpg` as a fallback for Edge, Safari, IE11
- `webp` would only help a small percentage of Edge & Safari on macOS 11 (Big Sur) users
This leads to the following situation:
- Chrome, Firefox gets the small `avif`
- Edge, Safari, IE11 gets the bigger `jpg`
To learn more about `avif` take a look at [AVIF has landed](https://jakearchibald.com/2020/avif-has-landed/).
If you want to add `webp` (or replace `avif` with it) you can do so by setting the formats
👉 `rocket.config.js`
```js
export default {
imagePresets: {
responsive: {
formats: ['avif', 'webp', 'jpeg'],
},
},
};
```
## Default widths
In order to understand the need for having a single image in multiple resolutions we need to understand the our website is served to many different environments and each may come with its own specific device pixel ratio (DPR). The device pixel ratio is the ratio between physical pixels and logical pixels. For instance, the Galaxy S20 report a device pixel ratio of 3, because the physical linear resolution is triple the logical linear resolution.
Physical resolution: 1440 x 3200
Logical resolution: 480 x 1067
And 1440 / 480 = 3.
By default, we generate the following widths `600`, `900` and `1640` because
- we only want to generate a small amount of widths to limit CI time and service worker cache size
- `600` is good for mobile with DRP 2
- `900` is good for mobile with DRP 3 and desktop with DPR of 1
- `1640` is good for desktop with DPR of 2
If you want to add more widths you can add them to `widths`.
👉 `rocket.config.js`
```js
export default {
imagePresets: {
responsive: {
widths: [300, 600, 900, 1200, 1640],
sizes: '(min-width: 1024px) 820px, calc(100vw - 20px)',
},
},
};
```
<inline-notification type="tip">
As an end user in most cases you don't want to mess with this as a layout preset should set this for you. If you are building your own layout preset then be sure to set `widths` and `sizes` via `adjustImagePresets`
```js
export function myPreset() {
return {
adjustImagePresets: imagePresets => ({
...imagePresets,
responsive: {
...imagePresets.responsive,
widths: [600, 900, 1640],
sizes: '(min-width: 1024px) 820px, calc(100vw - 40px)',
},
}),
};
}
```
</inline-notification>
```js script
import '@rocket/launch/inline-notification/inline-notification.js';
```

View File

@@ -1,4 +1,4 @@
# Configuration >> Overview ||10 # Configuration >> Overview || 10
The configuration file is `rocket.config.js` or `rocket.config.mjs`. The configuration file is `rocket.config.js` or `rocket.config.mjs`.
@@ -86,3 +86,15 @@ const config = {
export default config; export default config;
``` ```
## Lifecycle
You can hook into the rocket lifecycle by specifying a function for `before11ty`. This function runs before 11ty calls it's write method. If it is an async function, Rocket will await it's promise.
```js
export default {
async before11ty() {
await copyDataFiles();
},
};
```

View File

@@ -1,5 +1,11 @@
# Markdown JavaScript >> Overview || 10 # Markdown JavaScript >> Overview || 10
```js script
import '@mdjs/mdjs-story/define';
import '@mdjs/mdjs-preview/define';
import { html } from '@mdjs/mdjs-story';
```
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. 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.
To annotate we use a code block with `js script`. To annotate we use a code block with `js script`.
@@ -63,13 +69,6 @@ import '@mdjs/mdjs-preview/define';
Once loaded you can use them like so: Once loaded you can use them like so:
````md
```js script
import '@mdjs/mdjs-story/define';
import '@mdjs/mdjs-preview/define';
```
````
### Story ### Story
The code snippet will actually get executed at that place and you will have a live demo The code snippet will actually get executed at that place and you will have a live demo
@@ -117,12 +116,6 @@ 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). 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 { html } from 'lit-html';
```
```js preview-story ```js preview-story
import 'demo-wc-card/demo-wc-card.js'; import 'demo-wc-card/demo-wc-card.js';
export const header = () => { export const header = () => {

View File

@@ -17,7 +17,7 @@ You can showcase live running code by annotating a code block with `js preview-s
- Settings can be remembered for other pages / return visits - Settings can be remembered for other pages / return visits
```js script ```js script
import { html } from 'lit-html'; import { html } from '@mdjs/mdjs-preview';
import './assets/demo-element.js'; import './assets/demo-element.js';
``` ```
@@ -25,7 +25,7 @@ import './assets/demo-element.js';
````md ````md
```js script ```js script
import { html } from 'lit-html'; import { html } from '@mdjs/mdjs-preview';
import './assets/demo-element.js'; import './assets/demo-element.js';
``` ```

View File

@@ -3,12 +3,12 @@
You can showcase live running code by annotating a code block with `js story`. You can showcase live running code by annotating a code block with `js story`.
```js script ```js script
import { html } from 'lit-html'; import { html } from '@mdjs/mdjs-story';
``` ```
````md ````md
```js script ```js script
import { html } from 'lit-html'; import { html } from '@mdjs/mdjs-story';
``` ```
```js story ```js story

View File

@@ -20,7 +20,7 @@ The Plugins Manager helps you register and execute your plugins across the vario
## Adding Remark/Unified Plugins ## Adding Remark/Unified Plugins
If you want to a plugin to the Markdown processing you can use `setupUnifiedPlugins`. If you want to add a plugin to the Markdown processing you can use `setupUnifiedPlugins`.
```js ```js
import emoji from 'remark-emoji'; import emoji from 'remark-emoji';

View File

@@ -9,7 +9,7 @@ Many servers are configured to handle this automatically and to serve a 404.html
The [Rocket Launch preset](../../docs/presets/launch.md) ships a default 404 template you can use. The [Rocket Launch preset](../../docs/presets/launch.md) ships a default 404 template you can use.
To enable it, you need to create a 404.md and use the 404 layout. To enable it, you need to create a `404.md` and use the 404 layout.
👉 `docs/404.md` 👉 `docs/404.md`
@@ -20,6 +20,10 @@ permalink: 404.html
--- ---
``` ```
This results in a `404.html` page, which will do nothing by itself. But many hosting services like netlify or firebase, for example will redirect 404s to this `404.html` by default.
If the hosting provider doesn't already do this, then you may be able to accomplish it via some settings for example by using a `.htaccess` file in case of an apache server.
## Add a Sitemap ## Add a Sitemap
A sitemap can be used to inform search engines or services about the pages your site has. A sitemap can be used to inform search engines or services about the pages your site has.

View File

@@ -0,0 +1,11 @@
# Presets >> Create your own > Options || 10
Your preset can hook into the rocket lifecycle by specifying a function for `before11ty`. This function runs before 11ty calls it's write method. If it is an async function, Rocket will await it's promise.
```js
export default {
async before11ty() {
await copyDataFiles();
},
};
```

View File

@@ -37,6 +37,14 @@ If you look into `docs/_merged_includes/_joiningBlocks/bottom/` you will see a f
- `190-google-analytics.njk` - `190-google-analytics.njk`
- `my-script.njk` - `my-script.njk`
<inline-notification type="tip">
File names without an order/number in front are considered with the order number `10 000` so the generally end up at the bottom. If you need something even below unordered items you can use numbers that are greater then `10 000`.
_Note: For unordered files there is no guarantee of any order._
</inline-notification>
## Controlling the order ## Controlling the order
In the html `<head>` order is usually not that important but when adding script it does. In the html `<head>` order is usually not that important but when adding script it does.
@@ -57,3 +65,7 @@ which brings the order to
## More information ## More information
For more details please see the [Joining Blocks Docs](../../docs/presets/joining-blocks.md) For more details please see the [Joining Blocks Docs](../../docs/presets/joining-blocks.md)
```js script
import '@rocket/launch/inline-notification/inline-notification.js';
```

View File

@@ -45,7 +45,7 @@
}, },
"devDependencies": { "devDependencies": {
"@changesets/cli": "^2.12.0", "@changesets/cli": "^2.12.0",
"@open-wc/testing": "^2.5.32", "@open-wc/testing": "^3.0.0-next.1",
"@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.1.0", "@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-typescript": "^8.1.0", "@rollup/plugin-typescript": "^8.1.0",
@@ -75,14 +75,14 @@
"onchange": "^7.1.0", "onchange": "^7.1.0",
"prettier": "^2.2.1", "prettier": "^2.2.1",
"prettier-plugin-package": "^1.3.0", "prettier-plugin-package": "^1.3.0",
"puppeteer": "^5.5.0", "puppeteer": "^9.0.0",
"remark-emoji": "^2.1.0", "remark-emoji": "^2.1.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"rollup": "^2.36.1", "rollup": "^2.36.1",
"rollup-plugin-terser": "^7.0.2", "rollup-plugin-terser": "^7.0.2",
"sinon": "^9.2.3", "sinon": "^9.2.3",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript": "^4.1.3" "typescript": "^4.3.2"
}, },
"eslintConfig": { "eslintConfig": {
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",

View File

@@ -38,6 +38,6 @@
"testing" "testing"
], ],
"dependencies": { "dependencies": {
"plugins-manager": "^0.2.1" "plugins-manager": "^0.2.2"
} }
} }

View File

@@ -1,5 +1,11 @@
# @rocket/building-rollup # @rocket/building-rollup
## 0.3.1
### Patch Changes
- 60e85a1: Support `picture` tags by handling `source` tags with `srcset` attributes in the rollup asset gathering build phase.
## 0.3.0 ## 0.3.0
### Minor Changes ### Minor Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@rocket/building-rollup", "name": "@rocket/building-rollup",
"version": "0.3.0", "version": "0.3.1",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -56,7 +56,7 @@
"@rollup/plugin-babel": "^5.2.2", "@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-node-resolve": "^11.0.1", "@rollup/plugin-node-resolve": "^11.0.1",
"@rollup/plugin-replace": "^2.4.2", "@rollup/plugin-replace": "^2.4.2",
"@web/rollup-plugin-html": "^1.6.0", "@web/rollup-plugin-html": "^1.8.0",
"@web/rollup-plugin-import-meta-assets": "^1.0.4", "@web/rollup-plugin-import-meta-assets": "^1.0.4",
"@web/rollup-plugin-polyfills-loader": "^1.1.0", "@web/rollup-plugin-polyfills-loader": "^1.1.0",
"browserslist": "^4.16.1", "browserslist": "^4.16.1",

View File

@@ -1,5 +1,31 @@
# check-html-links # check-html-links
## 0.2.3
### Patch Changes
- 5043429: Ignore `<a href="tel:9999">` links
- f08f926: Add missing `slash` dependency
- a0e8edf: Ignore links containing not http schema urls like `sketch://`, `vscode://`, ...
```html
<a href="sketch://add-library?url=https%3A%2F%2Fmyexample.com%2Fdesign%2Fui-kit.xml"></a>
<a href="vscode://file/c:/myProject/package.json:5:10"></a>
```
- 1949b1e: Ignore plain and html encoded mailto links
```html
<!-- source -->
<a href="mailto:address@example.com">contact</a>
<!-- html encoded -->
<a
href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#100;&#100;&#114;&#101;&#115;&#115;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;"
>contact</a
>
```
## 0.2.2 ## 0.2.2
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "check-html-links", "name": "check-html-links",
"version": "0.2.2", "version": "0.2.3",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -37,7 +37,8 @@
"command-line-args": "^5.1.1", "command-line-args": "^5.1.1",
"glob": "^7.0.0", "glob": "^7.0.0",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"sax-wasm": "^2.0.0" "sax-wasm": "^2.0.0",
"slash": "^3.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/glob": "^7.0.0" "@types/glob": "^7.0.0"

View File

@@ -182,6 +182,18 @@ function getValueAndAnchor(inValue) {
}; };
} }
/**
* @param {string} url
* @returns {boolean}
*/
function isNonHttpSchema(url) {
const found = url.match(/([a-z]+):/);
if (found) {
return found.length > 0;
}
return false;
}
/** /**
* *
* @param {Link[]} links * @param {Link[]} links
@@ -207,8 +219,13 @@ async function resolveLinks(links, { htmlFilePath, rootDir, ignoreUsage }) {
if (ignoreUsage(value)) { if (ignoreUsage(value)) {
// ignore // ignore
} else if (value.includes('mailto:')) { } else if (
value.startsWith('mailto:') ||
value.startsWith('&#109;&#97;&#105;&#108;&#116;&#111;&#58;') // = "mailto:" but html encoded
) {
// ignore for now - could add a check to validate if the email address is valid // ignore for now - could add a check to validate if the email address is valid
} else if (value.startsWith('tel:')) {
// ignore for now - could add a check to validate if the phone number is valid
} else if (valueFile === '' && anchor !== '') { } else if (valueFile === '' && anchor !== '') {
addLocalFile(htmlFilePath, anchor, usageObj); addLocalFile(htmlFilePath, anchor, usageObj);
} else if (value.startsWith('//') || value.startsWith('http')) { } else if (value.startsWith('//') || value.startsWith('http')) {
@@ -219,6 +236,8 @@ async function resolveLinks(links, { htmlFilePath, rootDir, ignoreUsage }) {
addLocalFile(filePath, anchor, usageObj); addLocalFile(filePath, anchor, usageObj);
} else if (value === '' && anchor === '') { } else if (value === '' && anchor === '') {
// no need to check it // no need to check it
} else if (isNonHttpSchema(value)) {
// not a schema we handle
} else { } else {
const filePath = path.join(path.dirname(htmlFilePath), valueFile); const filePath = path.join(path.dirname(htmlFilePath), valueFile);
addLocalFile(filePath, anchor, usageObj); addLocalFile(filePath, anchor, usageObj);

View File

@@ -1 +1,3 @@
<a href="mailto:foo@bar.com"></a> <a href="mailto:foo@bar.com"></a>
<!-- encoded mailto links -->
<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#100;&#100;&#114;&#101;&#115;&#115;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;"></a>

View File

@@ -0,0 +1,2 @@
<a href="sketch://add-library?url=https%3A%2F%2Fmyexample.com%2Fdesign%2Fui-kit.xml"></a>
<a href="vscode://file/c:/myProject/package.json:5:10"></a>

View File

@@ -0,0 +1 @@
<a href="tel:99999"></a>

View File

@@ -183,6 +183,16 @@ describe('validateFolder', () => {
expect(cleanup(errors)).to.deep.equal([]); expect(cleanup(errors)).to.deep.equal([]);
}); });
it('ignores tel links', async () => {
const { errors, cleanup } = await execute('fixtures/tel');
expect(cleanup(errors)).to.deep.equal([]);
});
it('ignore not http schema urls', async () => {
const { errors, cleanup } = await execute('fixtures/not-http-schema');
expect(cleanup(errors)).to.deep.equal([]);
});
it('ignoring a folder', async () => { it('ignoring a folder', async () => {
const { errors, cleanup } = await execute('fixtures/internal-link-ignore', { const { errors, cleanup } = await execute('fixtures/internal-link-ignore', {
ignoreLinkPatterns: ['./relative/*', './relative/**/*'], ignoreLinkPatterns: ['./relative/*', './relative/**/*'],

View File

@@ -1,5 +1,115 @@
# @rocket/cli # @rocket/cli
## 0.9.6
### Patch Changes
- bf99541: Adjust copy logic to
1. for `_assets/_static` copy over everything
2. for all other paths copy over everything except `*.html` and `*.md`
- 579e8e7: Unordered joiningBlocks are now considered with the order number `10 000` and will generally be at the bottom.
You can use numbers `> 10 000` to place files even after unordered joiningBlocks.
## 0.9.5
### Patch Changes
- 1b9559f: Adds `before11ty` hook to config and presets
## 0.9.4
### Patch Changes
- 2b5c61d: Allow configuring the imagePreset ignore rules via the option `ignore`
```js
export default {
imagePresets: {
responsive: {
// ...
ignore: ({ src }) =>
src.endsWith('.jpeg') || src.endsWith('svg') || src.includes('rocket-unresponsive.'),
},
},
};
```
- 2b5c61d: Do not generate responsive images for files ending in `.svg` or that include `rocket-ignore.`
- ce0b00e: don't transform external images
- 3b1a0cf: Allow to configure check-html-links
```js
export default {
checkLinks: {
/* ... */
},
};
```
## 0.9.3
### Patch Changes
- 795a361: The server worker url should respect a set pathPrefix.
## 0.9.2
### Patch Changes
- 5330740: When replacing images with responsive picture tags do this from the bottom up so the initial dom parsing locations still hold true.
## 0.9.1
### Patch Changes
- 43a7ca1: Responsive images need to respect a set pathPrefix
## 0.9.0
### Minor Changes
- eae2007: Update to mdjs version that uses lit 2 and renders stories to light dom
### Patch Changes
- Updated dependencies [eae2007]
- @rocket/eleventy-plugin-mdjs-unified@0.5.0
## 0.8.2
### Patch Changes
- 60e85a1: Support `picture` tags by handling `source` tags with `srcset` attributes in the rollup asset gathering build phase.
- Updated dependencies [60e85a1]
- @rocket/building-rollup@0.3.1
## 0.8.1
### Patch Changes
- c338696: Updated dependency of eleventy-img for M1 compatibility
## 0.8.0
### Minor Changes
- 8bba4a8: Every content image in markdown will outputted in multiple widths and formats to ensure small image file sizes while retaining quality.
You can adjust the defaults by setting `imagePresets.responsive`.
```js
export default {
imagePresets: {
responsive: {
widths: [600, 900, 1640],
formats: ['avif', 'jpeg'],
sizes: '(min-width: 1024px) 820px, calc(100vw - 40px)',
},
},
};
```
## 0.7.0 ## 0.7.0
### Minor Changes ### Minor Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@rocket/cli", "name": "@rocket/cli",
"version": "0.7.0", "version": "0.9.6",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -56,10 +56,10 @@
], ],
"dependencies": { "dependencies": {
"@11ty/eleventy": "^0.11.1", "@11ty/eleventy": "^0.11.1",
"@11ty/eleventy-img": "^0.7.4", "@11ty/eleventy-img": "^0.9.0",
"@rocket/building-rollup": "^0.3.0", "@rocket/building-rollup": "^0.3.1",
"@rocket/core": "^0.1.2", "@rocket/core": "^0.1.2",
"@rocket/eleventy-plugin-mdjs-unified": "^0.4.1", "@rocket/eleventy-plugin-mdjs-unified": "^0.5.0",
"@rocket/eleventy-rocket-nav": "^0.3.0", "@rocket/eleventy-rocket-nav": "^0.3.0",
"@rollup/plugin-babel": "^5.2.2", "@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-node-resolve": "^11.0.1", "@rollup/plugin-node-resolve": "^11.0.1",
@@ -67,12 +67,12 @@
"@web/dev-server": "^0.1.4", "@web/dev-server": "^0.1.4",
"@web/dev-server-rollup": "^0.3.2", "@web/dev-server-rollup": "^0.3.2",
"@web/rollup-plugin-copy": "^0.2.0", "@web/rollup-plugin-copy": "^0.2.0",
"check-html-links": "^0.2.2", "check-html-links": "^0.2.3",
"command-line-args": "^5.1.1", "command-line-args": "^5.1.1",
"command-line-usage": "^6.1.1", "command-line-usage": "^6.1.1",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"micromatch": "^4.0.2", "micromatch": "^4.0.2",
"plugins-manager": "^0.2.1", "plugins-manager": "^0.2.2",
"slash": "^3.0.0", "slash": "^3.0.0",
"utf8": "^3.0.0", "utf8": "^3.0.0",
"workbox-window": "^6.1.5" "workbox-window": "^6.1.5"

View File

@@ -1,5 +1,7 @@
{% set rocketServiceWorkerUrl = '/' + rocketConfig.serviceWorkerName %}
<script> <script>
window.__rocketServiceWorkerUrl = '/{{ rocketConfig.serviceWorkerName }}'; window.__rocketServiceWorkerUrl = '{{ rocketServiceWorkerUrl | url }}';
</script> </script>
<script type="module" inject-service-worker="" src="{{ '/_assets/scripts/registerServiceWorker.js' | asset | url }}"></script> <script type="module" inject-service-worker="" src="{{ '/_assets/scripts/registerServiceWorker.js' | asset | url }}"></script>

View File

@@ -11,7 +11,7 @@
} }
</style> </style>
<script type="module"> <script type="module">
import { render } from 'lit-html'; import { render } from '@mdjs/mdjs-story';
async function onHashChange() { async function onHashChange() {
const urlParts = new URLSearchParams(document.location.hash.substr(1)); const urlParts = new URLSearchParams(document.location.hash.substr(1));

View File

@@ -29,7 +29,7 @@ async function productionBuild(config) {
name: 'copy', name: 'copy',
plugin: copy, plugin: copy,
options: { options: {
patterns: ['!(*.md|*.html)*', '_merged_assets/_static/**/*.{png,gif,jpg,json,css,svg,ico}'], patterns: ['!(*.md|*.html)*', '_merged_assets/_static/**/*'],
rootDir: config.outputDevDir, rootDir: config.outputDevDir,
}, },
}), }),

View File

@@ -31,6 +31,7 @@ export class RocketEleventy extends Eleventy {
async write() { async write() {
await this.__rocketCli.mergePresets(); await this.__rocketCli.mergePresets();
for (const fn of this.__rocketCli.config.__before11tyFunctions) await fn();
await super.write(); await super.write();
await this.__rocketCli.update(); await this.__rocketCli.update();
} }
@@ -120,7 +121,7 @@ export class RocketCli {
for (const folder of ['_assets', '_data', '_includes']) { for (const folder of ['_assets', '_data', '_includes']) {
const to = path.join(this.config._inputDirCwdRelative, `_merged${folder}`); const to = path.join(this.config._inputDirCwdRelative, `_merged${folder}`);
await fs.emptyDir(to); await fs.emptyDir(to);
for (const sourceDir of this.config._presetPathes) { for (const sourceDir of this.config._presetPaths) {
const from = path.join(sourceDir, folder); const from = path.join(sourceDir, folder);
if (fs.existsSync(from)) { if (fs.existsSync(from)) {
if (folder === '_includes') { if (folder === '_includes') {

View File

@@ -50,6 +50,7 @@ export class RocketLint {
const checkLinks = new CheckHtmlLinksCli(); const checkLinks = new CheckHtmlLinksCli();
checkLinks.setOptions({ checkLinks.setOptions({
...this.config.checkLinks,
rootDir: this.config.lintInputDir, rootDir: this.config.lintInputDir,
printOnError: false, printOnError: false,
continueOnError: true, continueOnError: true,

View File

@@ -0,0 +1,265 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
const fs = require('fs');
const path = require('path');
const EleventyImage = require('@11ty/eleventy-img');
const urlFilter = require('@11ty/eleventy/src/Filters/Url.js');
const { SaxEventType, SAXParser } = require('sax-wasm');
const { getComputedConfig } = require('../public/computedConfig.cjs');
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,
{ highWaterMark: 256 * 1024 }, // 256k chunks
);
/**
* @param {object} options
* @param {string} options.html
* @param {Position} options.start
* @param {Position} options.end
* @param {string} options.insert
*/
function replaceBetween({ html, start, end, insert = '' }) {
const lines = html.split('\n');
const i = start.line;
const line = lines[i];
const upToChange = line.slice(0, start.character);
const afterChange = line.slice(end.character - 4);
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 getAttributes(data) {
if (data.attributes) {
const { attributes } = data;
return attributes.map(entry => ({ name: entry.name.value, value: entry.value.value }));
}
return [];
}
// /**
// * @param {Tag} data
// */
// function getText(data) {
// if (data.textNodes) {
// return data.textNodes.map(textNode => textNode.value).join('');
// }
// return null;
// }
// /**
// * @param {Tag} data
// */
// function getClassList(data) {
// const classString = getAttribute(data, 'class');
// return classString ? classString.split(' ') : [];
// }
/**
*
* @param src {string} image src attribute value.
* @returns {boolean} true if src starts with https://, http:// or //
*/
function isExternalSrc(src) {
return /^(?:https?:)?\/\//.test(src);
}
/**
* @param {string} html
*/
function getImages(html, { imagePresets }) {
/** @type {Heading[]} */
const images = [];
parser.eventHandler = (ev, _data) => {
if (ev === SaxEventType.CloseTag) {
const data = /** @type {Tag} */ (/** @type {any} */ (_data));
if (data.name === 'img') {
const { openStart, closeEnd } = data;
const attributes = getAttributes(data);
const presetName = getAttribute(data, 'rocket-image');
const src = getAttribute(data, 'src');
const title = getAttribute(data, 'title');
const alt = getAttribute(data, 'alt');
if (presetName) {
const presetSettings = imagePresets[presetName];
if (!presetSettings) {
throw new Error(`Could not find imagePresets: { ${presetName}: {} }`);
}
const { ignore } = presetSettings;
const ignoreFn = typeof ignore === 'function' ? ignore : () => false;
if (!isExternalSrc(src) && !ignoreFn({ src, title, alt, attributes })) {
images.push({
presetName,
attributes,
src,
title,
alt,
openStart,
closeEnd,
});
}
}
}
}
};
parser.write(Buffer.from(html, 'utf8'));
parser.end();
// @ts-ignore
return images;
}
function getSrcsetAttribute(imageFormat) {
return `srcset="${imageFormat.map(entry => entry.srcset).join(', ')}"`;
}
async function responsiveImages(images, { inputPath, outputDir, imagePresets = {} }) {
for (let i = 0; i < images.length; i += 1) {
const { alt, filePath, title, src, presetName, attributes } = images[i];
if (alt === undefined) {
throw new Error(`Missing \`alt\` on responsive image from: ${src} in ${inputPath}`);
}
const presetSettings = imagePresets[presetName];
if (!presetSettings) {
throw new Error(`Could not find imagePresets: { ${presetName}: {} }`);
}
const sizes = presetSettings.sizes || '100vw';
const metadata = await EleventyImage(filePath, {
outputDir: path.join(outputDir, 'images'),
urlPath: urlFilter('/images/'),
...presetSettings,
});
const lowsrc = metadata.jpeg[0];
let pictureStartWithSources = '';
let srcsetAttribute = '';
let sizesAttribute = '';
let pictureEnd = '';
if (Object.keys(metadata).length > 1) {
const sources = Object.values(metadata)
.map(imageFormat => {
return `<source type="${imageFormat[0].sourceType}" ${getSrcsetAttribute(
imageFormat,
)} sizes="${sizes}">`;
})
.join('\n');
pictureStartWithSources = `<picture>\n${sources}`;
pictureEnd = '</picture>';
} else {
srcsetAttribute = getSrcsetAttribute(Object.values(metadata)[0]);
sizesAttribute = `sizes="${sizes}"`;
}
const attributesString = attributes
.filter(attribute => !['src', 'title'].includes(attribute.name))
.map(attribute => `${attribute.name}="${attribute.value}"`)
.join(' ');
const figureStart = title ? '<figure>' : '';
const figureEndWithCaption = title ? `<figcaption>${title}</figcaption>\n</figure>` : '';
images[i].newHtml = `
${figureStart}
${pictureStartWithSources}
<img
${attributesString}
src="${lowsrc.url}"
${srcsetAttribute}
${sizesAttribute}
width="${lowsrc.width}"
height="${lowsrc.height}"
loading="lazy"
decoding="async"
/>
${pictureEnd}
${figureEndWithCaption}
`;
}
return images;
}
function updateHtml(html, changes) {
let newHtml = html;
for (const change of changes.reverse()) {
newHtml = replaceBetween({
html: newHtml,
start: change.openStart,
end: change.closeEnd,
insert: change.newHtml,
});
}
return newHtml;
}
function resolveFilePath(images, { inputPath }) {
for (let i = 0; i < images.length; i += 1) {
images[i].filePath = path.join(path.dirname(inputPath), images[i].src);
}
return images;
}
let isSetup = false;
/**
* @param {string} html
*/
async function insertResponsiveImages(html) {
const config = getComputedConfig();
if (!isSetup) {
await parser.prepareWasm(saxWasmBuffer);
isSetup = true;
}
const options = {
inputPath: this.inputPath,
outputDir: this.outputDir,
imagePresets: config.imagePresets,
};
let images = getImages(html, options);
images = resolveFilePath(images, options);
images = await responsiveImages(images, options);
const newHtml = updateHtml(html, images);
return newHtml;
}
module.exports = {
insertResponsiveImages,
};

View File

@@ -1,6 +1,10 @@
const rocketCopy = { const rocketCopy = {
configFunction: (eleventyConfig, { _inputDirCwdRelative, filesExtensionsToCopy }) => { configFunction: (eleventyConfig, { _inputDirCwdRelative }) => {
eleventyConfig.addPassthroughCopy(`${_inputDirCwdRelative}/**/*.{${filesExtensionsToCopy}}`); eleventyConfig.addPassthroughCopy(`${_inputDirCwdRelative}/!(*.md|*.html)*`);
eleventyConfig.addPassthroughCopy(
`${_inputDirCwdRelative}/!(_includes|_data|_assets|_merged_data|_merged_includes)*/**/!(*.md|*.html)*`,
);
eleventyConfig.addPassthroughCopy(`${_inputDirCwdRelative}/_merged_assets/_static/**/*`);
}, },
}; };

View File

@@ -1,6 +1,7 @@
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const { processLocalReferences } = require('./processLocalReferences.cjs'); const { processLocalReferences } = require('./processLocalReferences.cjs');
const { insertResponsiveImages } = require('./insertResponsiveImages.cjs');
function inlineFilePath(filePath) { function inlineFilePath(filePath) {
let data = fs.readFileSync(filePath, function (err, contents) { let data = fs.readFileSync(filePath, function (err, contents) {
@@ -24,6 +25,7 @@ const rocketFilters = {
eleventyConfig.addFilter('inlineFilePath', inlineFilePath); eleventyConfig.addFilter('inlineFilePath', inlineFilePath);
eleventyConfig.addTransform('insertResponsiveImages', insertResponsiveImages);
eleventyConfig.addTransform('processLocalReferences', processLocalReferences); eleventyConfig.addTransform('processLocalReferences', processLocalReferences);
}, },
}; };

View File

@@ -5,6 +5,7 @@
/** @typedef {import('@web/dev-server').DevServerConfig} DevServerConfig */ /** @typedef {import('@web/dev-server').DevServerConfig} DevServerConfig */
/** @typedef {import('../types/main').RocketCliOptions} RocketCliOptions */ /** @typedef {import('../types/main').RocketCliOptions} RocketCliOptions */
/** @typedef {import('../types/main').ImagePreset} ImagePreset */
/** @typedef {import('../types/main').RocketPlugin} RocketPlugin */ /** @typedef {import('../types/main').RocketPlugin} RocketPlugin */
import path from 'path'; import path from 'path';
@@ -19,9 +20,25 @@ import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url)); const __dirname = path.dirname(fileURLToPath(import.meta.url));
/**
* The default responsive ignore function will ignore files
* - ending in `.svg`
* - containing `rocket-unresponsive.`
*
* @param {object} opts
* @param {string} opts.src
* @param {string} opts.title
* @param {string} opts.alt
* @param {{name: string, value: string}[]} opts.attributes
* @returns {boolean}
*/
function ignore({ src }) {
return src.endsWith('svg') || src.includes('rocket-unresponsive.');
}
/** /**
* @param {Partial<RocketCliOptions>} inConfig * @param {Partial<RocketCliOptions>} inConfig
* @returns {Promise<RocketCliOptions>} * @returns {Promise<RocketCliOptions & { __before11tyFunctions: RocketCliOptions['before11ty'][] }>}
*/ */
export async function normalizeConfig(inConfig) { export async function normalizeConfig(inConfig) {
let config = { let config = {
@@ -45,11 +62,30 @@ export async function normalizeConfig(inConfig) {
devServer: {}, devServer: {},
...inConfig, ...inConfig,
/** @type{RocketCliOptions['before11ty'][]} */
__before11tyFunctions: [],
/** @type{{[key: string]: ImagePreset}} */
imagePresets: {
responsive: {
widths: [600, 900, 1640],
formats: ['avif', 'jpeg'],
sizes: '100vw',
ignore,
},
},
}; };
if (inConfig && inConfig.devServer) { if (inConfig && inConfig.devServer) {
config.devServer = { ...config.devServer, ...inConfig.devServer }; config.devServer = { ...config.devServer, ...inConfig.devServer };
} }
if (inConfig.imagePresets && inConfig.imagePresets.responsive) {
config.imagePresets.responsive = {
...config.imagePresets.responsive,
...inConfig.imagePresets.responsive,
};
}
let userConfigFile; let userConfigFile;
let __configDir = process.cwd(); let __configDir = process.cwd();
@@ -73,7 +109,14 @@ export async function normalizeConfig(inConfig) {
...config.devServer, ...config.devServer,
...fileConfig.devServer, ...fileConfig.devServer,
}, },
imagePresets: config.imagePresets,
}; };
if (fileConfig.imagePresets && fileConfig.imagePresets.responsive) {
config.imagePresets.responsive = {
...config.imagePresets.responsive,
...fileConfig.imagePresets.responsive,
};
}
} }
} catch (error) { } catch (error) {
console.error('Could not read rocket config file', error); console.error('Could not read rocket config file', error);
@@ -84,9 +127,13 @@ export async function normalizeConfig(inConfig) {
const _inputDirCwdRelative = path.join(_configDirCwdRelative, config.inputDir); const _inputDirCwdRelative = path.join(_configDirCwdRelative, config.inputDir);
// cli core preset is always first // cli core preset is always first
config._presetPathes = [path.join(__dirname, '..', 'preset')]; config._presetPaths = [path.join(__dirname, '..', 'preset')];
for (const preset of config.presets) { for (const preset of config.presets) {
config._presetPathes.push(preset.path); config._presetPaths.push(preset.path);
if (preset.adjustImagePresets) {
config.imagePresets = preset.adjustImagePresets(config.imagePresets);
}
if (preset.setupUnifiedPlugins) { if (preset.setupUnifiedPlugins) {
config.setupUnifiedPlugins = [...config.setupUnifiedPlugins, ...preset.setupUnifiedPlugins]; config.setupUnifiedPlugins = [...config.setupUnifiedPlugins, ...preset.setupUnifiedPlugins];
@@ -118,9 +165,13 @@ export async function normalizeConfig(inConfig) {
if (preset.setupCliPlugins) { if (preset.setupCliPlugins) {
config.setupCliPlugins = [...config.setupCliPlugins, ...preset.setupCliPlugins]; config.setupCliPlugins = [...config.setupCliPlugins, ...preset.setupCliPlugins];
} }
if (typeof preset.before11ty === 'function') {
config.__before11tyFunctions.push(preset.before11ty);
}
} }
// add "local" preset // add "local" preset
config._presetPathes.push(path.resolve(_inputDirCwdRelative)); config._presetPaths.push(path.resolve(_inputDirCwdRelative));
/** @type {MetaPlugin[]} */ /** @type {MetaPlugin[]} */
let pluginsMeta = [ let pluginsMeta = [
@@ -145,6 +196,10 @@ export async function normalizeConfig(inConfig) {
plugins.push(pluginInst); plugins.push(pluginInst);
} }
if (typeof config.before11ty === 'function') {
config.__before11tyFunctions.push(config.before11ty);
}
// TODO: check pathPrefix to NOT have a '/' at the end as it will mean it may get ignored by 11ty 🤷‍♂️ // TODO: check pathPrefix to NOT have a '/' at the end as it will mean it may get ignored by 11ty 🤷‍♂️
return { return {

View File

@@ -106,7 +106,7 @@ function socialMediaImagePlugin(args = {}) {
}; };
} }
function sortyByOrder(a, b) { function sortByOrder(a, b) {
if (a.order > b.order) { if (a.order > b.order) {
return 1; return 1;
} }
@@ -127,20 +127,20 @@ async function dirToTree(sourcePath, extra = '') {
if (entry.isDirectory()) { if (entry.isDirectory()) {
const value = await dirToTree(sourcePath, relativePath); const value = await dirToTree(sourcePath, relativePath);
unsortedEntries.push({ unsortedEntries.push({
order: matches && matches.length > 0 ? parseInt(matches[1]) : 0, order: matches && matches.length > 0 ? parseInt(matches[1]) : 10000,
name: entry.name, name: entry.name,
value, value,
}); });
} else { } else {
unsortedEntries.push({ unsortedEntries.push({
order: matches && matches.length > 0 ? parseInt(matches[1]) : 0, order: matches && matches.length > 0 ? parseInt(matches[1]) : 10000,
name: entry.name, name: entry.name,
value: relativePath, value: relativePath,
}); });
} }
} }
const sortedTree = {}; const sortedTree = {};
for (const unsortedEntry of unsortedEntries.sort(sortyByOrder)) { for (const unsortedEntry of unsortedEntries.sort(sortByOrder)) {
sortedTree[unsortedEntry.name] = unsortedEntry.value; sortedTree[unsortedEntry.name] = unsortedEntry.value;
} }
return sortedTree; return sortedTree;

View File

@@ -5,6 +5,16 @@ const { getComputedConfig } = require('../public/computedConfig.cjs');
const rocketFilters = require('../eleventy-plugins/rocketFilters.cjs'); const rocketFilters = require('../eleventy-plugins/rocketFilters.cjs');
const rocketCopy = require('../eleventy-plugins/rocketCopy.cjs'); const rocketCopy = require('../eleventy-plugins/rocketCopy.cjs');
const rocketCollections = require('../eleventy-plugins/rocketCollections.cjs'); const rocketCollections = require('../eleventy-plugins/rocketCollections.cjs');
const { adjustPluginOptions } = require('plugins-manager');
const image = require('./mdjsImageHandler.cjs');
const defaultSetupUnifiedPlugins = [
adjustPluginOptions('remark2rehype', {
handlers: {
image,
},
}),
];
module.exports = function (eleventyConfig) { module.exports = function (eleventyConfig) {
const config = getComputedConfig(); const config = getComputedConfig();
@@ -20,15 +30,14 @@ module.exports = function (eleventyConfig) {
{ {
name: 'rocket-copy', name: 'rocket-copy',
plugin: rocketCopy, plugin: rocketCopy,
options: { options: { _inputDirCwdRelative },
_inputDirCwdRelative,
filesExtensionsToCopy: 'png,gif,jpg,jpeg,svg,css,xml,json,js',
},
}, },
{ {
name: 'eleventy-plugin-mdjs-unified', name: 'eleventy-plugin-mdjs-unified',
plugin: eleventyPluginMdjsUnified, plugin: eleventyPluginMdjsUnified,
options: { setupUnifiedPlugins: config.setupUnifiedPlugins }, options: {
setupUnifiedPlugins: [...defaultSetupUnifiedPlugins, ...config.setupUnifiedPlugins],
},
}, },
{ {
name: 'eleventy-rocket-nav', name: 'eleventy-rocket-nav',

View File

@@ -0,0 +1,17 @@
const normalize = require('mdurl/encode');
function image(h, node) {
const props = {
src: normalize(node.url),
alt: node.alt,
'rocket-image': 'responsive',
};
if (node.title !== null && node.title !== undefined) {
props.title = node.title;
}
return h(node, 'img', props);
}
module.exports = image;

View File

@@ -19,6 +19,7 @@ export function setFixtureDir(importMetaUrl) {
* @property {boolean} stripStartEndWhitespace * @property {boolean} stripStartEndWhitespace
* @property {boolean} stripScripts * @property {boolean} stripScripts
* @property {boolean} formatHtml * @property {boolean} formatHtml
* @property {boolean} replaceImageHashes
* @property {start|build} type * @property {start|build} type
*/ */
@@ -51,6 +52,7 @@ export async function readOutput(
stripScripts = false, stripScripts = false,
formatHtml = false, formatHtml = false,
type = 'build', type = 'build',
replaceImageHashes = false,
} = {}, } = {},
) { ) {
if (!cli || !cli.config) { if (!cli || !cli.config) {
@@ -70,6 +72,9 @@ export async function readOutput(
const scriptCloseTagStart = text.indexOf('</script>', scriptOpenTagEnd) + 9; const scriptCloseTagStart = text.indexOf('</script>', scriptOpenTagEnd) + 9;
text = text.substring(0, scriptOpenTagEnd) + text.substring(scriptCloseTagStart); text = text.substring(0, scriptOpenTagEnd) + text.substring(scriptCloseTagStart);
} }
if (replaceImageHashes) {
text = text.replace(/\/images\/([a-z0-9]+)-/g, '/images/__HASH__-');
}
if (formatHtml) { if (formatHtml) {
text = prettier.format(text, { parser: 'html', printWidth: 100 }); text = prettier.format(text, { parser: 'html', printWidth: 100 });
} }

View File

@@ -106,31 +106,33 @@ describe('RocketCli computedConfig', () => {
cli = await executeStart('computed-config-fixtures/image-link/rocket.config.js'); cli = await executeStart('computed-config-fixtures/image-link/rocket.config.js');
const namedMdContent = [ const namedMdContent = [
'<p><a href="../">Root</a>', '<p>',
'<a href="../one-level/raw/">Raw</a>', ' <a href="../">Root</a>',
'<img src="../images/my-img.svg" alt="my-img">', ' <a href="../one-level/raw/">Raw</a>',
'<img src="/images/my-img.svg" alt="absolute-img"></p>', ' <img src="../images/my-img.svg" alt="my-img" />',
' <img src="/images/my-img.svg" alt="absolute-img" />',
'</p>',
]; ];
const namedHtmlContent = [ const namedHtmlContent = [
'<div id="with-anchor">', '<div id="with-anchor">',
' <a href="../">Root</a>', ' <a href="../">Root</a>',
' <a href="../one-level/raw/">Raw</a>', ' <a href="../one-level/raw/">Raw</a>',
' <img src="../images/my-img.svg" alt="my-img">', ' <img src="../images/my-img.svg" alt="my-img" />',
' <img src="/images/my-img.svg" alt="absolute-img">', ' <img src="/images/my-img.svg" alt="absolute-img" />',
' <picture>', ' <picture>',
' <source media="(min-width:465px)" srcset="../images/picture-min-465.jpg">', ' <source media="(min-width:465px)" srcset="../images/picture-min-465.jpg" />',
' <img src="../images/picture-fallback.jpg" alt="Fallback" style="width:auto;">', ' <img src="../images/picture-fallback.jpg" alt="Fallback" style="width: auto" />',
' </picture>', ' </picture>',
'</div>', '</div>',
]; ];
const templateHtml = await readStartOutput(cli, 'template/index.html'); const templateHtml = await readStartOutput(cli, 'template/index.html', { formatHtml: true });
expect(templateHtml, 'template/index.html does not match').to.equal( expect(templateHtml, 'template/index.html does not match').to.equal(
namedHtmlContent.join('\n'), namedHtmlContent.join('\n'),
); );
const guidesHtml = await readStartOutput(cli, 'guides/index.html'); const guidesHtml = await readStartOutput(cli, 'guides/index.html', { formatHtml: true });
expect(guidesHtml, 'guides/index.html does not match').to.equal( expect(guidesHtml, 'guides/index.html does not match').to.equal(
[...namedMdContent, ...namedHtmlContent].join('\n'), [...namedMdContent, ...namedHtmlContent].join('\n'),
); );
@@ -157,27 +159,28 @@ describe('RocketCli computedConfig', () => {
); );
// for index files no '../' will be added // for index files no '../' will be added
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readStartOutput(cli, 'index.html', { formatHtml: true });
expect(indexHtml, 'index.html does not match').to.equal( expect(indexHtml, 'index.html does not match').to.equal(
[ [
'<p><a href="./">Root</a>', '<p>',
'<a href="guides/#with-anchor">Guides</a>',
'<a href="./one-level/raw/">Raw</a>',
'<a href="template/">Template</a>',
'<a href="./rules/tabindex/">EndingIndex</a>',
'<img src="./images/my-img.svg" alt="my-img">',
'<img src="/images/my-img.svg" alt="absolute-img"></p>',
'<div>',
' <a href="./">Root</a>', ' <a href="./">Root</a>',
' 👇<a href="guides/#with-anchor">Guides</a>', ' <a href="guides/#with-anchor">Guides</a>',
' 👉 <a href="./one-level/raw/">Raw</a>', ' <a href="./one-level/raw/">Raw</a>',
' <a href="template/">Template</a>', ' <a href="template/">Template</a>',
' <a href="./rules/tabindex/">EndingIndex</a>', ' <a href="./rules/tabindex/">EndingIndex</a>',
' <img src="./images/my-img.svg" alt="my-img">', ' <img src="./images/my-img.svg" alt="my-img" />',
' <img src="/images/my-img.svg" alt="absolute-img">', ' <img src="/images/my-img.svg" alt="absolute-img" />',
'</p>',
'<div>',
' <a href="./">Root</a>',
' 👇<a href="guides/#with-anchor">Guides</a> 👉 <a href="./one-level/raw/">Raw</a>',
' <a href="template/">Template</a>',
' <a href="./rules/tabindex/">EndingIndex</a>',
' <img src="./images/my-img.svg" alt="my-img" />',
' <img src="/images/my-img.svg" alt="absolute-img" />',
' <picture>', ' <picture>',
' <source media="(min-width:465px)" srcset="./images/picture-min-465.jpg">', ' <source media="(min-width:465px)" srcset="./images/picture-min-465.jpg" />',
' <img src="./images/picture-fallback.jpg" alt="Fallback" style="width:auto;">', ' <img src="./images/picture-fallback.jpg" alt="Fallback" style="width: auto" />',
' </picture>', ' </picture>',
'</div>', '</div>',
].join('\n'), ].join('\n'),

View File

@@ -102,6 +102,30 @@ describe('RocketCli e2e', () => {
); );
const assetHtml = await readStartOutput(cli, 'use-assets/index.html'); const assetHtml = await readStartOutput(cli, 'use-assets/index.html');
expect(assetHtml).to.equal('<link rel="stylesheet" href="/_merged_assets/some.css">'); expect(assetHtml).to.equal('<link rel="stylesheet" href="/_merged_assets/some.css">');
const imageHtml = await readStartOutput(cli, 'image/index.html', { replaceImageHashes: true });
expect(imageHtml).to.equal(
[
'<p>',
' <figure>',
' <picture>',
'<source type="image/avif" srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w" sizes="100vw">',
'<source type="image/jpeg" srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w" sizes="100vw">',
' <img',
' alt="My Image Alternative Text" rocket-image="responsive"',
' src="/images/__HASH__-600.jpeg"',
' ',
' ',
' width="600"',
' height="316"',
' loading="lazy"',
' decoding="async"',
' />',
' </picture>',
' <figcaption>My Image Description</figcaption>',
'</figure>',
' </p>',
].join('\n'),
);
}); });
it('can add a pathPrefix that will be used in the build command', async () => { it('can add a pathPrefix that will be used in the build command', async () => {
@@ -119,6 +143,26 @@ describe('RocketCli e2e', () => {
expect(assetHtml).to.equal( expect(assetHtml).to.equal(
'<html><head><link rel="stylesheet" href="../41297ffa.css">\n\n</head><body>\n\n</body></html>', '<html><head><link rel="stylesheet" href="../41297ffa.css">\n\n</head><body>\n\n</body></html>',
); );
let imageHtml = await readBuildOutput(cli, 'image/index.html');
imageHtml = imageHtml.replace(/\.\.\/([a-z0-9]+)\./g, '../__HASH__.');
expect(imageHtml).to.equal(
[
'<html><head>',
'</head><body><p>',
' </p><figure>',
' <picture>',
'<source type="image/avif" srcset="../__HASH__.avif 600w, ../__HASH__.avif 900w" sizes="100vw">',
'<source type="image/jpeg" srcset="../__HASH__.jpeg 600w, ../__HASH__.jpeg 900w" sizes="100vw">',
' <img alt="My Image Alternative Text" rocket-image="responsive" src="../__HASH__.jpeg" width="600" height="316" loading="lazy" decoding="async">',
' </picture>',
' <figcaption>My Image Description</figcaption>',
'</figure>',
' <p></p>',
'',
'',
'</body></html>',
].join('\n'),
);
}); });
it('smoke test for link checking', async () => { it('smoke test for link checking', async () => {

View File

@@ -0,0 +1,296 @@
import chai from 'chai';
import chalk from 'chalk';
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
describe('RocketCli images', () => {
let cli;
before(() => {
// ignore colors in tests as most CIs won't support it
chalk.level = 0;
setFixtureDir(import.meta.url);
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
}
});
describe('Images', () => {
it('does render content images responsive', async () => {
cli = await executeStart('e2e-fixtures/images/rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html', {
formatHtml: true,
replaceImageHashes: true,
});
expect(indexHtml).to.equal(
[
'<p>',
' <figure>',
' <picture>',
' <source',
' type="image/avif"',
' srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w"',
' sizes="100vw"',
' />',
' <source',
' type="image/jpeg"',
' srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w"',
' sizes="100vw"',
' />',
' <img',
' alt="My Image Alternative Text"',
' rocket-image="responsive"',
' src="/images/__HASH__-600.jpeg"',
' width="600"',
' height="316"',
' loading="lazy"',
' decoding="async"',
' />',
' </picture>',
' <figcaption>My Image Description</figcaption>',
' </figure>',
'</p>',
].join('\n'),
);
const keepSvgHtml = await readStartOutput(cli, 'ignores/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
// ignores src="[...].svg" and src="[...]rocket-unresponsive.[...]"
expect(keepSvgHtml).to.equal(
[
'<p>Ignore SVG</p>',
'<p><img src="../_assets/logo.svg" alt="Logo stays svg" rocket-image="responsive" /></p>',
'<p>Ignore if contains <code>rocket-unresponsive.</code></p>',
'<p>',
' <img',
' src="../_assets/my-image.rocket-unresponsive.jpg"',
' alt="Logo stays svg"',
' rocket-image="responsive"',
' />',
'</p>',
'<p>Responsive</p>',
'<p>',
' <picture>',
' <source',
' type="image/avif"',
' srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w"',
' sizes="100vw"',
' />',
' <source',
' type="image/jpeg"',
' srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w"',
' sizes="100vw"',
' />',
' <img',
' alt="My Image Alternative Text"',
' rocket-image="responsive"',
' src="/images/__HASH__-600.jpeg"',
' width="600"',
' height="316"',
' loading="lazy"',
' decoding="async"',
' />',
' </picture>',
'</p>',
].join('\n'),
);
});
it('can configure more patterns to ignore', async () => {
cli = await executeStart('e2e-fixtures/images/ignore-more.rocket.config.js');
const keepSvgHtml = await readStartOutput(cli, 'ignores/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
// ignores src="[...].svg" and src="[...]rocket-unresponsive.[...]"
expect(keepSvgHtml).to.equal(
[
'<p>Ignore SVG</p>',
'<p><img src="../_assets/logo.svg" alt="Logo stays svg" rocket-image="responsive" /></p>',
'<p>Ignore if contains <code>rocket-unresponsive.</code></p>',
'<p>',
' <img',
' src="../_assets/my-image.rocket-unresponsive.jpg"',
' alt="Logo stays svg"',
' rocket-image="responsive"',
' />',
'</p>',
'<p>Responsive</p>',
'<p>',
' <img src="../_assets/my-image.jpeg" alt="My Image Alternative Text" rocket-image="responsive" />',
'</p>',
].join('\n'),
);
});
it('renders multiple images in the correct order', async () => {
cli = await executeStart('e2e-fixtures/images/rocket.config.js');
const indexHtml = await readStartOutput(cli, 'two-images/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
expect(indexHtml).to.equal(
[
'<h2 id="one">',
' <a aria-hidden="true" tabindex="-1" href="#one"><span class="icon icon-link"></span></a>one',
'</h2>',
'<p>',
' <picture>',
' <source',
' type="image/avif"',
' srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w"',
' sizes="100vw"',
' />',
' <source',
' type="image/jpeg"',
' srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w"',
' sizes="100vw"',
' />',
' <img',
' alt="one"',
' rocket-image="responsive"',
' src="/images/__HASH__-600.jpeg"',
' width="600"',
' height="316"',
' loading="lazy"',
' decoding="async"',
' />',
' </picture>',
'</p>',
'<h2 id="two">',
' <a aria-hidden="true" tabindex="-1" href="#two"><span class="icon icon-link"></span></a>two',
'</h2>',
'<p>',
' <picture>',
' <source',
' type="image/avif"',
' srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w"',
' sizes="100vw"',
' />',
' <source',
' type="image/jpeg"',
' srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w"',
' sizes="100vw"',
' />',
' <img',
' alt="two"',
' rocket-image="responsive"',
' src="/images/__HASH__-600.jpeg"',
' width="600"',
' height="316"',
' loading="lazy"',
' decoding="async"',
' />',
' </picture>',
'</p>',
].join('\n'),
);
});
it('can configure those responsive images', async () => {
cli = await executeStart('e2e-fixtures/images/small.rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html', {
formatHtml: true,
replaceImageHashes: true,
});
expect(indexHtml).to.equal(
[
'<p>',
' <figure>',
' <picture>',
' <source',
' type="image/avif"',
' srcset="/images/__HASH__-30.avif 30w, /images/__HASH__-60.avif 60w"',
' sizes="(min-width: 1024px) 30px, 60px"',
' />',
' <source',
' type="image/jpeg"',
' srcset="/images/__HASH__-30.jpeg 30w, /images/__HASH__-60.jpeg 60w"',
' sizes="(min-width: 1024px) 30px, 60px"',
' />',
' <img',
' alt="My Image Alternative Text"',
' rocket-image="responsive"',
' src="/images/__HASH__-30.jpeg"',
' width="30"',
' height="15"',
' loading="lazy"',
' decoding="async"',
' />',
' </picture>',
' <figcaption>My Image Description</figcaption>',
' </figure>',
'</p>',
].join('\n'),
);
});
it('will only render a figure & figcaption if there is a caption/title', async () => {
cli = await executeStart('e2e-fixtures/images/small.rocket.config.js');
const indexHtml = await readStartOutput(cli, 'no-title/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
expect(indexHtml).to.equal(
[
'<p>',
' <picture>',
' <source',
' type="image/avif"',
' srcset="/images/__HASH__-30.avif 30w, /images/__HASH__-60.avif 60w"',
' sizes="(min-width: 1024px) 30px, 60px"',
' />',
' <source',
' type="image/jpeg"',
' srcset="/images/__HASH__-30.jpeg 30w, /images/__HASH__-60.jpeg 60w"',
' sizes="(min-width: 1024px) 30px, 60px"',
' />',
' <img',
' alt="My Image Alternative Text"',
' rocket-image="responsive"',
' src="/images/__HASH__-30.jpeg"',
' width="30"',
' height="15"',
' loading="lazy"',
' decoding="async"',
' />',
' </picture>',
'</p>',
].join('\n'),
);
});
it('will render an img with srcset and sizes if there is only one image format', async () => {
cli = await executeStart('e2e-fixtures/images/single-format.rocket.config.js');
const indexHtml = await readStartOutput(cli, 'no-title/index.html', {
formatHtml: true,
replaceImageHashes: true,
});
expect(indexHtml).to.equal(
[
'<p>',
' <img',
' alt="My Image Alternative Text"',
' rocket-image="responsive"',
' src="/images/__HASH__-30.jpeg"',
' srcset="/images/__HASH__-30.jpeg 30w, /images/__HASH__-60.jpeg 60w"',
' sizes="(min-width: 1024px) 30px, 60px"',
' width="30"',
' height="15"',
' loading="lazy"',
' decoding="async"',
' />',
'</p>',
].join('\n'),
);
});
});
});

View File

@@ -29,7 +29,13 @@ describe('RocketCli mergeTemplates', () => {
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readStartOutput(cli, 'index.html');
expect(trimWhiteSpace(indexHtml)).to.equal( expect(trimWhiteSpace(indexHtml)).to.equal(
['<p>first</p>', '<p>second</p>', '<p>30-third</p>', '<p>100-last</p>'].join('\n'), [
'<p>30-first</p>',
'<p>100-second</p>',
'<p>bar-third</p>',
'<p>foo-fourth</p>',
'<p>10100-last</p>',
].join('\n'),
); );
}); });

View File

@@ -104,4 +104,30 @@ describe('RocketCli preset', () => {
const indexHtml = await readStartOutput(cli, 'index.html'); const indexHtml = await readStartOutput(cli, 'index.html');
expect(indexHtml).to.include('<meta name="added" content="at the top" />'); expect(indexHtml).to.include('<meta name="added" content="at the top" />');
}); });
it('a preset can provide an adjustImagePresets() function', async () => {
cli = await executeStart('preset-fixtures/use-preset/rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html', {
formatHtml: true,
replaceImageHashes: true,
});
expect(indexHtml).to.equal(
[
'<p>',
' <img',
' alt="My Image Alternative Text"',
' rocket-image="responsive"',
' src="/images/__HASH__-30.jpeg"',
' srcset="/images/__HASH__-30.jpeg 30w, /images/__HASH__-60.jpeg 60w"',
' sizes="30px"',
' width="30"',
' height="15"',
' loading="lazy"',
' decoding="async"',
' />',
'</p>',
].join('\n'),
);
});
}); });

View File

@@ -0,0 +1,66 @@
import chai from 'chai';
import chalk from 'chalk';
import { executeBuild, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers';
const { expect } = chai;
function getInjectServiceWorker(text) {
const scriptOpenTagStart = text.indexOf('<script type="module" inject-service-worker=""');
const scriptCloseTagEnd = text.indexOf('</script>', scriptOpenTagStart) + 9;
text = text.substring(scriptOpenTagStart, scriptCloseTagEnd);
return text;
}
function getServiceWorkerUrl(text) {
const matches = text.match(/window\.__rocketServiceWorkerUrl = '(.*?)';/);
return matches[1];
}
describe('RocketCli e2e', () => {
let cli;
before(() => {
// ignore colors in tests as most CIs won't support it
chalk.level = 0;
setFixtureDir(import.meta.url);
});
afterEach(async () => {
if (cli?.cleanup) {
await cli.cleanup();
}
});
it('will add a script to inject the service worker', async () => {
cli = await executeBuild('e2e-fixtures/service-worker/rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html');
const indexInject = getInjectServiceWorker(indexHtml);
expect(indexInject).to.equal(
'<script type="module" inject-service-worker="" src="/_merged_assets/scripts/registerServiceWorker.js"></script>',
);
expect(getServiceWorkerUrl(indexHtml)).to.equal('/service-worker.js');
const subHtml = await readStartOutput(cli, 'sub/index.html');
const subInject = getInjectServiceWorker(subHtml);
expect(subInject).to.equal(
'<script type="module" inject-service-worker="" src="/_merged_assets/scripts/registerServiceWorker.js"></script>',
);
expect(getServiceWorkerUrl(subHtml)).to.equal('/service-worker.js');
});
// TODO: find a way to run these test either by forcing pathPrefix in start or skipping asset gathering for build or ...
it.skip('will add a script to inject the service worker', async () => {
cli = await executeBuild('e2e-fixtures/service-worker/pathPrefix.rocket.config.js');
const indexHtml = await readStartOutput(cli, 'index.html');
const indexInject = getInjectServiceWorker(indexHtml);
expect(indexInject).to.equal(
'<script type="module" inject-service-worker="" src="/my-prefix-folder/_merged_assets/scripts/registerServiceWorker.js"></script>',
);
expect(getServiceWorkerUrl(indexHtml)).to.equal('/my-prefix-folder/service-worker.js');
const subHtml = await readStartOutput(cli, 'sub/index.html');
const subInject = getInjectServiceWorker(subHtml);
expect(subInject).to.equal(
'<script type="module" inject-service-worker="" src="/my-prefix-folder/_merged_assets/scripts/registerServiceWorker.js"></script>',
);
expect(getServiceWorkerUrl(subHtml)).to.equal('/my-prefix-folder/service-worker.js');
});
});

View File

@@ -1,3 +1,20 @@
import { adjustPluginOptions } from 'plugins-manager';
function image(h, node) {
return h(node, 'img', {
src: node.url,
alt: node.alt,
});
}
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */ /** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {}; const config = {
setupUnifiedPlugins: [
adjustPluginOptions('remark2rehype', {
handlers: {
image,
},
}),
],
};
export default config; export default config;

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

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

View File

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

View File

@@ -0,0 +1,33 @@
<svg fill="#e63946" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 511.998 511.998" xml:space="preserve">
<g>
<path d="M98.649,430.256c-46.365,28.67-71.17,30.939-78.916,23.51c-7.75-7.433-6.519-32.307,20.182-79.832
c24.953-44.412,65.374-96.693,113.818-147.211l-11.279-10.817C93.124,267.348,51.871,320.751,26.291,366.279
c-19.228,34.22-37.848,79.134-17.375,98.766c5.84,5.6,13.599,7.935,22.484,7.935c22.269,0,51.606-14.677,75.469-29.432
c44.416-27.464,96.044-70.919,145.373-122.362l-11.279-10.817C192.517,360.888,141.976,403.464,98.649,430.256z"/>
<rect x="238.112" y="272.64" transform="matrix(-0.7218 -0.6921 0.6921 -0.7218 237.9094 656.5383)" width="25.589" height="15.628"/>
<rect x="268.895" y="302.163" transform="matrix(-0.7218 -0.6921 0.6921 -0.7218 270.4774 728.6761)" width="25.589" height="15.628"/>
<rect x="232.827" y="268.929" transform="matrix(-0.7218 -0.6921 0.6921 -0.7218 297.4719 673.0591)" width="102.364" height="15.628"/>
<path d="M500.916,41.287c-7.769,1.59-76.412,16.062-93.897,34.294l-50.728,52.899l-114.703-3.629l-39.198,40.876l79.28,40.569
l-21.755,22.687l72.848,69.858l21.755-22.687l43.857,77.51l39.197-40.876l-8.433-114.451l50.727-52.899
c17.485-18.234,29.067-87.422,30.331-95.251l1.801-11.169L500.916,41.287z M228.209,161.383l19.842-20.692l93.688,2.964
l-48.775,50.864L228.209,161.383z M401.632,327.686l-35.822-63.308l48.776-50.865l6.886,93.482L401.632,327.686z
M332.298,276.743l-50.287-48.223L412.89,92.037l50.288,48.223L332.298,276.743z M473.009,128.036l-48.316-46.334
c14.54-8.427,44.787-17.217,68.076-22.632C488.336,82.567,480.82,113.155,473.009,128.036z"/>
<rect x="302.369" y="231.988" transform="matrix(-0.7218 -0.6921 0.6921 -0.7218 384.0262 633.9694)" width="34.12" height="15.628"/>
<rect x="411.311" y="127.35" transform="matrix(-0.6921 0.7218 -0.7218 -0.6921 807.9747 -74.331)" width="17.061" height="15.628"/>
<rect x="394.288" y="145.087" transform="matrix(-0.7218 -0.6921 0.6921 -0.7218 586.0206 542.7934)" width="15.628" height="17.06"/>
<rect x="376.571" y="163.565" transform="matrix(-0.7218 -0.6921 0.6921 -0.7218 542.7271 562.3462)" width="15.628" height="17.06"/>
<rect x="161.111" y="185.158" transform="matrix(0.7071 0.7071 -0.7071 0.7071 192.1943 -60.3323)" width="15.628" height="33.35"/>
<rect x="184.683" y="172.695" transform="matrix(0.707 0.7072 -0.7072 0.707 182.4625 -83.9076)" width="15.628" height="11.118"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@@ -0,0 +1,15 @@
---
layout: layout-raw
---
Ignore SVG
![Logo stays svg](./_assets/logo.svg)
Ignore if contains `rocket-unresponsive.`
![Logo stays svg](./_assets/my-image.rocket-unresponsive.jpg)
Responsive
![My Image Alternative Text](./_assets/my-image.jpeg)

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,10 @@
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
imagePresets: {
responsive: {
ignore: ({ src }) =>
src.endsWith('.jpeg') || src.endsWith('svg') || src.includes('rocket-unresponsive.'),
},
},
};
export default config;

View File

@@ -0,0 +1,3 @@
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {};
export default config;

View File

@@ -0,0 +1,11 @@
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
imagePresets: {
responsive: {
widths: [30, 60],
formats: ['jpeg'],
sizes: '(min-width: 1024px) 30px, 60px',
},
},
};
export default config;

View File

@@ -0,0 +1,11 @@
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
imagePresets: {
responsive: {
widths: [30, 60],
formats: ['avif', 'jpeg'],
sizes: '(min-width: 1024px) 30px, 60px',
},
},
};
export default config;

View File

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

View File

@@ -0,0 +1 @@
module.exports = 'https://example.com';

View File

@@ -0,0 +1,5 @@
---
layout: layout-default
---
Content inside `docs/index.md`

View File

@@ -0,0 +1,5 @@
---
layout: layout-default
---
Content inside `docs/sub.md`

View File

@@ -0,0 +1,6 @@
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
pathPrefix: '/my-prefix-folder/',
};
export default config;

View File

@@ -0,0 +1,3 @@
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {};
export default config;

View File

@@ -7,4 +7,9 @@ export default {
data: '--config-override--', data: '--config-override--',
}, },
}, },
imagePresets: {
responsive: {
sizes: '--override-sizes--',
},
},
}; };

View File

@@ -10,9 +10,10 @@ function cleanup(config) {
const configNoPaths = { ...config }; const configNoPaths = { ...config };
delete configNoPaths._inputDirCwdRelative; delete configNoPaths._inputDirCwdRelative;
delete configNoPaths.configFile; delete configNoPaths.configFile;
delete configNoPaths._presetPathes; delete configNoPaths._presetPaths;
delete configNoPaths.eleventy; delete configNoPaths.eleventy;
delete configNoPaths.outputDevDir; delete configNoPaths.outputDevDir;
delete configNoPaths.imagePresets.responsive.ignore;
return configNoPaths; return configNoPaths;
} }
@@ -23,11 +24,12 @@ describe('normalizeConfig', () => {
// testing pathes is always a little more complicted 😅 // testing pathes is always a little more complicted 😅
expect(config._inputDirCwdRelative).to.match(/empty\/docs$/); expect(config._inputDirCwdRelative).to.match(/empty\/docs$/);
expect(config._presetPathes[0]).to.match(/cli\/preset$/); expect(config._presetPaths[0]).to.match(/cli\/preset$/);
expect(config._presetPathes[1]).to.match(/empty\/docs$/); expect(config._presetPaths[1]).to.match(/empty\/docs$/);
expect(config.outputDevDir).to.match(/_site-dev$/); expect(config.outputDevDir).to.match(/_site-dev$/);
expect(cleanup(config)).to.deep.equal({ expect(cleanup(config)).to.deep.equal({
__before11tyFunctions: [],
command: 'help', command: 'help',
createSocialMediaImages: true, createSocialMediaImages: true,
devServer: {}, devServer: {},
@@ -47,6 +49,13 @@ describe('normalizeConfig', () => {
{ commands: ['build'] }, { commands: ['build'] },
{ commands: ['start', 'build', 'lint'] }, { commands: ['start', 'build', 'lint'] },
], ],
imagePresets: {
responsive: {
formats: ['avif', 'jpeg'],
sizes: '100vw',
widths: [600, 900, 1640],
},
},
inputDir: 'docs', inputDir: 'docs',
outputDir: '_site', outputDir: '_site',
}); });
@@ -62,6 +71,7 @@ describe('normalizeConfig', () => {
}); });
expect(cleanup(config)).to.deep.equal({ expect(cleanup(config)).to.deep.equal({
__before11tyFunctions: [],
command: 'help', command: 'help',
createSocialMediaImages: true, createSocialMediaImages: true,
devServer: { devServer: {
@@ -77,6 +87,13 @@ describe('normalizeConfig', () => {
setupCliPlugins: [], setupCliPlugins: [],
setupEleventyComputedConfig: [], setupEleventyComputedConfig: [],
presets: [], presets: [],
imagePresets: {
responsive: {
formats: ['avif', 'jpeg'],
sizes: '100vw',
widths: [600, 900, 1640],
},
},
serviceWorkerName: 'service-worker.js', serviceWorkerName: 'service-worker.js',
plugins: [ plugins: [
{ commands: ['start'] }, { commands: ['start'] },
@@ -95,6 +112,7 @@ describe('normalizeConfig', () => {
}); });
expect(cleanup(config)).to.deep.equal({ expect(cleanup(config)).to.deep.equal({
__before11tyFunctions: [],
command: 'help', command: 'help',
createSocialMediaImages: true, createSocialMediaImages: true,
devServer: { devServer: {
@@ -110,6 +128,13 @@ describe('normalizeConfig', () => {
setupCliPlugins: [], setupCliPlugins: [],
setupEleventyComputedConfig: [], setupEleventyComputedConfig: [],
presets: [], presets: [],
imagePresets: {
responsive: {
formats: ['avif', 'jpeg'],
sizes: '--override-sizes--',
widths: [600, 900, 1640],
},
},
serviceWorkerName: 'service-worker.js', serviceWorkerName: 'service-worker.js',
plugins: [ plugins: [
{ commands: ['start'] }, { commands: ['start'] },
@@ -133,6 +158,7 @@ describe('normalizeConfig', () => {
}); });
expect(cleanup(config)).to.deep.equal({ expect(cleanup(config)).to.deep.equal({
__before11tyFunctions: [],
command: 'help', command: 'help',
createSocialMediaImages: true, createSocialMediaImages: true,
devServer: {}, devServer: {},
@@ -146,6 +172,13 @@ describe('normalizeConfig', () => {
setupCliPlugins: [], setupCliPlugins: [],
setupEleventyComputedConfig: [], setupEleventyComputedConfig: [],
presets: [], presets: [],
imagePresets: {
responsive: {
formats: ['avif', 'jpeg'],
sizes: '100vw',
widths: [600, 900, 1640],
},
},
serviceWorkerName: 'service-worker.js', serviceWorkerName: 'service-worker.js',
plugins: [ plugins: [
{ commands: ['start'] }, { commands: ['start'] },

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@@ -0,0 +1 @@
module.exports = 'do-not-generate-a-social-media-image';

View File

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

View File

@@ -0,0 +1,19 @@
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export function myPreset() {
return {
path: path.resolve(__dirname),
adjustImagePresets: imagePresets => ({
...imagePresets,
responsive: {
...imagePresets.responsive,
widths: [30, 60],
formats: ['jpeg'],
sizes: '30px',
},
}),
};
}

View File

@@ -0,0 +1,8 @@
import { myPreset } from './my-preset.js';
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
const config = {
presets: [myPreset()],
};
export default config;

View File

@@ -1,58 +1,79 @@
import { DevServerConfig } from '@web/dev-server'; import { DevServerConfig } from '@web/dev-server';
import { CheckHtmlLinksCliOptions } from 'check-html-links/dist-types/types/main';
export interface RocketPreset { export interface RocketPreset {
path: string; path: string;
adjustImagePresets?: (preset: { [key: string]: ImagePreset }) => { [key: string]: ImagePreset };
before11ty?: () => void | Promise<void>;
// TODO: improve all setup functions // TODO: improve all setup functions
setupUnifiedPlugins?: function[]; setupUnifiedPlugins?: function[];
setupDevAndBuildPlugins: function[]; setupDevAndBuildPlugins?: function[];
setupBuildPlugins: function[]; setupBuildPlugins?: function[];
setupDevPlugins: function[]; setupDevPlugins?: function[];
setupCliPlugins: function[]; setupCliPlugins?: function[];
setupEleventyPlugins: function[]; setupEleventyPlugins?: function[];
setupEleventyComputedConfig: function[]; setupEleventyComputedConfig?: function[];
} }
interface RocketStartConfig { interface RocketStartConfig {
createSocialMediaImages?: boolean; createSocialMediaImages?: boolean;
} }
type ImageFormat = 'avif' | 'webp' | 'jpg' | 'jpeg' | 'png' | 'svg';
interface ImagePreset {
widths: number[];
formats: ImageFormat[];
sizes: string;
}
export interface RocketCliOptions { export interface RocketCliOptions {
presets: Array<RocketPreset>; presets?: Array<RocketPreset>;
pathPrefix?: string; pathPrefix?: string;
serviceWorkerName?: string; serviceWorkerName?: string;
inputDir: string; inputDir?: string;
outputDir: string; outputDir?: string;
emptyOutputDir?: boolean; emptyOutputDir?: boolean;
absoluteBaseUrl?: string; absoluteBaseUrl?: string;
watch: boolean; watch?: boolean;
createSocialMediaImages?: boolean; createSocialMediaImages?: boolean;
imagePresets?: {
[key: string]: ImagePreset;
};
before11ty?: () => void | Promise<void>;
checkLinks?: Partial<CheckHtmlLinksCliOptions>;
start?: RocketStartConfig; start?: RocketStartConfig;
// TODO: improve all setup functions // TODO: improve all setup functions
setupUnifiedPlugins?: function[]; setupUnifiedPlugins?: function[];
setupDevAndBuildPlugins: function[]; setupDevAndBuildPlugins?: function[];
setupBuildPlugins: function[]; setupBuildPlugins?: function[];
setupDevPlugins: function[]; setupDevPlugins?: function[];
setupCliPlugins: function[]; setupCliPlugins?: function[];
setupEleventyPlugins: function[]; setupEleventyPlugins?: function[];
setupEleventyComputedConfig: function[]; setupEleventyComputedConfig?: function[];
// advanced // advanced
devServer: DevServerConfig; devServer?: DevServerConfig;
eleventy: function; // TODO: improve eleventy?: (eleventyConfig: any) => void; // TODO: improve
plugins: RocketPlugin[]; plugins?: RocketPlugin[];
// rarely used // rarely used
command: string; command?: string;
configFile?: string; configFile?: string;
outputDevDir: string; outputDevDir?: string;
private _inputDirCwdRelative: string; private _inputDirCwdRelative?: string;
private _presetPathes?: Array<string>; private _presetPaths?: string[];
private __before11tyFunctions?: (() => void | Promise<void>)[];
} }
export interface RocketPlugin { export interface RocketPlugin {
commands: Array<string>; commands: string[];
} }

View File

@@ -1,5 +1,11 @@
# @rocket/eleventy-plugin-mdjs-unified # @rocket/eleventy-plugin-mdjs-unified
## 0.5.0
### Minor Changes
- eae2007: Update to mdjs version that uses lit 2 and renders stories to light dom
## 0.4.1 ## 0.4.1
### Patch Changes ### Patch Changes

View File

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

View File

@@ -1,5 +1,32 @@
# @rocket/launch # @rocket/launch
## 0.5.2
### Patch Changes
- 9e3c2f5: Only show the help & feedback link if a site.helpUrl is defined
- 9625b94: Remove footer urls to pages that users would need to create
- 1f79d7a: Add font-family CSS variables
- `--primary-font-family` for body text
- `--secondary-font-family` for emphasis (e.g. call-to-action)
- `--heading-font-family` for headings (defaults to `--primary-font-family`)
- `--monospace-font-family` for code blocks
## 0.5.1
### Patch Changes
- cf44221: Adds a Slack invite to social links
- f5d349e: add used fonts from google fonts
## 0.5.0
### Minor Changes
- 8bba4a8: Configure responsive image sizes to align with the launch preset breakpoints.
The set value is `sizes: '(min-width: 1024px) 820px, calc(100vw - 40px)'`.
## 0.4.2 ## 0.4.2
### Patch Changes ### Patch Changes

View File

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

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 123 123" fill="currentColor">
<title>Slack</title>
<path stroke="none" stroke-width="1" stroke-dasharray="none" stroke-linecap="butt" stroke-dashoffset="0" stroke-linejoin="miter" stroke-miterlimit="4" fill-rule="nonzero"
d="M26.4 78.2c0 7.1-5.8 12.9-12.9 12.9S.6 85.3.6 78.2c0-7.1 5.8-12.9 12.9-12.9h12.9v12.9zm6.5 0c0-7.1 5.8-12.9 12.9-12.9s12.9 5.8 12.9 12.9v32.3c0 7.1-5.8 12.9-12.9 12.9s-12.9-5.8-12.9-12.9V78.2zm12.9-51.8c-7.1 0-12.9-5.8-12.9-12.9S38.7.6 45.8.6s12.9 5.8 12.9 12.9v12.9H45.8zm0 6.5c7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H13.5C6.4 58.7.6 52.9.6 45.8s5.8-12.9 12.9-12.9h32.3zM97.6 45.8c0-7.1 5.8-12.9 12.9-12.9 7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H97.6V45.8zm-6.5 0c0 7.1-5.8 12.9-12.9 12.9-7.1 0-12.9-5.8-12.9-12.9V13.5C65.3 6.4 71.1.6 78.2.6c7.1 0 12.9 5.8 12.9 12.9v32.3zM78.2 97.6c7.1 0 12.9 5.8 12.9 12.9 0 7.1-5.8 12.9-12.9 12.9-7.1 0-12.9-5.8-12.9-12.9V97.6h12.9zm0-6.5c-7.1 0-12.9-5.8-12.9-12.9 0-7.1 5.8-12.9 12.9-12.9h32.3c7.1 0 12.9 5.8 12.9 12.9 0 7.1-5.8 12.9-12.9 12.9H78.2z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -7,7 +7,7 @@
body { body {
margin: 0; margin: 0;
font-family: 'Open Sans', sans-serif; font-family: var(--primary-font-family);
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
font-size: 16px; font-size: 16px;
@@ -106,7 +106,7 @@ hr {
#content-wrapper .content-area, #content-wrapper .content-area,
#main-header .content-area, #main-header .content-area,
#main-footer .content-area { #main-footer .content-area {
padding: 0 30px; padding: 0 20px;
} }
#content-wrapper .content-area { #content-wrapper .content-area {
@@ -213,6 +213,14 @@ body[layout^='layout-home'] #main-header a:hover {
margin-right: 50px; margin-right: 50px;
} }
#main-header .content-area > .social-link {
margin-right: 15px;
}
#main-header .content-area > *:last-child {
margin-right: 0;
}
#main-header .search { #main-header .search {
order: 1; order: 1;
} }
@@ -426,11 +434,13 @@ li.current > ul > li.anchor {
/* for blog detail page */ /* for blog detail page */
rocket-navigation h3 { rocket-navigation h3 {
font-family: var(--heading-font-family, var(--primary-font-family));
font-size: 16px; font-size: 16px;
margin: 0 0 7px 0; margin: 0 0 7px 0;
} }
.sidebar-tags h3 { .sidebar-tags h3 {
font-family: var(--heading-font-family, var(--primary-font-family));
margin-top: 30px; margin-top: 30px;
} }
@@ -533,7 +543,7 @@ main > * {
display: inline-block; display: inline-block;
text-align: center; text-align: center;
text-transform: uppercase; text-transform: uppercase;
font-family: 'Montserrat', sans-serif; font-family: var(--secondary-font-family);
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
vertical-align: middle; vertical-align: middle;

View File

@@ -1,6 +1,7 @@
@font-face { @font-face {
font-family: octicons-link; font-family: octicons-link;
src: url(data:font/woff;charset=utf-8;base64,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) src:
url(data:font/woff;charset=utf-8;base64,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)
format('woff'); format('woff');
} }
@@ -61,7 +62,7 @@
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
color: var(--markdown-body, --page-background); color: var(--markdown-body, --page-background);
line-height: 1.5; line-height: 1.5;
font-family: 'Open Sans', sans-serif; font-family: var(--primary-font-family);
font-size: 16px; font-size: 16px;
line-height: 1.5; line-height: 1.5;
word-wrap: break-word; word-wrap: break-word;
@@ -188,6 +189,7 @@
.markdown-body h4, .markdown-body h4,
.markdown-body h5, .markdown-body h5,
.markdown-body h6 { .markdown-body h6 {
font-family: var(--heading-font-family, var(--primary-font-family));
margin-bottom: 0; margin-bottom: 0;
margin-top: 0; margin-top: 0;
} }
@@ -265,7 +267,7 @@
.markdown-body code, .markdown-body code,
.markdown-body pre { .markdown-body pre {
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace; font-family: var(--monospace-font-family);
font-size: 12px; font-size: 12px;
} }
@@ -463,9 +465,9 @@
} }
.markdown-body img { .markdown-body img {
/* background-color: #fff; */
box-sizing: content-box; box-sizing: content-box;
max-width: 100%; max-width: 100%;
width: 100%;
height: auto; height: auto;
} }
@@ -555,57 +557,75 @@ pre[class*='language-'] {
.token.atrule { .token.atrule {
color: var(--markdown-syntax-atrule-color, #d73a49); color: var(--markdown-syntax-atrule-color, #d73a49);
} }
.token.attr-name { .token.attr-name {
color: var(--markdown-syntax-attr-name-color, #d73a49); color: var(--markdown-syntax-attr-name-color, #d73a49);
} }
.token.boolean { .token.boolean {
color: var(--markdown-syntax-boolean-color, #005cc5); color: var(--markdown-syntax-boolean-color, #005cc5);
} }
.token.class-name { .token.class-name {
color: var(--markdown-syntax-class-name-color, #6f42c1); color: var(--markdown-syntax-class-name-color, #6f42c1);
} }
.token.constant { .token.constant {
color: var(--markdown-syntax-constant-color, #005cc5); color: var(--markdown-syntax-constant-color, #005cc5);
} }
.token.entity { .token.entity {
color: var(--markdown-syntax-entity-color, #005cc5); color: var(--markdown-syntax-entity-color, #005cc5);
} }
.token.function { .token.function {
color: var(--markdown-syntax-function-color, #6f42c1); color: var(--markdown-syntax-function-color, #6f42c1);
} }
.token.inserted { .token.inserted {
color: var(--markdown-syntax-inserted-color, #005cc5); color: var(--markdown-syntax-inserted-color, #005cc5);
} }
.token.keyword { .token.keyword {
color: var(--markdown-syntax-keyword-color, #d73a49); color: var(--markdown-syntax-keyword-color, #d73a49);
} }
.token.number { .token.number {
color: var(--markdown-syntax-number-color, #005cc5); color: var(--markdown-syntax-number-color, #005cc5);
} }
.token.operator { .token.operator {
color: var(--markdown-syntax-operator-color, #005cc5); color: var(--markdown-syntax-operator-color, #005cc5);
} }
.token.property { .token.property {
color: var(--markdown-syntax-property-color, #005cc5); color: var(--markdown-syntax-property-color, #005cc5);
} }
.token.punctuation { .token.punctuation {
color: var(--markdown-syntax-punctuation-color, #005cc5); color: var(--markdown-syntax-punctuation-color, #005cc5);
} }
.token.regex { .token.regex {
color: var(--markdown-syntax-regex-color, #032f62); color: var(--markdown-syntax-regex-color, #032f62);
} }
.token.selector { .token.selector {
color: var(--markdown-syntax-selector-color, #22863a); color: var(--markdown-syntax-selector-color, #22863a);
} }
.token.symbol { .token.symbol {
color: var(--markdown-syntax-symbol-color, #005cc5); color: var(--markdown-syntax-symbol-color, #005cc5);
} }
.token.tag { .token.tag {
color: var(--markdown-syntax-tag-color, #22863a); color: var(--markdown-syntax-tag-color, #22863a);
} }
.token.url { .token.url {
color: var(--markdown-syntax-url-color, #005cc5); color: var(--markdown-syntax-url-color, #005cc5);
} }
.token.variable { .token.variable {
color: var(--markdown-syntax-variable-color, #005cc5); color: var(--markdown-syntax-variable-color, #005cc5);
} }
@@ -613,6 +633,7 @@ pre[class*='language-'] {
.language-autohotkey .token.selector { .language-autohotkey .token.selector {
color: var(--markdown-syntax-hotkey-selector-color, #d73a49); color: var(--markdown-syntax-hotkey-selector-color, #d73a49);
} }
.language-autohotkey .token.keyword { .language-autohotkey .token.keyword {
color: var(--markdown-syntax-keyword-color, #22863a); color: var(--markdown-syntax-keyword-color, #22863a);
} }

View File

@@ -14,7 +14,11 @@ html {
--page-background: white; --page-background: white;
--footer-background: rgba(0, 0, 0, 0.1); --footer-background: rgba(0, 0, 0, 0.1);
/* typography */
--text-color: black; --text-color: black;
--primary-font-family: 'Open Sans', sans-serif;
--secondary-font-family: 'Montserrat', sans-serif;
--monospace-font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', 'Courier', monospace;
} }
html.dark { html.dark {
@@ -32,8 +36,10 @@ html.dark {
--page-background: #333; --page-background: #333;
--footer-background: #4f4f4f; --footer-background: #4f4f4f;
/* typography */
--text-color: white; --text-color: white;
/* markdown */
--markdown-octicon-link: white; --markdown-octicon-link: white;
--markdown-syntax-background-color: #a0a0a0; --markdown-syntax-background-color: #a0a0a0;
--markdown-link-color: #fb7881; --markdown-link-color: #fb7881;

View File

@@ -2,10 +2,6 @@
{ {
"name": "Discover", "name": "Discover",
"children": [ "children": [
{
"text": "Blog",
"href": "/blog/"
},
{ {
"text": "Help and Feedback", "text": "Help and Feedback",
"href": "https://github.com/modernweb-dev/rocket/issues" "href": "https://github.com/modernweb-dev/rocket/issues"
@@ -23,19 +19,11 @@
"text": "Twitter", "text": "Twitter",
"href": "https://twitter.com/modern_web_dev" "href": "https://twitter.com/modern_web_dev"
}, },
{
"text": "Slack",
"href": "/about/slack/"
}
] ]
}, },
{ {
"name": "Support", "name": "Support",
"children": [ "children": [
{
"text": "Sponsor",
"href": "/about/sponsor/"
},
{ {
"text": "Contribute", "text": "Contribute",
"href": "https://github.com/modernweb-dev/rocket/blob/master/CONTRIBUTING.md" "href": "https://github.com/modernweb-dev/rocket/blob/master/CONTRIBUTING.md"

View File

@@ -9,6 +9,11 @@ module.exports = function () {
name: 'GitHub', name: 'GitHub',
url: 'https://github.com/modernweb-dev/rocket', url: 'https://github.com/modernweb-dev/rocket',
}, },
{
name: 'Slack',
url:
'https://join.slack.com/t/lit-and-friends/shared_invite/zt-llwznvsy-LZwT13R66gOgnrg12PUGqw',
},
], ],
gitSiteUrl: 'https://github.com/modernweb-dev/rocket', gitSiteUrl: 'https://github.com/modernweb-dev/rocket',
gitBranch: 'master', gitBranch: 'master',

View File

@@ -0,0 +1,10 @@
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&amp;display=optional"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&amp;display=optional"
rel="stylesheet"
/>

View File

@@ -1,6 +1,6 @@
{%- for entry in collections.header %} {%- for entry in collections.header %}
<a href="{{ entry.url | url }}" class=" <a href="{{ entry.url | url }}" class="
{% if entry.url == page.url %} current {% endif %} {% if entry.url == page.url %} current {% endif %}
{% if (page.url.search(entry.url) !== -1) and (page.url !== '/') %} active {% endif %} {% if page.url and page.url.search and (page.url.search(entry.url) !== -1) and (page.url !== '/') %} active {% endif %}
">{{ entry.data.eleventyNavigation.key }}</a> ">{{ entry.data.eleventyNavigation.key }}</a>
{%- endfor %} {%- endfor %}

View File

@@ -1,6 +1,6 @@
<div class="sidebar-bottom"> <div class="sidebar-bottom">
<hr> <hr/> {% include 'partials/_shared/darkSwitch.njk' %}
{% include 'partials/_shared/darkSwitch.njk' %} {% if site.helpUrl %}
<a href="{{ site.helpUrl | url }}">Help and Feedback</a>
<a href="{{ site.helpUrl | url }}">Help and Feedback</a> {% endif %}
</div> </div>

View File

@@ -52,5 +52,13 @@ export function rocketLaunch() {
setupEleventyComputedConfig: [ setupEleventyComputedConfig: [
adjustPluginOptions('layout', { defaultLayout: 'layout-sidebar' }), adjustPluginOptions('layout', { defaultLayout: 'layout-sidebar' }),
], ],
adjustImagePresets: imagePresets => ({
...imagePresets,
responsive: {
...imagePresets.responsive,
widths: [600, 900, 1640],
sizes: '(min-width: 1024px) 820px, calc(100vw - 40px)',
},
}),
}; };
} }

View File

@@ -83,6 +83,17 @@ describe('RocketLaunch preset', () => {
'', '',
' <meta name="twitter:card" content="summary_large_image" />', ' <meta name="twitter:card" content="summary_large_image" />',
'', '',
' <link rel="preconnect" href="https://fonts.googleapis.com" crossorigin />',
'',
' <link',
' href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&amp;display=optional"',
' rel="stylesheet"',
' />',
' <link',
' href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&amp;display=optional"',
' rel="stylesheet"',
' />',
'',
' <link rel="stylesheet" href="/_merged_assets/variables.css" />', ' <link rel="stylesheet" href="/_merged_assets/variables.css" />',
' <link rel="stylesheet" href="/_merged_assets/layout.css" />', ' <link rel="stylesheet" href="/_merged_assets/layout.css" />',
' <link rel="stylesheet" href="/_merged_assets/markdown.css" />', ' <link rel="stylesheet" href="/_merged_assets/markdown.css" />',
@@ -138,6 +149,30 @@ describe('RocketLaunch preset', () => {
' ></path>', ' ></path>',
' </svg>', ' </svg>',
' </a>', ' </a>',
' <a',
' class="social-link"',
' href="https://join.slack.com/t/lit-and-friends/shared_invite/zt-llwznvsy-LZwT13R66gOgnrg12PUGqw"',
' aria-label="Rocket on Slack"',
' rel="noopener noreferrer"',
' target="_blank"',
' >',
' <span class="sr-only">Slack</span>',
'',
' <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 123 123" fill="currentColor">',
' <title>Slack</title>',
' <path',
' stroke="none"',
' stroke-width="1"',
' stroke-dasharray="none"',
' stroke-linecap="butt"',
' stroke-dashoffset="0"',
' stroke-linejoin="miter"',
' stroke-miterlimit="4"',
' fill-rule="nonzero"',
' d="M26.4 78.2c0 7.1-5.8 12.9-12.9 12.9S.6 85.3.6 78.2c0-7.1 5.8-12.9 12.9-12.9h12.9v12.9zm6.5 0c0-7.1 5.8-12.9 12.9-12.9s12.9 5.8 12.9 12.9v32.3c0 7.1-5.8 12.9-12.9 12.9s-12.9-5.8-12.9-12.9V78.2zm12.9-51.8c-7.1 0-12.9-5.8-12.9-12.9S38.7.6 45.8.6s12.9 5.8 12.9 12.9v12.9H45.8zm0 6.5c7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H13.5C6.4 58.7.6 52.9.6 45.8s5.8-12.9 12.9-12.9h32.3zM97.6 45.8c0-7.1 5.8-12.9 12.9-12.9 7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H97.6V45.8zm-6.5 0c0 7.1-5.8 12.9-12.9 12.9-7.1 0-12.9-5.8-12.9-12.9V13.5C65.3 6.4 71.1.6 78.2.6c7.1 0 12.9 5.8 12.9 12.9v32.3zM78.2 97.6c7.1 0 12.9 5.8 12.9 12.9 0 7.1-5.8 12.9-12.9 12.9-7.1 0-12.9-5.8-12.9-12.9V97.6h12.9zm0-6.5c-7.1 0-12.9-5.8-12.9-12.9 0-7.1 5.8-12.9 12.9-12.9h32.3c7.1 0 12.9 5.8 12.9 12.9 0 7.1-5.8 12.9-12.9 12.9H78.2z"',
' />',
' </svg>',
' </a>',
' </div>', ' </div>',
' </header>', ' </header>',
'', '',
@@ -285,6 +320,17 @@ describe('RocketLaunch preset', () => {
'', '',
' <meta name="twitter:card" content="summary_large_image" />', ' <meta name="twitter:card" content="summary_large_image" />',
'', '',
' <link rel="preconnect" href="https://fonts.googleapis.com" crossorigin />',
'',
' <link',
' href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&amp;display=optional"',
' rel="stylesheet"',
' />',
' <link',
' href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&amp;display=optional"',
' rel="stylesheet"',
' />',
'',
' <link rel="stylesheet" href="/_merged_assets/variables.css" />', ' <link rel="stylesheet" href="/_merged_assets/variables.css" />',
' <link rel="stylesheet" href="/_merged_assets/layout.css" />', ' <link rel="stylesheet" href="/_merged_assets/layout.css" />',
' <link rel="stylesheet" href="/_merged_assets/markdown.css" />', ' <link rel="stylesheet" href="/_merged_assets/markdown.css" />',
@@ -340,6 +386,30 @@ describe('RocketLaunch preset', () => {
' ></path>', ' ></path>',
' </svg>', ' </svg>',
' </a>', ' </a>',
' <a',
' class="social-link"',
' href="https://join.slack.com/t/lit-and-friends/shared_invite/zt-llwznvsy-LZwT13R66gOgnrg12PUGqw"',
' aria-label="Rocket on Slack"',
' rel="noopener noreferrer"',
' target="_blank"',
' >',
' <span class="sr-only">Slack</span>',
'',
' <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 123 123" fill="currentColor">',
' <title>Slack</title>',
' <path',
' stroke="none"',
' stroke-width="1"',
' stroke-dasharray="none"',
' stroke-linecap="butt"',
' stroke-dashoffset="0"',
' stroke-linejoin="miter"',
' stroke-miterlimit="4"',
' fill-rule="nonzero"',
' d="M26.4 78.2c0 7.1-5.8 12.9-12.9 12.9S.6 85.3.6 78.2c0-7.1 5.8-12.9 12.9-12.9h12.9v12.9zm6.5 0c0-7.1 5.8-12.9 12.9-12.9s12.9 5.8 12.9 12.9v32.3c0 7.1-5.8 12.9-12.9 12.9s-12.9-5.8-12.9-12.9V78.2zm12.9-51.8c-7.1 0-12.9-5.8-12.9-12.9S38.7.6 45.8.6s12.9 5.8 12.9 12.9v12.9H45.8zm0 6.5c7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H13.5C6.4 58.7.6 52.9.6 45.8s5.8-12.9 12.9-12.9h32.3zM97.6 45.8c0-7.1 5.8-12.9 12.9-12.9 7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H97.6V45.8zm-6.5 0c0 7.1-5.8 12.9-12.9 12.9-7.1 0-12.9-5.8-12.9-12.9V13.5C65.3 6.4 71.1.6 78.2.6c7.1 0 12.9 5.8 12.9 12.9v32.3zM78.2 97.6c7.1 0 12.9 5.8 12.9 12.9 0 7.1-5.8 12.9-12.9 12.9-7.1 0-12.9-5.8-12.9-12.9V97.6h12.9zm0-6.5c-7.1 0-12.9-5.8-12.9-12.9 0-7.1 5.8-12.9 12.9-12.9h32.3c7.1 0 12.9 5.8 12.9 12.9 0 7.1-5.8 12.9-12.9 12.9H78.2z"',
' />',
' </svg>',
' </a>',
' </div>', ' </div>',
' </header>', ' </header>',
'', '',

View File

@@ -1,5 +1,66 @@
# Change Log # Change Log
## 0.8.0
### Minor Changes
- 814b5d2: **BREAKING CHANGE** Stories of `story` and `preview-story` are now rendered to light dom instead of shadow dom to allow usage of a scoped registry for the internal dom
```js
export const story = html`
<p>my story</p>
`;
```
```html
<!-- before -->
<mdjs-story>
#shadow-root (open)
<p>my story</p>
</mdjs-story>
<!-- after -->
<mdjs-story>
<p>my story</p>
</mdjs-story>
```
- e1e96ac: **BREAKING CHANGE** The default renderer for `story` and `preview-story` updated to [lit](https://lit.dev/) 2
If your main lit-html version is 1.x be sure to import html for your story rendering from `@mdjs/mdjs-preview`.
````md
```js script
import { html } from '@mdjs/mdjs-preview';
```
```js preview-story
export const foo = () =>
html`
<demo-element></demo-element>
`;
```
````
### Patch Changes
- Updated dependencies [e1e96ac]
- Updated dependencies [814b5d2]
- Updated dependencies [814b5d2]
- Updated dependencies [e1e96ac]
- @mdjs/mdjs-preview@0.5.0
- @mdjs/mdjs-story@0.3.0
## 0.7.2
### Patch Changes
- ce9b12e: Support importing via es module
```js
import { mdjsProcess } = from '@mdjs/core';
```
## 0.7.1 ## 0.7.1
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mdjs/core", "name": "@mdjs/core",
"version": "0.7.1", "version": "0.8.0",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
@@ -32,6 +32,7 @@
"files": [ "files": [
"*.d.ts", "*.d.ts",
"*.js", "*.js",
"*.mjs",
"dist-types", "dist-types",
"src", "src",
"types" "types"
@@ -43,12 +44,12 @@
"remark" "remark"
], ],
"dependencies": { "dependencies": {
"@mdjs/mdjs-preview": "^0.4.2", "@mdjs/mdjs-preview": "^0.5.0",
"@mdjs/mdjs-story": "^0.2.0", "@mdjs/mdjs-story": "^0.3.0",
"@types/unist": "^2.0.3", "@types/unist": "^2.0.3",
"es-module-lexer": "^0.3.26", "es-module-lexer": "^0.3.26",
"github-markdown-css": "^4.0.0", "github-markdown-css": "^4.0.0",
"plugins-manager": "^0.2.1", "plugins-manager": "^0.2.2",
"rehype-autolink-headings": "^5.0.1", "rehype-autolink-headings": "^5.0.1",
"rehype-prism-template": "^0.4.1", "rehype-prism-template": "^0.4.1",
"rehype-raw": "^5.0.0", "rehype-raw": "^5.0.0",

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