mirror of
https://github.com/modernweb-dev/rocket.git
synced 2026-03-21 15:54:57 +00:00
Compare commits
123 Commits
@rocket/cl
...
@mdjs/core
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f8785a885 | ||
|
|
62637a829e | ||
|
|
81c4d7bf3c | ||
|
|
08181194e2 | ||
|
|
97cb38ccb8 | ||
|
|
26d3de1444 | ||
|
|
1f141058c1 | ||
|
|
08574c9b31 | ||
|
|
e81b77f236 | ||
|
|
456b8e78f0 | ||
|
|
0d7ea015af | ||
|
|
445b02872f | ||
|
|
1a599db3ed | ||
|
|
6b6bed5391 | ||
|
|
30eb822151 | ||
|
|
15a82c0e4d | ||
|
|
0197bee621 | ||
|
|
5c6b9c91eb | ||
|
|
6221e5f9ea | ||
|
|
06741ed729 | ||
|
|
23c164c822 | ||
|
|
c2a76c3f53 | ||
|
|
70bb7a128e | ||
|
|
3c342473d7 | ||
|
|
9e0579ab19 | ||
|
|
de202da0a5 | ||
|
|
509a8d9115 | ||
|
|
42418f2c00 | ||
|
|
cadd8588b0 | ||
|
|
aabe011427 | ||
|
|
e1089c5701 | ||
|
|
9f10386eb2 | ||
|
|
0987a41620 | ||
|
|
7301a0f354 | ||
|
|
5ac6aa6693 | ||
|
|
9f1633cccc | ||
|
|
00f4a91550 | ||
|
|
eb62dd9fd5 | ||
|
|
bb07267289 | ||
|
|
738941afdd | ||
|
|
ef086c7aa3 | ||
|
|
3d22fbb72e | ||
|
|
adf0f1d88f | ||
|
|
4145031162 | ||
|
|
ac58953527 | ||
|
|
7dc3e0f9b0 | ||
|
|
305a657ff5 | ||
|
|
8585e2ad66 | ||
|
|
4585675b00 | ||
|
|
39f4fa7050 | ||
|
|
ccdd4d077e | ||
|
|
a5661b85c2 | ||
|
|
99b12c7c9e | ||
|
|
61bb700c3e | ||
|
|
aa93c2ad89 | ||
|
|
8e9c0a3106 | ||
|
|
1c68a95c3c | ||
|
|
c1876da2ff | ||
|
|
3dde0ab096 | ||
|
|
09caa4bcef | ||
|
|
ddc89e05bb | ||
|
|
7e70d8a327 | ||
|
|
fc8b3a2944 | ||
|
|
ee20047305 | ||
|
|
48dcdd7d6d | ||
|
|
03e15051be | ||
|
|
312d5bec81 | ||
|
|
e31e8be75b | ||
|
|
9978ea7eda | ||
|
|
d91e46b867 | ||
|
|
174217180b | ||
|
|
f6aa1872c2 | ||
|
|
f5a6cbfb97 | ||
|
|
989758ce03 | ||
|
|
fbcedde7a0 | ||
|
|
d72427d889 | ||
|
|
b7d5cbacf3 | ||
|
|
8d8c756607 | ||
|
|
3750c4e7a2 | ||
|
|
5c3eda35a9 | ||
|
|
6910d50bf5 | ||
|
|
a2dc8656db | ||
|
|
e778cd8a3c | ||
|
|
9e3c2f52d9 | ||
|
|
579e8e72a2 | ||
|
|
06ae8693b2 | ||
|
|
cee2b7b04c | ||
|
|
9625b94d39 | ||
|
|
1f79d7a047 | ||
|
|
bf99541951 | ||
|
|
8df9a3e9c3 | ||
|
|
1b9559f2a5 | ||
|
|
8eede4b16b | ||
|
|
2294ccf4a2 | ||
|
|
3b1a0cf26a | ||
|
|
cf442215a9 | ||
|
|
41049f3908 | ||
|
|
2b5c61d19c | ||
|
|
f5d349e256 | ||
|
|
ce0b00e7a1 | ||
|
|
83286a99de | ||
|
|
6cabdba5f6 | ||
|
|
f5f2d69d0c | ||
|
|
795a3613af | ||
|
|
bcf8f4fe83 | ||
|
|
5330740cb3 | ||
|
|
2edd61beaa | ||
|
|
2a5fc08f35 | ||
|
|
43a7ca10c3 | ||
|
|
da39fa72f3 | ||
|
|
a0e8edfbb9 | ||
|
|
50434293bb | ||
|
|
f08f92615b | ||
|
|
1949b1e1cb | ||
|
|
340bf8e653 | ||
|
|
eae200708d | ||
|
|
f707f636fa | ||
|
|
814b5d29ad | ||
|
|
e1e96acceb | ||
|
|
7543a129cf | ||
|
|
60e85a17a7 | ||
|
|
fd8f97859a | ||
|
|
56fdb0cbd4 |
@@ -10,3 +10,5 @@ _site
|
||||
_site-dev
|
||||
__output
|
||||
__output-dev
|
||||
|
||||
docs/_merged*
|
||||
|
||||
@@ -8,25 +8,25 @@ First, create a fork of the [modernweb-dev/rocket](https://github.com/modernweb-
|
||||
|
||||
Next, clone our repository onto your computer.
|
||||
|
||||
```sh
|
||||
```shell
|
||||
git clone git@github.com:modernweb-dev/rocket.git
|
||||
```
|
||||
|
||||
Once cloning is complete, change directory to the repository.
|
||||
|
||||
```sh
|
||||
```shell
|
||||
cd rocket
|
||||
```
|
||||
|
||||
Now add your fork as a remote (replacing YOUR_USERNAME with your GitHub username).
|
||||
|
||||
```sh
|
||||
```shell
|
||||
git remote add fork git@github.com:<YOUR_USERNAME>/rocket.git
|
||||
```
|
||||
|
||||
Create a new local branch.
|
||||
|
||||
```sh
|
||||
```shell
|
||||
git checkout -b my-awesome-fix
|
||||
```
|
||||
|
||||
@@ -34,7 +34,7 @@ git checkout -b my-awesome-fix
|
||||
|
||||
Now that you have cloned the repository, ensure you have [yarn](https://classic.yarnpkg.com/lang/en/) installed, then run the following commands to set up the development environment.
|
||||
|
||||
```sh
|
||||
```shell
|
||||
yarn install
|
||||
```
|
||||
|
||||
@@ -69,7 +69,7 @@ This documents your intent to release, and allows you to specify a message that
|
||||
|
||||
Run
|
||||
|
||||
```sh
|
||||
```shell
|
||||
yarn changeset
|
||||
```
|
||||
|
||||
@@ -92,7 +92,7 @@ Exceptions:
|
||||
Commit messages must follow the [conventional commit format](https://www.conventionalcommits.org/en/v1.0.0/)
|
||||
Modern-web uses package name as scope. So for example if you fix a _terrible bug_ in the package `@web/test-runner`, the commit message should look like this:
|
||||
|
||||
```sh
|
||||
```shell
|
||||
fix(test-runner): fix terrible bug
|
||||
```
|
||||
|
||||
@@ -100,7 +100,7 @@ fix(test-runner): fix terrible bug
|
||||
|
||||
Now it's time to push your branch that contains your committed changes to your fork.
|
||||
|
||||
```sh
|
||||
```shell
|
||||
git push -u fork my-awesome-fix
|
||||
```
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
src="https://img.shields.io/badge/twitter-@modern_web_dev-1DA1F3?style=flat-square"
|
||||
alt="Follow @modern_web_dev on Twitter"
|
||||
/></a>
|
||||
<a href="https://open.vscode.dev/modernweb-dev/rocket"
|
||||
><img
|
||||
src="https://open.vscode.dev/badges/open-in-vscode.svg"
|
||||
alt="Open in VS Code"
|
||||
/></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
1
docs/.eleventyignore
Normal file
1
docs/.eleventyignore
Normal file
@@ -0,0 +1 @@
|
||||
*.docs.md
|
||||
1
docs/_assets/_static/logos/npm.svg
Normal file
1
docs/_assets/_static/logos/npm.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="n" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#c12127;}.cls-2{fill:#fff;}</style></defs><title>n</title><path class="cls-1" d="M0,16V0H16V16ZM3,3V13H8V5h3v8h2V3Z"/><path class="cls-2" d="M3,3H13V13H11V5H8v8H3Z"/></svg>
|
||||
|
After Width: | Height: | Size: 287 B |
3
docs/_assets/_static/logos/pnpm.svg
Normal file
3
docs/_assets/_static/logos/pnpm.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="76.58987244897958 44 164.00775510204068 164" width="160.01" height="160"><defs><path d="M237.6 95L187.6 95L187.6 45L237.6 45L237.6 95Z" id="arNRoK435"></path><path d="M182.59 95L132.59 95L132.59 45L182.59 45L182.59 95Z" id="a3H2WU7Px"></path><path d="M127.59 95L77.59 95L77.59 45L127.59 45L127.59 95Z" id="b1DInM56vl"></path><path d="M237.6 150L187.6 150L187.6 100L237.6 100L237.6 150Z" id="a7LFlgQIwu"></path><path d="M182.59 150L132.59 150L132.59 100L182.59 100L182.59 150Z" id="amwLiZcuo"></path><path d="M182.59 205L132.59 205L132.59 155L182.59 155L182.59 205Z" id="f3Peu5RWan"></path><path d="M237.6 205L187.6 205L187.6 155L237.6 155L237.6 205Z" id="a6DXBfqPa"></path><path d="M127.59 205L77.59 205L77.59 155L127.59 155L127.59 205Z" id="c1GWSTH1z7"></path></defs><g><g><use xlink:href="#arNRoK435" opacity="1" fill="#f9ad00" fill-opacity="1"></use></g><g><use xlink:href="#a3H2WU7Px" opacity="1" fill="#f9ad00" fill-opacity="1"></use></g><g><use xlink:href="#b1DInM56vl" opacity="1" fill="#f9ad00" fill-opacity="1"></use></g><g><use xlink:href="#a7LFlgQIwu" opacity="1" fill="#f9ad00" fill-opacity="1"></use></g><g><use xlink:href="#amwLiZcuo" opacity="1" fill="#4e4e4e" fill-opacity="1"></use></g><g><use xlink:href="#f3Peu5RWan" opacity="1" fill="#4e4e4e" fill-opacity="1"></use></g><g><use xlink:href="#a6DXBfqPa" opacity="1" fill="#4e4e4e" fill-opacity="1"></use></g><g><use xlink:href="#c1GWSTH1z7" opacity="1" fill="#4e4e4e" fill-opacity="1"></use></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
docs/_assets/_static/logos/yarn.svg
Normal file
1
docs/_assets/_static/logos/yarn.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 518 518"><style>.st0{fill:#2c8ebb}.st1{fill:#fff}</style><path class="st0" d="M259 0c143 0 259 116 259 259S402 518 259 518 0 402 0 259 116 0 259 0z"/><path class="st1" d="M435.2 337.5c-1.8-14.2-13.8-24-29.2-23.8-23 .3-42.3 12.2-55.1 20.1-5 3.1-9.3 5.4-13 7.1.8-11.6.1-26.8-5.9-43.5-7.3-20-17.1-32.3-24.1-39.4 8.1-11.8 19.2-29 24.4-55.6 4.5-22.7 3.1-58-7.2-77.8-2.1-4-5.6-6.9-10-8.1-1.8-.5-5.2-1.5-11.9.4C293.1 96 289.6 93.8 286.9 92c-5.6-3.6-12.2-4.4-18.4-2.1-8.3 3-15.4 11-22.1 25.2-1 2.1-1.9 4.1-2.7 6.1-12.7.9-32.7 5.5-49.6 23.8-2.1 2.3-6.2 4-10.5 5.6h.1c-8.8 3.1-12.8 10.3-17.7 23.3-6.8 18.2.2 36.1 7.1 47.7-9.4 8.4-21.9 21.8-28.5 37.5-8.2 19.4-9.1 38.4-8.8 48.7-7 7.4-17.8 21.3-19 36.9-1.6 21.8 6.3 36.6 9.8 42 1 1.6 2.1 2.9 3.3 4.2-.4 2.7-.5 5.6.1 8.6 1.3 7 5.7 12.7 12.4 16.3 13.2 7 31.6 10 45.8 2.9 5.1 5.4 14.4 10.6 31.3 10.6h1c4.3 0 58.9-2.9 74.8-6.8 7.1-1.7 12-4.7 15.2-7.4 10.2-3.2 38.4-12.8 65-30 18.8-12.2 25.3-14.8 39.3-18.2 13.6-3.3 22.1-15.7 20.4-29.4zm-23.8 14.7c-16 3.8-24.1 7.3-43.9 20.2-30.9 20-64.7 29.3-64.7 29.3s-2.8 4.2-10.9 6.1c-14 3.4-66.7 6.3-71.5 6.4-12.9.1-20.8-3.3-23-8.6-6.7-16 9.6-23 9.6-23s-3.6-2.2-5.7-4.2c-1.9-1.9-3.9-5.7-4.5-4.3-2.5 6.1-3.8 21-10.5 27.7-9.2 9.3-26.6 6.2-36.9.8-11.3-6 .8-20.1.8-20.1s-6.1 3.6-11-3.8c-4.4-6.8-8.5-18.4-7.4-32.7 1.2-16.3 19.4-32.1 19.4-32.1s-3.2-24.1 7.3-48.8c9.5-22.5 35.1-40.6 35.1-40.6s-21.5-23.8-13.5-45.2c5.2-14 7.3-13.9 9-14.5 6-2.3 11.8-4.8 16.1-9.5 21.5-23.2 48.9-18.8 48.9-18.8s13-39.5 25-31.8c3.7 2.4 17 32 17 32s14.2-8.3 15.8-5.2c8.6 16.7 9.6 48.6 5.8 68-6.4 32-22.4 49.2-28.8 60-1.5 2.5 17.2 10.4 29 43.1 10.9 29.9 1.2 55 2.9 57.8.3.5.4.7.4.7s12.5 1 37.6-14.5c13.4-8.3 29.3-17.6 47.4-17.8 17.5-.3 18.4 20.2 5.2 23.4z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -1,3 +1,41 @@
|
||||
:not(rocket-navigation):not(:defined) {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
rocket-navigation,
|
||||
header {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
}
|
||||
|
||||
code-tabs[collection="package-managers"] {
|
||||
--code-tabs-icon-height: 18px;
|
||||
}
|
||||
|
||||
.call-to-action {
|
||||
background: var(--button-one) !important;
|
||||
text-shadow: none !important;
|
||||
border-radius: 5px !important;
|
||||
padding-top: 15px !important;
|
||||
padding-bottom: 15px !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.call-to-action:hover,
|
||||
.call-to-action:focus,
|
||||
.call-to-action:active {
|
||||
background: var(--button-one-hover) !important;
|
||||
}
|
||||
|
||||
.call-to-action:nth-child(2) {
|
||||
background: var(--button-two) !important;
|
||||
}
|
||||
|
||||
.call-to-action:nth-child(2):hover,
|
||||
.call-to-action:nth-child(2):focus,
|
||||
.call-to-action:nth-child(2):active {
|
||||
background: var(--button-two-hover) !important;
|
||||
}
|
||||
|
||||
body[layout^='layout-home'] .markdown-body .call-to-action:nth-of-type(2) {
|
||||
--primary-color: #222;
|
||||
--primary-color-lighter: #333;
|
||||
@@ -11,11 +49,3 @@ body[layout^='layout-home'] .markdown-body .call-to-action:nth-of-type(2) {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
|
||||
rocket-navigation {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
}
|
||||
|
||||
header {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
}
|
||||
|
||||
141
docs/_assets/theme.css
Normal file
141
docs/_assets/theme.css
Normal file
@@ -0,0 +1,141 @@
|
||||
html {
|
||||
--button-one-hover: #436eff;
|
||||
--button-one: #2758ff;
|
||||
--button-two-hover: #444;
|
||||
--button-two: black;
|
||||
--contrast-color-dark: #1d3557;
|
||||
--contrast-color-light: #fff;
|
||||
--footer-background: rgba(0, 0, 0, 0.02);
|
||||
--header-color: white;
|
||||
--markdown-link-color: #2758ff;
|
||||
--markdown-syntax-background-color: #f9f9f9;
|
||||
--markdown-table-row-odd-background-color: #efefef;
|
||||
--owc-active-color: #2758ff;
|
||||
--owc-hover-color: #436eff;
|
||||
--page-background: white;
|
||||
--primary-color-accent: #cee5f6;
|
||||
--primary-color-darker: #1a5285;
|
||||
--primary-color-lighter: #449ad7;
|
||||
--primary-color: rgb(44, 62, 80);
|
||||
--primary-lines-color: #ccc;
|
||||
--primary-text-color: #2c3e50;
|
||||
--primary-text-inverse-color: #eee;
|
||||
--switch-unselected-color: #808080;
|
||||
--switch-selected-color: #42b983;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
--header-color: #2f3136;
|
||||
--footer-background: rgba(255, 255, 255, 0.1);
|
||||
--page-background: #36393e;
|
||||
--text-color: #eee;
|
||||
--primary-text-color: #eee;
|
||||
--primary-color: white;
|
||||
--primary-color-lighter: #449ad7;
|
||||
--primary-color-darker: #1a5285;
|
||||
--primary-color-accent: #cee5f6;
|
||||
--contrast-color-light: #fff;
|
||||
--contrast-color-dark: #1d3557;
|
||||
--primary-lines-color: #333;
|
||||
--owc-active-color: #41ffb0;
|
||||
--owc-hover-color: #6dffc2;
|
||||
--button-one: #9b03fe;
|
||||
--button-one-hover: #a724ff;
|
||||
--button-two: black;
|
||||
--button-two-hover: rgb(36, 36, 36);
|
||||
--rocket-search-background-color: #4a4d52;
|
||||
--rocket-search-highlight-color: #41ffb0;
|
||||
--rocket-search-hover-background-color: #6b717a;
|
||||
--rocket-search-fill-color: #fff;
|
||||
--primary-text-inverse-color: #2c3e50;
|
||||
--switch-unselected-color: #808080;
|
||||
--switch-selected-color: #42b983;
|
||||
|
||||
/* Markdown */
|
||||
--markdown-octicon-link: var(--primary-text-color);
|
||||
--markdown-link-color: #41ffb0;
|
||||
--markdown-divider-color: #e1e4e8;
|
||||
--markdown-blockquote-border-color: #dfe2e5;
|
||||
--markdown-blockquote-color: #90aac7;
|
||||
--markdown-kbd-background-color: #fafbfc;
|
||||
--markdown-kbd-border-color: #c6cbd1;
|
||||
--markdown-kbd-border-bottom-color: #959da5;
|
||||
--markdown-kbd-color: #444d56;
|
||||
--markdown-heading-color-6: #6a737d;
|
||||
--markdown-table-background-color: var(--markdown-syntax-background-color);
|
||||
--markdown-table-row-odd-background-color: var(--markdown-kbd-color);
|
||||
--markdown-table-border-color: transparent;
|
||||
--markdown-code-background-color: rgba(27, 31, 35, 0.05);
|
||||
--markdown-pre-background-color: rgb(49, 49, 49);
|
||||
|
||||
/* syntax */
|
||||
--markdown-syntax-color: #f8f8f2;
|
||||
--markdown-syntax-background-color: #2e3440;
|
||||
--markdown-syntax-atrule-color: #88c0d0;
|
||||
--markdown-syntax-attr-name-color: #a3be8c;
|
||||
--markdown-syntax-attr-value-color: #88c0d0;
|
||||
--markdown-syntax-builtin-color: #a3be8c;
|
||||
--markdown-syntax-boolean-color: #81a1c1;
|
||||
--markdown-syntax-class-name-color: #88c0d0;
|
||||
--markdown-syntax-constant-color: #81a1c1;
|
||||
--markdown-syntax-char-color: #a3be8c;
|
||||
--markdown-syntax-deleted-color: #81a1c1;
|
||||
--markdown-syntax-entity-color: #81a1c1;
|
||||
--markdown-syntax-function-color: #88c0d0;
|
||||
--markdown-syntax-inserted-color: #a3be8c;
|
||||
--markdown-syntax-keyword-color: #81a1c1;
|
||||
--markdown-syntax-number-color: #b48ead;
|
||||
--markdown-syntax-operator-color: #81a1c1;
|
||||
--markdown-syntax-property-color: #81a1c1;
|
||||
--markdown-syntax-punctuation-color: #81a1c1;
|
||||
--markdown-syntax-regex-color: #81a1c1;
|
||||
--markdown-syntax-important-color: #81a1c1;
|
||||
--markdown-syntax-selector-color: #a3be8c;
|
||||
--markdown-syntax-symbol-color: #81a1c1;
|
||||
--markdown-syntax-string-color: #a3be8c;
|
||||
--markdown-syntax-tag-color: #81a1c1;
|
||||
--markdown-syntax-url-color: #81a1c1;
|
||||
--markdown-syntax-variable-color: #81a1c1;
|
||||
--markdown-syntax-hotkey-selector-color: #d73a49;
|
||||
--markdown-syntax-keyword-color: #22863a;
|
||||
--markdown-syntax-background-color: rgb(27, 29, 35);
|
||||
--markdown-syntax-atrule-color: rgb(198, 120, 221);
|
||||
--markdown-syntax-attr-name-color: rgb(198, 120, 221);
|
||||
--markdown-syntax-boolean-color: rgb(209, 154, 102);
|
||||
--markdown-syntax-class-name-color: rgb(97, 175, 239);
|
||||
--markdown-syntax-constant-color: rgb(220, 220, 170);
|
||||
--markdown-syntax-entity-color: rgb(220, 220, 170);
|
||||
--markdown-syntax-function-color: rgb(97, 175, 239);
|
||||
--markdown-syntax-inserted-color: rgb(220, 220, 170);
|
||||
--markdown-syntax-keyword-color: rgb(198, 120, 221);
|
||||
--markdown-syntax-number-color: rgb(220, 220, 170);
|
||||
--markdown-syntax-operator-color: rgb(220, 220, 170);
|
||||
--markdown-syntax-property-color: rgb(220, 220, 170);
|
||||
--markdown-syntax-punctuation-color: white;
|
||||
--markdown-syntax-regex-color: rgb(209, 154, 102);
|
||||
--markdown-syntax-selector-color: rgb(86, 156, 214);
|
||||
--markdown-syntax-symbol-color: rgb(220, 220, 170);
|
||||
--markdown-syntax-tag-color: rgb(86, 156, 214);
|
||||
--markdown-syntax-url-color: rgb(220, 220, 170);
|
||||
--markdown-syntax-variable-color: rgb(220, 220, 170);
|
||||
}
|
||||
|
||||
.string {
|
||||
color: rgb(152, 195, 121);
|
||||
}
|
||||
|
||||
.comment {
|
||||
color: #7d7d7d;
|
||||
}
|
||||
|
||||
.language-css {
|
||||
--markdown-syntax-string-color: #81a1c1;
|
||||
}
|
||||
}
|
||||
|
||||
body[layout='home'] .markdown-body .call-to-action:nth-of-type(2) {
|
||||
--primary-color: #222;
|
||||
--primary-color-lighter: #333;
|
||||
--primary-color-darker: #000;
|
||||
}
|
||||
@@ -9,6 +9,11 @@ module.exports = async function () {
|
||||
name: 'GitHub',
|
||||
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',
|
||||
gitBranch: 'main',
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<link rel="stylesheet" href="{{ '/_assets/theme.css' | asset | url }}">
|
||||
@@ -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" />
|
||||
|
||||
<link rel="stylesheet" href="{{ '/_assets/body.css' | asset | url }}" mdjs-use>
|
||||
|
||||
@@ -140,7 +140,7 @@ The features so far are:
|
||||
|
||||
It checks your final HTML output so you need to execute it after your Static Site Generator.
|
||||
|
||||
```
|
||||
```shell
|
||||
npx check-html-links _site
|
||||
```
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Configuration >> Computed Config ||20
|
||||
# Configuration >> Computed Config || 20
|
||||
|
||||
If you want to add data that depends on other data then you can do it via [Eleventy's computed data](https://www.11ty.dev/docs/data-computed/).
|
||||
|
||||
@@ -8,25 +8,23 @@ Rocket exposes it via `setupEleventyComputedConfig`.
|
||||
|
||||
Let's say you want to add a `Welcome to the contact page` everywhere. (A filter might be a better choice, but it's a good example of the concept.)
|
||||
|
||||
👉 `rocket.config.mjs` (or your theme config file)
|
||||
👉 `rocket.config.js` (or your theme config file)
|
||||
|
||||
```js
|
||||
<!-- prettier-ignore-start -->
|
||||
```js copy
|
||||
import { addPlugin } from 'plugins-manager';
|
||||
|
||||
/** @type {Partial<import("../../../types/main").RocketCliOptions>} */
|
||||
const config = {
|
||||
/** @type {import('@rocket/cli').RocketCliOptions} */
|
||||
export default ({
|
||||
setupEleventyComputedConfig: [
|
||||
addPlugin({ name: 'greeting', plugin: data => `Welcome to the ${data.title} page.` }),
|
||||
],
|
||||
};
|
||||
|
||||
export default config;
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
{% raw %}
|
||||
Now you can use {{ greeting }} everywhere.
|
||||
{% endraw %}
|
||||
And it will be correctly replaced with a Welcome and the page title.
|
||||
Now you can use {% raw %}{{ greeting }}{% endraw %} everywhere,
|
||||
and it will be correctly replaced with a Welcome and the page title.
|
||||
|
||||
## Default Available Configs
|
||||
|
||||
|
||||
@@ -88,8 +88,10 @@ The default preset for regular markdown content is available as `responsive`.
|
||||
|
||||
👉 `rocket.config.js`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
export default {
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
imagePresets: {
|
||||
responsive: {
|
||||
widths: [300, 820],
|
||||
@@ -97,15 +99,97 @@ export default {
|
||||
sizes: '(min-width: 1024px) 820px, calc(100vw - 20px)',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Ignoring Images
|
||||
|
||||
Files ending in `.svg` or that include `rocket-ignore.` will remain untouched.
|
||||
|
||||
For example
|
||||
|
||||
```md
|
||||

|
||||

|
||||

|
||||
```
|
||||
|
||||
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`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
imagePresets: {
|
||||
responsive: {
|
||||
// ...
|
||||
ignore: ({ src }) =>
|
||||
src.endsWith('.jpeg') || src.endsWith('svg') || src.includes('rocket-unresponsive.'),
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
With that setting we get the following behavior
|
||||
|
||||
```md
|
||||

|
||||

|
||||

|
||||
```
|
||||
|
||||
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
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
export default {
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
imagePresets: {
|
||||
'my-image-preset': {
|
||||
widths: [30, 60],
|
||||
@@ -113,8 +197,9 @@ export default {
|
||||
sizes: '(min-width: 1024px) 30px, 60px',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
Once that `imagePreset` is defined you can use it by adding it to any `img` tag.
|
||||
|
||||
@@ -156,15 +241,18 @@ If you want to add `webp` (or replace `avif` with it) you can do so by setting t
|
||||
|
||||
👉 `rocket.config.js`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
export default {
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
imagePresets: {
|
||||
responsive: {
|
||||
formats: ['avif', 'webp', 'jpeg'],
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Default widths
|
||||
|
||||
@@ -186,16 +274,19 @@ If you want to add more widths you can add them to `widths`.
|
||||
|
||||
👉 `rocket.config.js`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
export default {
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
imagePresets: {
|
||||
responsive: {
|
||||
widths: [300, 600, 900, 1200, 1640],
|
||||
sizes: '(min-width: 1024px) 820px, calc(100vw - 20px)',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<inline-notification type="tip">
|
||||
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
# Configuration >> Overview ||10
|
||||
# Configuration >> Overview || 10
|
||||
|
||||
The configuration file is `rocket.config.js` or `rocket.config.mjs`.
|
||||
|
||||
The config files consist of the following parts:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
|
||||
export default {
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
presets: [rocketLaunch()],
|
||||
emptyOutputDir: true,
|
||||
pathPrefix: 'subfolder-only-for-build',
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
Rocket is primarily build around plugins for each of its systems.
|
||||
|
||||
New plugins can be added and all default plugins can be adjusted or even removed by using the following functions.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
export default {
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
// add remark/unified plugin to the Markdown processing (e.g. enable special code blocks)
|
||||
setupUnifiedPlugins: [],
|
||||
|
||||
@@ -40,8 +45,9 @@ export default {
|
||||
|
||||
// add a plugin to the cli (e.g. a new command like "rocket my-command")
|
||||
setupCliPlugins: [],
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Adding Rollup Plugins
|
||||
|
||||
@@ -55,19 +61,19 @@ You can accomplish this with Rollup and dev server plugins. Make sure to add bot
|
||||
|
||||
For these cases you can use `setupDevAndBuildPlugins`, which will automatically add the plugin for you to both Rollup and dev-server:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
import json from '@rollup/plugin-json';
|
||||
import { addPlugin } from 'plugins-manager';
|
||||
|
||||
/** @type {Partial<import("@rocket/cli").RocketCliOptions>} */
|
||||
const config = {
|
||||
/** @type {import('@rocket/cli').RocketCliOptions} */
|
||||
export default ({
|
||||
setupDevAndBuildPlugins: [
|
||||
addPlugin({ name: 'json', plugin: json, location: 'top', options: { my: 'settings' } }),
|
||||
],
|
||||
};
|
||||
|
||||
export default config;
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
This will add the Rollup plugin `json` with the id `json` at the top of the plugin list of Rollup and the dev server. It needs to be at the top so further plugins down the line can work with JSON imports.
|
||||
For the Dev Server the plugins are automatically wrapped by `@web/dev-server-rollup`. Note that [not all Rollup plugins](https://modern-web.dev/docs/dev-server/plugins/rollup/#compatibility-with-rollup-plugins) will work with the dev-server.
|
||||
@@ -76,13 +82,85 @@ For the Dev Server the plugins are automatically wrapped by `@web/dev-server-rol
|
||||
|
||||
All plugins which are either default or are added via a preset can still be adjusted by using `adjustPluginOptions`.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
import { adjustPluginOptions } from 'plugins-manager';
|
||||
|
||||
/** @type {Partial<import("@rocket/cli").RocketCliOptions>} */
|
||||
const config = {
|
||||
/** @type {import('@rocket/cli').RocketCliOptions} */
|
||||
export default ({
|
||||
setupDevAndBuildPlugins: [adjustPluginOptions('json', { my: 'overwrite settings' })],
|
||||
};
|
||||
|
||||
export default config;
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Lifecycle
|
||||
|
||||
You can hook into the rocket lifecycle by specifying a function for `before11ty`. This function runs before 11ty calls it's write method. If it is an async function, Rocket will await it's promise.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
async before11ty() {
|
||||
await copyDataFiles();
|
||||
},
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Advanced
|
||||
|
||||
Sometimes you need even more control over specific settings.
|
||||
|
||||
### Rollup
|
||||
|
||||
For example if you wanna add an `acron` plugin to rollup
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
import { importAssertions } from 'acorn-import-assertions';
|
||||
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
rollup: config => ({
|
||||
...config,
|
||||
acornInjectPlugins: [importAssertions],
|
||||
}),
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
### Eleventy
|
||||
|
||||
For example to add custom filter you can access the eleventy config directly
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
eleventy: eleventyConfig => {
|
||||
eleventyConfig.addFilter('value', value => `prefix${value}`);
|
||||
},
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
You even have access to the full rocketConfig if you for example want to create filters that behave differently during start/build.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
eleventy: (config, rocketConfig) => {
|
||||
config.addFilter('conditional-resolve', value => {
|
||||
if (rocketConfig.command === 'build') {
|
||||
return `build:${value}`;
|
||||
}
|
||||
if (rocketConfig.command === 'start') {
|
||||
return `start:${value}`;
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
@@ -12,11 +12,14 @@ Changing the service worker file name can be quite a hassle so you can adjust ge
|
||||
|
||||
👉 `rocket.config.js`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
export default {
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
serviceWorkerName: 'my-service-worker-name.js',
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Meet the Service Worker
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Use mdjs in your Eleventy site.
|
||||
|
||||
## Setup
|
||||
|
||||
```
|
||||
```shell
|
||||
npm install @rocket/eleventy-plugin-mdjs
|
||||
```
|
||||
|
||||
|
||||
@@ -7,6 +7,25 @@ eleventyNavigation:
|
||||
|
||||
Here you will find all the details for each of the packages/systems we offer.
|
||||
|
||||
You should check out:
|
||||
## Contents
|
||||
|
||||
- [@rocket/launch](./presets/launch.md) which is our default preset
|
||||
- [Configuration](./configuration/)
|
||||
- [Overview](./configuration/overview/)
|
||||
- [Computed Config](./configuration/computed-config/)
|
||||
- [Service Worker](./configuration/service-worker/)
|
||||
- [Images](./configuration/images/)
|
||||
- [Presets](./presets/)
|
||||
- [Joining Blocks](./presets/joining-blocks/)
|
||||
- [`@rocket/launch`](./presets/launch/)
|
||||
- [`@rocket/search`](./presets/search/)
|
||||
- [`@rocket/blog`](./presets/blog/)
|
||||
- [Markdown JavaScript](./markdown-javascript/)
|
||||
- [Overview](./markdown-javascript/overview/)
|
||||
- [Preview](./markdown-javascript/preview/)
|
||||
- [Story](./markdown-javascript/story/)
|
||||
- [Eleventy Plugins](./eleventy-plugins/)
|
||||
- [Markdown JavaScript (mdjs)](./eleventy-plugins/mdjs-unified/)
|
||||
- [Tools](./tools/)
|
||||
- [Plugins Manager](./tools/plugins-manager/)
|
||||
- [Rollup Config](./tools/rollup-config/)
|
||||
- [Check HTML Links ](./tools/check-html-links/)
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# 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.
|
||||
|
||||
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:
|
||||
|
||||
````md
|
||||
```js script
|
||||
import '@mdjs/mdjs-story/define';
|
||||
import '@mdjs/mdjs-preview/define';
|
||||
```
|
||||
````
|
||||
|
||||
### Story
|
||||
|
||||
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).
|
||||
|
||||
```js script
|
||||
import '@mdjs/mdjs-story/define';
|
||||
import '@mdjs/mdjs-preview/define';
|
||||
import { html } from 'lit-html';
|
||||
```
|
||||
|
||||
```js preview-story
|
||||
import 'demo-wc-card/demo-wc-card.js';
|
||||
export const header = () => {
|
||||
@@ -130,6 +123,68 @@ export const header = () => {
|
||||
};
|
||||
```
|
||||
|
||||
```js story-code
|
||||
// not defined for android
|
||||
```
|
||||
|
||||
```js story-code
|
||||
// not defined for ios
|
||||
```
|
||||
|
||||
#### Story Code
|
||||
|
||||
If your preview is followed by a code blocks marked as `story-code` then those will be shown when switching between multiple platforms
|
||||
|
||||
````md
|
||||
```js preview-story
|
||||
// will be visible when platform web is selected
|
||||
export const JsPreviewStory = () => html` <demo-wc-card>JS Preview Story</demo-wc-card> `;
|
||||
```
|
||||
|
||||
```xml story-code
|
||||
<!-- will be visible when platform android is selected -->
|
||||
<Button
|
||||
android:id="@+id/demoWcCard"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Android Code"
|
||||
style="@style/Widget.FooComponents.Demo.Wc.Card"
|
||||
/>
|
||||
```
|
||||
|
||||
```swift story-code
|
||||
// will be visible when platform ios is selected
|
||||
import DemoWc.Card
|
||||
|
||||
let card = DemoWcButton()
|
||||
```
|
||||
````
|
||||
|
||||
See it in action by opening up the code block and switching platforms
|
||||
|
||||
```js preview-story
|
||||
// will be visible when platform web is selected
|
||||
export const JsPreviewStory = () => html` <demo-wc-card>JS Preview Story</demo-wc-card> `;
|
||||
```
|
||||
|
||||
```xml story-code
|
||||
<!-- will be visible when platform android is selected -->
|
||||
<Button
|
||||
android:id="@+id/demoWcCard"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Android Code"
|
||||
style="@style/Widget.FooComponents.Demo.Wc.Card"
|
||||
/>
|
||||
```
|
||||
|
||||
```swift story-code
|
||||
// will be visible when platform ios is selected
|
||||
import DemoWc.Card
|
||||
|
||||
let card = DemoWcButton()
|
||||
```
|
||||
|
||||
## Supported Systems
|
||||
|
||||
### Storybook
|
||||
|
||||
@@ -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
|
||||
|
||||
```js script
|
||||
import { html } from 'lit-html';
|
||||
import { html } from '@mdjs/mdjs-preview';
|
||||
import './assets/demo-element.js';
|
||||
```
|
||||
|
||||
@@ -25,7 +25,7 @@ import './assets/demo-element.js';
|
||||
|
||||
````md
|
||||
```js script
|
||||
import { html } from 'lit-html';
|
||||
import { html } from '@mdjs/mdjs-preview';
|
||||
import './assets/demo-element.js';
|
||||
```
|
||||
|
||||
@@ -40,6 +40,68 @@ will result in
|
||||
export const foo = () => html` <demo-element></demo-element> `;
|
||||
```
|
||||
|
||||
```js story-code
|
||||
// not defined for android
|
||||
```
|
||||
|
||||
```js story-code
|
||||
// not defined for ios
|
||||
```
|
||||
|
||||
#### Story Code
|
||||
|
||||
If your preview is followed by a code blocks marked as `story-code` then those will be shown when switching between multiple platforms
|
||||
|
||||
````md
|
||||
```js preview-story
|
||||
// will be visible when platform web is selected
|
||||
export const JsPreviewStory = () => html` <demo-element></demo-element> `;
|
||||
```
|
||||
|
||||
```xml story-code
|
||||
<!-- will be visible when platform android is selected -->
|
||||
<Button
|
||||
android:id="@+id/demoElement"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Android Code"
|
||||
style="@style/Widget.Demo.Element"
|
||||
/>
|
||||
```
|
||||
|
||||
```swift story-code
|
||||
// will be visible when platform ios is selected
|
||||
import Demo.Element
|
||||
|
||||
let card = DemoElement()
|
||||
```
|
||||
````
|
||||
|
||||
See it in action by opening up the code block and switching platforms
|
||||
|
||||
```js preview-story
|
||||
// will be visible when platform web is selected
|
||||
export const JsPreviewStory = () => html` <demo-element></demo-element> `;
|
||||
```
|
||||
|
||||
```xml story-code
|
||||
<!-- will be visible when platform android is selected -->
|
||||
<Button
|
||||
android:id="@+id/demoElement"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Android Code"
|
||||
style="@style/Widget.Demo.Element"
|
||||
/>
|
||||
```
|
||||
|
||||
```swift story-code
|
||||
// will be visible when platform ios is selected
|
||||
import Demo.Element
|
||||
|
||||
let card = DemoElement()
|
||||
```
|
||||
|
||||
## HTML Story
|
||||
|
||||
````md
|
||||
@@ -72,15 +134,18 @@ excludeFromSearch: true
|
||||
|
||||
Once you have that you need to configure it for the story renderer by setting it in your `rocket.config.js`.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
export default {
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
setupUnifiedPlugins: [
|
||||
adjustPluginOptions('mdjsSetupCode', {
|
||||
simulationSettings: { simulatorUrl: '/simulator/' },
|
||||
}),
|
||||
],
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<inline-notification type="tip">
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
You can showcase live running code by annotating a code block with `js story`.
|
||||
|
||||
```js script
|
||||
import { html } from 'lit-html';
|
||||
import { html } from '@mdjs/mdjs-story';
|
||||
```
|
||||
|
||||
````md
|
||||
```js script
|
||||
import { html } from 'lit-html';
|
||||
import { html } from '@mdjs/mdjs-story';
|
||||
```
|
||||
|
||||
```js story
|
||||
|
||||
@@ -1,21 +1,36 @@
|
||||
# Presets >> Blog ||40
|
||||
# Presets >> Blog || 40
|
||||
|
||||
Enable writing blog posts within your Rocket site.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
<code-tabs collection="package-managers" default-tab="npm" align="end">
|
||||
|
||||
```bash tab npm
|
||||
npm i @rocket/blog
|
||||
```
|
||||
|
||||
```bash tab yarn
|
||||
yarn add @rocket/blog
|
||||
```
|
||||
|
||||
```bash tab pnpm
|
||||
pnpm add @rocket/blog
|
||||
```
|
||||
|
||||
</code-tabs>
|
||||
|
||||
## Usage
|
||||
|
||||
👉 `rocket.config.mjs`
|
||||
👉 `rocket.config.js`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
import { rocketBlog } from '@rocket/blog';
|
||||
|
||||
export default {
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
presets: [rocketBlog()],
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Presets >> Joining Blocks ||10
|
||||
# Presets >> Joining Blocks || 10
|
||||
|
||||
The template system allows for a very granular control of how individual parts will be merged, overwritten or reorderd.
|
||||
|
||||
@@ -6,7 +6,7 @@ As a preset you may want to add this to your layout.
|
||||
|
||||
{% raw %}
|
||||
|
||||
```
|
||||
```jinja2
|
||||
<footer id="main-footer">
|
||||
{% for blockName, blockPath in _joiningBlocks.footer %}
|
||||
{% include blockPath %}
|
||||
@@ -22,11 +22,15 @@ This will now render all templates within `_includes/_joiningBlocks/footer/*`.
|
||||
|
||||
Let's assume we have a preset with the following files
|
||||
|
||||
```html
|
||||
<!-- usedPreset/_includes/_joiningBlocks/footer/10-first.njk -->
|
||||
<p>first</p>
|
||||
👉 `_includes/_joiningBlocks/footer/10-first.njk`
|
||||
|
||||
<!-- usedPreset/_includes/_joiningBlocks/footer/20-second.njk -->
|
||||
```html
|
||||
<p>first</p>
|
||||
```
|
||||
|
||||
👉 `_includes/_joiningBlocks/footer/20-second.njk`
|
||||
|
||||
```html
|
||||
<p>second</p>
|
||||
```
|
||||
|
||||
@@ -41,8 +45,9 @@ And it produces this in your website
|
||||
|
||||
Now we can add a file which will insert content without needing to overwrite any of the preset file.
|
||||
|
||||
👉 `docs/_includes/_joiningBlocks/footer/15-in-between.njk`
|
||||
|
||||
```html
|
||||
<!-- docs/_includes/_joiningBlocks/footer/15-in-between.njk -->
|
||||
<p>in-between</p>
|
||||
```
|
||||
|
||||
@@ -60,8 +65,9 @@ the final output will be
|
||||
|
||||
Now if you want to overwrite you can use the same filename.
|
||||
|
||||
👉 `docs/_includes/_joiningBlocks/footer/10-first.njk`
|
||||
|
||||
```html
|
||||
<!-- docs/_includes/_joiningBlocks/footer/10-first.njk -->
|
||||
<p>updated first</p>
|
||||
```
|
||||
|
||||
@@ -78,8 +84,9 @@ the final output will be
|
||||
|
||||
Sometimes you wanna reorder when you overwrite as well
|
||||
|
||||
👉 `docs/_includes/_joiningBlocks/footer/30-first.njk`
|
||||
|
||||
```html
|
||||
<!-- docs/_includes/_joiningBlocks/footer/30-first.njk -->
|
||||
<p>first</p>
|
||||
```
|
||||
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
# Presets >> Launch ||20
|
||||
|
||||
Rocket comes with a preset you will love. Simple, responsive and behaving like native, it sure is going to be a hit among your users.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i @rocket/launch
|
||||
```
|
||||
|
||||
👉 `rocket.config.mjs`
|
||||
|
||||
```js
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
|
||||
export default {
|
||||
presets: [rocketLaunch()],
|
||||
};
|
||||
```
|
||||
|
||||
## Data
|
||||
|
||||
Most data comes from `site.cjs`.
|
||||
|
||||
There is also a specific `rocketLaunch.json`.
|
||||
|
||||
The footer data comes from `footer.json`
|
||||
|
||||
## Inline Notification
|
||||
|
||||
Notification are web components that bring in some styles.
|
||||
|
||||
To use them in Markdown you need to write the HTML tag and have it separated by an empty line.
|
||||
|
||||
```js script
|
||||
import '@rocket/launch/inline-notification/inline-notification.js';
|
||||
```
|
||||
|
||||
First you need to import the script
|
||||
|
||||
````
|
||||
```js script
|
||||
import '@rocket/launch/inline-notification/inline-notification.js';
|
||||
```
|
||||
````
|
||||
|
||||
### Tip
|
||||
|
||||
<inline-notification type="tip">
|
||||
|
||||
I am a tip
|
||||
|
||||
</inline-notification>
|
||||
|
||||
**Usage**
|
||||
|
||||
```md
|
||||
<inline-notification type="tip">
|
||||
|
||||
I am a tip
|
||||
|
||||
</inline-notification>
|
||||
```
|
||||
|
||||
### Modify the Title
|
||||
|
||||
To override the title you can provide a property success.
|
||||
|
||||
<inline-notification type="tip" title="success">
|
||||
|
||||
I am a success message
|
||||
|
||||
</inline-notification>
|
||||
|
||||
**Usage**
|
||||
|
||||
```md
|
||||
<inline-notification type="tip" title="success">
|
||||
|
||||
I am a success message
|
||||
|
||||
</inline-notification>
|
||||
```
|
||||
|
||||
### Warning
|
||||
|
||||
<inline-notification type="warning">
|
||||
|
||||
I am a warning
|
||||
|
||||
</inline-notification>
|
||||
|
||||
**Usage**
|
||||
|
||||
```md
|
||||
<inline-notification type="warning">
|
||||
|
||||
I am a warning
|
||||
|
||||
</inline-notification>
|
||||
```
|
||||
|
||||
### Danger
|
||||
|
||||
<inline-notification type="danger">
|
||||
|
||||
I am a dangerous message
|
||||
|
||||
</inline-notification>
|
||||
|
||||
**Usage**
|
||||
|
||||
```md
|
||||
<inline-notification type="danger">
|
||||
|
||||
I am a dangerous message
|
||||
|
||||
</inline-notification>
|
||||
```
|
||||
7
docs/docs/presets/launch/custom-elements.txt
Normal file
7
docs/docs/presets/launch/custom-elements.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
layout: layout-api
|
||||
package: '@rocket/launch'
|
||||
module: inline-notification/index.js
|
||||
---
|
||||
|
||||
# Presets >> Launch >> Custom Elements || 20
|
||||
3
docs/docs/presets/launch/index.md
Normal file
3
docs/docs/presets/launch/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Presets >> Launch || 20
|
||||
|
||||
- [Preset](./preset/)
|
||||
145
docs/docs/presets/launch/preset.md
Normal file
145
docs/docs/presets/launch/preset.md
Normal file
@@ -0,0 +1,145 @@
|
||||
---
|
||||
alerts:
|
||||
- type: tip
|
||||
content: Take a tip from me
|
||||
- type: warning
|
||||
content: Be *sure* about this...
|
||||
- type: danger
|
||||
content: You **really** shouldn't!
|
||||
---
|
||||
|
||||
# Presets >> Launch >> Preset || 10
|
||||
|
||||
Rocket comes with a preset you will love. Simple, responsive and behaving like native, it sure is going to be a hit among your users.
|
||||
|
||||
## Installation
|
||||
|
||||
Install `@rocket/launch` from the NPM repository using your favourite package manager.
|
||||
|
||||
<code-tabs collection="package-managers" default-tab="npm" align="end">
|
||||
|
||||
```bash tab npm
|
||||
npm i @rocket/launch
|
||||
```
|
||||
|
||||
```bash tab yarn
|
||||
yarn add @rocket/launch
|
||||
```
|
||||
|
||||
```bash tab pnpm
|
||||
pnpm add @rocket/launch
|
||||
```
|
||||
|
||||
</code-tabs>
|
||||
|
||||
## Usage
|
||||
|
||||
👉 `rocket.config.js`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
presets: [rocketLaunch()],
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Data
|
||||
|
||||
The launch preset configures [11ty data](https://www.11ty.dev/docs/data/) using a few overridable files:
|
||||
|
||||
- `site.cjs`: Responsible for most of the site-wide config
|
||||
- `rocketLaunch.json`: configures the homepage layout
|
||||
- `footer.json`: Configures the content of the footer
|
||||
|
||||
## Inline Notification
|
||||
|
||||
```js script
|
||||
import '@rocket/launch/inline-notification/inline-notification.js';
|
||||
```
|
||||
|
||||
Launch ships with `<inline-notification>`, a custom element that applies some styles similar to "info boxes". The element works for `<noscript>` users as well, as long as you don't [override](/guides/presets/overriding/) the default `noscript.css` file.
|
||||
|
||||
To add an inline notification you need to remember to import the element definition:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
~~~markdown
|
||||
```js script
|
||||
import '@rocket/launch/inline-notification/inline-notification.js';
|
||||
```
|
||||
~~~
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
Then you can add your notification to the page. If you want to write the notification's content using markdown, just pad the opening and closing tags with empty lines.
|
||||
|
||||
There are three varieties of `<inline-notification>`, "tip", "warning", and "danger"
|
||||
|
||||
<style>
|
||||
#inline-notifications::part(tab) {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
#inline-notifications code-tab::part(content) {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 6px;
|
||||
}
|
||||
#inline-notifications code-copy::part(copy-button) {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--primary-lines-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<code-tabs id="inline-notifications" default-tab="tip">
|
||||
|
||||
{%for alert in alerts%}
|
||||
|
||||
<code-tab data-label="{{ alert.type }}" data-id="{{ alert.type }}" no-copy>
|
||||
|
||||
```md copy
|
||||
<inline-notification type="{{ alert.type }}">
|
||||
|
||||
{{ alert.content | safe }}
|
||||
|
||||
</inline-notification>
|
||||
```
|
||||
|
||||
<inline-notification type="{{ alert.type }}">
|
||||
|
||||
{{ alert.content | safe }}
|
||||
|
||||
</inline-notification>
|
||||
|
||||
</code-tab>
|
||||
|
||||
{%endfor%}
|
||||
|
||||
</code-tabs>
|
||||
|
||||
### Modify the Title
|
||||
|
||||
The notification title defautls to it's type. You can write a custom title with the `title` attribute.
|
||||
|
||||
<inline-notification type="tip" title="success">
|
||||
|
||||
I am a success message
|
||||
|
||||
</inline-notification>
|
||||
|
||||
```md
|
||||
<inline-notification type="tip" title="success">
|
||||
|
||||
I am a success message
|
||||
|
||||
</inline-notification>
|
||||
```
|
||||
|
||||
<inline-notification type="warning">
|
||||
|
||||
The `title` attribute does not change the title for `<noscript>` users, so don't include any critical information in it.
|
||||
|
||||
</inline-notification>
|
||||
@@ -1,19 +0,0 @@
|
||||
# Presets >> Search ||30
|
||||
|
||||
Add a search for all your static content.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i @rocket/search
|
||||
```
|
||||
|
||||
👉 `rocket.config.mjs`
|
||||
|
||||
```js
|
||||
import { rocketSearch } from '@rocket/search';
|
||||
|
||||
export default {
|
||||
presets: [rocketSearch()],
|
||||
};
|
||||
```
|
||||
9
docs/docs/presets/search/custom-elements.txt
Normal file
9
docs/docs/presets/search/custom-elements.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
layout: layout-api
|
||||
package: '@rocket/search'
|
||||
modules:
|
||||
- src/RocketSearch.js
|
||||
- src/RocketSearchCombobox.js
|
||||
---
|
||||
|
||||
# Presets >> Search >> Custom Elements || 20
|
||||
3
docs/docs/presets/search/index.md
Normal file
3
docs/docs/presets/search/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Presets >> Search || 10
|
||||
|
||||
- [Preset](./preset/)
|
||||
36
docs/docs/presets/search/preset.md
Normal file
36
docs/docs/presets/search/preset.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Presets >> Search >> Preset || 10
|
||||
|
||||
Add a search for all your static content.
|
||||
|
||||
## Installation
|
||||
|
||||
<code-tabs collection="package-managers" default-tab="npm" align="end">
|
||||
|
||||
```bash tab npm
|
||||
npm i @rocket/search
|
||||
```
|
||||
|
||||
```bash tab yarn
|
||||
yarn add @rocket/search
|
||||
```
|
||||
|
||||
```bash tab pnpm
|
||||
pnpm add @rocket/search
|
||||
```
|
||||
|
||||
</code-tabs>
|
||||
|
||||
## Usage
|
||||
|
||||
👉 `rocket.config.js`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
import { rocketSearch } from '@rocket/search';
|
||||
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
presets: [rocketSearch()],
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -1,6 +1,6 @@
|
||||
# Tools >> Check HTML Links ||30
|
||||
|
||||
```js
|
||||
```js script
|
||||
import '@rocket/launch/inline-notification/inline-notification.js';
|
||||
```
|
||||
|
||||
@@ -22,7 +22,7 @@ Read the [Introducing Check HTMl Links - no more bad links](../../blog/introduci
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
```shell
|
||||
npm i -D check-html-links
|
||||
```
|
||||
|
||||
|
||||
@@ -3,16 +3,125 @@
|
||||
The Plugins Manager replaces the specific registration/execution (with options) in a given plugin system by an intend to use a plugin (with these options).
|
||||
This allows your users to adjust the options before actually applying the plugins.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Install npm package
|
||||
```bash
|
||||
npm i plugins-manager
|
||||
```
|
||||
2. Change your public API from an array of plugin "instances" to an array of setup functions
|
||||
```diff
|
||||
import myPlugin from 'my-plugin';
|
||||
+ import { addPlugin } from 'plugins-manager';
|
||||
export default {
|
||||
- plugins: [myPlugin],
|
||||
+ setupPlugins: [addPlugin(myPlugin)]
|
||||
}
|
||||
```
|
||||
3. Convert setup function to plugins
|
||||
|
||||
```js
|
||||
import { applyPlugins } from 'plugins-manager';
|
||||
|
||||
const finalConfig = applyPlugins(config); // "converts" setupPlugins to plugins
|
||||
|
||||
// work with plugins or pass it on to another tool
|
||||
const bundle = await rollup(finalConfig);
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
As you users in most cases you will need to either add or adjust a given plugin in a config file.
|
||||
|
||||
👉 `my-tool.config.js`
|
||||
|
||||
```js
|
||||
import { addPlugin, adjustPluginOptions } from 'plugins-manager';
|
||||
import json from '@rollup/plugin-json';
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
||||
|
||||
export default {
|
||||
setupPlugins: [
|
||||
// add a new plugin with optional plugin options
|
||||
addPlugin(json, {
|
||||
/* ... */
|
||||
}),
|
||||
|
||||
// adjust the options of a plugin that is already registered
|
||||
adjustPluginOptions(nodeResolve, {
|
||||
/* ... */
|
||||
}),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
## Plugins can be functions or classes
|
||||
|
||||
### Function Plugins
|
||||
|
||||
```js
|
||||
function myPlugin({ lastName: 'initial-second' }) {
|
||||
// ...
|
||||
}
|
||||
|
||||
export default {
|
||||
setupPlugins: [addPlugin(myPlugin)],
|
||||
};
|
||||
|
||||
// function parameters are type safe
|
||||
addPlugin(myPlugin, { lastName: 'new name' }); // ts ok
|
||||
addPlugin(myPlugin, { otherProp: 'new name' }); // ts error
|
||||
```
|
||||
|
||||
### Class Plugins
|
||||
|
||||
The options are passed to the constructor.
|
||||
|
||||
```js
|
||||
/**
|
||||
* @typedef {object} MyClassOptions
|
||||
* @property {string} lastName
|
||||
*/
|
||||
|
||||
class MyClass {
|
||||
/** @type {MyClassOptions} */
|
||||
options = {
|
||||
lastName: 'initial-second',
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Partial<MyClassOptions>} options
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
this.options = { ...this.options, ...options };
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default {
|
||||
setupPlugins: [addPlugin(MyClass)],
|
||||
};
|
||||
|
||||
// constructor parameters are type safe
|
||||
addPlugin(MyClass, { lastName: 'new name' }); // ts ok
|
||||
addPlugin(MyClass, { otherProp: 'new name' }); // ts error
|
||||
```
|
||||
|
||||
## Problem
|
||||
|
||||
Many plugin systems require you to either execute a plugin function like in `rollup`.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
import json from '@rollup/plugin-json';
|
||||
export default {
|
||||
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
plugins: [json({ preferConst: true })],
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
or add it in a special way like in `eleventy`
|
||||
|
||||
@@ -44,18 +153,14 @@ This means if you wish to define default plugins and allow your user to override
|
||||
|
||||
The plugins manager lets you orchestrate a set of "meta plugins" which are defined by
|
||||
|
||||
- name
|
||||
- plugin
|
||||
- options
|
||||
- plugin (class or function)
|
||||
- it's options
|
||||
|
||||
```js
|
||||
import beep from '@rollup/plugin-beep';
|
||||
import url from '@rollup/plugin-url';
|
||||
|
||||
let metaPlugins = [
|
||||
{ name: 'beep', plugin: beep },
|
||||
{ name: 'url', plugin: url, options: { limit: 10000 } },
|
||||
];
|
||||
let metaPlugins = [{ plugin: beep }, { plugin: url, options: { limit: 10000 } }];
|
||||
```
|
||||
|
||||
This array can be modified by adding/removing or adjusting options.
|
||||
@@ -90,16 +195,13 @@ export default {
|
||||
|
||||
### Adding Helpers
|
||||
|
||||
Doing array manipulations is kinda error-prone so we offer encourage to use an array of setup function. Where as each setup function can either add a new plugin (with a unique name) or adjust an already existing plugin.
|
||||
Doing array manipulations is kinda error-prone so we encourage to use an array of setup function. Where as each setup function can either add a new plugin (with a unique name) or adjust an already existing plugin.
|
||||
|
||||
```js
|
||||
import { addPlugin, adjustPluginOptions } from 'plugins-manager';
|
||||
|
||||
const systemSetupFunctions = [
|
||||
addPlugin({ name: 'first', plugin: first }),
|
||||
addPlugin({ name: 'second', plugin: second }),
|
||||
];
|
||||
const userSetupFunctions = [adjustPluginOptions('first', { my: 'options' })];
|
||||
const systemSetupFunctions = [addPlugin(first), addPlugin(second)];
|
||||
const userSetupFunctions = [adjustPluginOptions(first, { my: 'options' })];
|
||||
```
|
||||
|
||||
Arrays of functions can by merged like so
|
||||
@@ -111,9 +213,9 @@ const finalSetupFunctions = [...systemSetupFunctions, ...userSetupFunctions];
|
||||
and then converted to the final output.
|
||||
|
||||
```js
|
||||
import { metaPluginsToRollupPlugins } from 'plugins-manager';
|
||||
import { applyPlugins } from 'plugins-manager';
|
||||
|
||||
const plugins = metaPluginsToRollupPlugins(finalSetupFunctions, metaPlugins);
|
||||
const plugins = applyPlugins(finalSetupFunctions, metaPlugins);
|
||||
```
|
||||
|
||||
## Adding a Plugin
|
||||
@@ -129,18 +231,27 @@ By default it adds at the bottom.
|
||||
import json from '@rollup/plugin-json';
|
||||
import { addPlugin } from 'plugins-manager';
|
||||
|
||||
const userSetupFunctions = [
|
||||
addPlugin({ name: 'json', plugin: json, options: { preferConst: true } }),
|
||||
];
|
||||
const userSetupFunctions = [addPlugin(json, { preferConst: true })];
|
||||
```
|
||||
|
||||
Example usage:
|
||||
|
||||
```js
|
||||
addPlugin({ name: 'json', plugin: json }); // Add at the bottom (default)
|
||||
addPlugin({ name: 'json', plugin: json, location: 'top' }); // Add at the top/beginning of the array
|
||||
addPlugin({ name: 'json', plugin: json, location: 'beep' }); // Add after (default) plugin 'beep'
|
||||
addPlugin({ name: 'json', plugin: json, location: 'beep', how: 'before' }); // Add before plugin 'beep'
|
||||
addPlugin(json); // Add at the bottom (default)
|
||||
addPlugin(json, {}, { location: 'top' }); // Add at the top/beginning of the array
|
||||
addPlugin(json, {}, { location: beep }); // Add after (default) plugin 'beep'
|
||||
addPlugin(json, {}, { location: beep, how: 'before' }); // Add before plugin 'beep'
|
||||
```
|
||||
|
||||
This is type safe and typescript will throw an error if you pass the wrong type.
|
||||
|
||||
```js
|
||||
function myPlugin({ myFlag = false } = {}) {
|
||||
// ...
|
||||
}
|
||||
|
||||
addPlugin(myPlugin, { myFlag: true }); // ts ok
|
||||
addPlugin(myPlugin, { notExisting: true }); // ts error
|
||||
```
|
||||
|
||||
## Adjusting Plugin Options
|
||||
@@ -150,12 +261,14 @@ Adjusting options means to either
|
||||
- flatly merge objects (e.g. only the first level will be preserved)
|
||||
- calling a function to do the merge yourself
|
||||
- setting the raw value (if not an object or function)
|
||||
- you need to have a reference to the plugin (which is used to auto complete the available options via typescript)
|
||||
|
||||
```js
|
||||
import json from '@rollup/plugin-json';
|
||||
import { adjustPluginOptions } from 'plugins-manager';
|
||||
|
||||
const userSetupFunctions = [
|
||||
adjustPluginOptions('json', { preferConst: false, anotherOption: 'format' }),
|
||||
adjustPluginOptions(json, { preferConst: false, anotherOption: 'format' }),
|
||||
];
|
||||
```
|
||||
|
||||
@@ -163,36 +276,53 @@ Example usage:
|
||||
|
||||
```js
|
||||
// given
|
||||
addPlugin({
|
||||
name: 'json',
|
||||
plugin: json,
|
||||
options: {
|
||||
other: {
|
||||
nested: 'other.nested',
|
||||
nested2: 'other.nested2',
|
||||
},
|
||||
main: true,
|
||||
addPlugin(json, {
|
||||
other: {
|
||||
nested: 'other.nested',
|
||||
nested2: 'other.nested2',
|
||||
},
|
||||
main: true,
|
||||
});
|
||||
|
||||
// merge objects flately
|
||||
adjustPluginOptions('json', { other: { nested: '--overwritten--' } });
|
||||
adjustPluginOptions(json, { other: { nested: '--overwritten--' } });
|
||||
// resulting options = { other: { nested: '--overwritten--' }, main: true }
|
||||
// NOTE: nested2 is removed
|
||||
|
||||
// merge via function
|
||||
adjustPluginOptions('json', config => ({ other: { ...config.other, nested: '--overwritten--' } }));
|
||||
adjustPluginOptions(json, config => ({ other: { ...config.other, nested: '--overwritten--' } }));
|
||||
// resulting options = { other: { nested: '--overwritten--', nested2: 'other.nested2' }, main: true }
|
||||
|
||||
// merge via function to override full options
|
||||
adjustPluginOptions('json', config => ({ only: 'this' }));
|
||||
adjustPluginOptions(json, config => ({ only: 'this' }));
|
||||
// resulting options = { only: 'this' }
|
||||
|
||||
// setting a raw value
|
||||
adjustPluginOptions('json', false);
|
||||
adjustPluginOptions(json, false);
|
||||
// resulting options = false
|
||||
```
|
||||
|
||||
This is type safe and typescript will throw an error if you pass the wrong type.
|
||||
|
||||
```js
|
||||
function myPlugin({ myFlag = false } = {}) {
|
||||
// ...
|
||||
}
|
||||
|
||||
adjustPluginOptions(myPlugin, { myFlag: true }); // ts ok
|
||||
adjustPluginOptions(myPlugin, { notExisting: true }); // ts error
|
||||
```
|
||||
|
||||
## Remove Plugin
|
||||
|
||||
Sometimes you would like to remove a default plugin from the config.
|
||||
|
||||
```js
|
||||
export default {
|
||||
setupPlugins: [removePlugin(json)],
|
||||
};
|
||||
```
|
||||
|
||||
## Converting metaPlugins to an Actual Plugin
|
||||
|
||||
To execute all setup function you can use this little helper
|
||||
@@ -223,25 +353,9 @@ Rollup has a more specific helper that handles
|
||||
Note: if you provide `config.plugins` then it will return that directly ignoring `setupPlugins`
|
||||
|
||||
```js
|
||||
import { metaConfigToRollupConfig } from 'plugins-manager';
|
||||
import { applyPlugins } from 'plugins-manager';
|
||||
|
||||
const finalConfig = metaConfigToRollupConfig(currentConfig, defaultMetaPlugins);
|
||||
```
|
||||
|
||||
Web Dev Server has a more specific helper that handles
|
||||
|
||||
- `config.setupPlugins`
|
||||
- `config.setupRollupPlugins`
|
||||
|
||||
Note: if you provide `config.plugins` then it will return that directly ignoring `setupPlugins` and `setupRollupPlugins`
|
||||
|
||||
```js
|
||||
import { metaConfigToWebDevServerConfig } from 'plugins-manager';
|
||||
import { fromRollup } from '@web/dev-server-rollup';
|
||||
|
||||
const finalConfig = metaConfigToWebDevServerConfig(currentConfig, defaultMetaPlugins, {
|
||||
rollupWrapperFunction: fromRollup,
|
||||
});
|
||||
const finalConfig = applyPlugins(currentConfig, defaultMetaPlugins);
|
||||
```
|
||||
|
||||
Eleventy
|
||||
|
||||
@@ -20,19 +20,19 @@ The Plugins Manager helps you register and execute your plugins across the vario
|
||||
|
||||
## 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`.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
import emoji from 'remark-emoji';
|
||||
import { addPlugin } from 'plugins-manager';
|
||||
|
||||
/** @type {Partial<import('@rocket/cli').RocketCliOptions>} */
|
||||
const config = {
|
||||
export default ({
|
||||
setupUnifiedPlugins: [addPlugin({ location: 'markdown', name: 'emoji', plugin: emoji })],
|
||||
};
|
||||
|
||||
export default config;
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
For plugins that should handle the Markdown <abbr title="Abstract Syntax Tree">AST</abbr> you should use `addPlugin({ location: 'markdown', name: 'my-plugin', plugin: MyPlugin})`. <br>
|
||||
While for the rehype AST you should use `addPlugin({ location: 'remark2rehype', name: 'my-plugin', plugin: MyPlugin})`.
|
||||
|
||||
@@ -10,94 +10,160 @@ Make sure they are installed before proceeding.
|
||||
|
||||
The fastest way to get started is by using an existing preset like the launch preset.
|
||||
|
||||
1. Start with an empty new folder
|
||||
### Step 1. Initialize the Project Package
|
||||
|
||||
```
|
||||
mkdir my-project
|
||||
cd my-project
|
||||
npm init -y
|
||||
```
|
||||
Start by creating an empty folder for your project
|
||||
|
||||
2. Install dependencies
|
||||
```bash copy
|
||||
mkdir my-project
|
||||
cd my-project
|
||||
```
|
||||
|
||||
```
|
||||
npm install --save-dev @rocket/cli @rocket/launch
|
||||
```
|
||||
Then initialize a package.json file
|
||||
|
||||
3. Add to your .gitignore
|
||||
<code-tabs collection="package-managers" default-tab="npm" align="end">
|
||||
|
||||
```
|
||||
## Rocket ignore files (need to be the full relative path to the folders)
|
||||
docs/_merged_data/
|
||||
docs/_merged_assets/
|
||||
docs/_merged_includes/
|
||||
```
|
||||
```bash tab npm
|
||||
npm init -y
|
||||
```
|
||||
|
||||
<inline-notification type="danger">
|
||||
```bash tab yarn
|
||||
yarn init -y
|
||||
```
|
||||
|
||||
You may be tempted to skip the step above, because you're not ready to commit to git yet!
|
||||
```bash tab pnpm
|
||||
pnpm init -y
|
||||
```
|
||||
|
||||
Rocket uses the .gitignore file to manage its requirements. If you skip this step, Rocket will fail to deploy!
|
||||
</code-tabs>
|
||||
|
||||
### Step 2. Install dependencies
|
||||
|
||||
<code-tabs collection="package-managers" default-tab="npm" align="end">
|
||||
|
||||
```bash tab npm
|
||||
npm install --save-dev @rocket/cli @rocket/launch
|
||||
```
|
||||
|
||||
```bash tab yarn
|
||||
yarn add -D @rocket/cli @rocket/launch
|
||||
```
|
||||
|
||||
```bash tab pnpm
|
||||
pnpm add -D @rocket/cli @rocket/launch
|
||||
```
|
||||
|
||||
</code-tabs>
|
||||
|
||||
### Step 3. Bootstrap the project
|
||||
|
||||
<code-tabs collection="package-managers" default-tab="npm" align="end">
|
||||
|
||||
```bash tab npm
|
||||
npx rocket bootstrap
|
||||
```
|
||||
|
||||
```bash tab yarn
|
||||
yarn rocket bootstrap
|
||||
```
|
||||
|
||||
```bash tab pnpm
|
||||
pnpx rocket bootstrap
|
||||
```
|
||||
|
||||
</code-tabs>
|
||||
|
||||
The `bootstrap` command creates four files in your repo:
|
||||
|
||||
- `.gitignore` containing rocket's build artifacts
|
||||
- `rocket.config.js` containing a minimal rocket config
|
||||
- `docs/.eleventyignore` required to allow you to [override templates](/guides/presets/overriding/)
|
||||
- `docs/index.md` your first page
|
||||
|
||||
It also set the package `type` to `"module"` and adds a `start` and `docs` package scripts.
|
||||
|
||||
<inline-notification type="warning">
|
||||
|
||||
If you don't want to use the `module` package type, make sure to rename the generated config file to `rocket.config.mjs`.
|
||||
|
||||
</inline-notification>
|
||||
|
||||
4. Create a `rocket.config.mjs` (or `.js` if you have type: "module" in you package.json)
|
||||
<details><summary>Default Files Contents</summary>
|
||||
|
||||
```js
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
<code-tabs default-tab="rocket.config.js">
|
||||
|
||||
export default {
|
||||
presets: [rocketLaunch()],
|
||||
};
|
||||
```
|
||||
<!-- prettier-ignore-start -->
|
||||
```js tab rocket.config.js
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
|
||||
5. (optionally) Create a file `.eleventyignore` (this file will be needed once you start customizing presets)
|
||||
/** @type {import('rocket/cli').RocketCliConfig} */
|
||||
export default ({
|
||||
presets: [rocketLaunch()],
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
```
|
||||
node_modules/**
|
||||
/docs/_assets
|
||||
/docs/_includes
|
||||
/docs/_data
|
||||
```
|
||||
```md tab docs/index.md
|
||||
# Welcome to Your Rocket Site
|
||||
|
||||
<inline-notification type="warning" title="note">
|
||||
Add your markdown content here.
|
||||
```
|
||||
|
||||
All further paths are relative to your project root (my-project in this case).
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
</inline-notification>
|
||||
```html tab docs/.eleventyignore
|
||||
_assets
|
||||
_includes
|
||||
_data
|
||||
```
|
||||
|
||||
```html tab .gitignore
|
||||
## Rocket ignore files (need to be the full relative path to the folders)
|
||||
docs/_merged_data/
|
||||
docs/_merged_assets/
|
||||
docs/_merged_includes/
|
||||
```
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
</code-tabs>
|
||||
|
||||
</details>
|
||||
|
||||
## Add your First Page
|
||||
|
||||
👉 `docs/index.md`
|
||||
Bootstrap created the file `docs/index.md`. Open it in your editor and change it to suit your needs.
|
||||
|
||||
<small>NOTE: This tutorial assumes you are familiar with Markdown, for page authoring.</small>
|
||||
|
||||
```md
|
||||
# Welcome to Your Rocket Site
|
||||
|
||||
Text here, like any Markdown file.
|
||||
Add your markdown content here.
|
||||
```
|
||||
|
||||
This tutorial assumes you are familiar with Markdown, for page authoring.
|
||||
|
||||
Please note that the heading - text prefixed with `#` or `##` - is not optional for each page in this tutorial. Everything below that first line is optional Markdown text.
|
||||
|
||||
## Startup:
|
||||
|
||||
👉 `package.json`
|
||||
|
||||
Add `"start": "rocket start"` to your package.json
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"start": "rocket start"
|
||||
}
|
||||
```
|
||||
## Startup
|
||||
|
||||
Now you can launch your site locally with
|
||||
|
||||
```bash
|
||||
npm run start
|
||||
<code-tabs collection="package-managers" default-tab="npm" align="end">
|
||||
|
||||
```bash tab npm
|
||||
npm start
|
||||
```
|
||||
|
||||
```bash tab yarn
|
||||
yarn start
|
||||
```
|
||||
|
||||
```bash tab pnpm
|
||||
pnpx start
|
||||
```
|
||||
|
||||
</code-tabs>
|
||||
|
||||
## Taking Inventory Before Adding Pages:
|
||||
|
||||
We're about to add both content and navigation at the same time.
|
||||
@@ -107,11 +173,16 @@ It can be helpful to take an inventory, before we start, to separate basic setup
|
||||
- We built the project with basic npm commands
|
||||
- Added a couple required files manually
|
||||
- Adjusted package.json
|
||||
- **doc/index.md** to seed the content
|
||||
- **docs/index.md** to seed the content
|
||||
- Launches with `npm start`
|
||||
|
||||
That's all it takes to get a new super-fast and powerful site, complete with a service worker, default styling, navigation, and ready to deploy as a plain old static files.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Adding Pages](../adding-pages/)
|
||||
- [Using Presets](../../presets/getting-started/)
|
||||
|
||||
```js script
|
||||
import '@rocket/launch/inline-notification/inline-notification.js';
|
||||
```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# First Pages >> Managing sidebar ||30
|
||||
# First Pages >> Managing sidebar || 30
|
||||
|
||||
The sidebar will show all the content of the current section.
|
||||
|
||||
@@ -23,7 +23,7 @@ Will be ordered as `First`, `Second`,
|
||||
|
||||
Internally `# Foo >> Bar >> Baz ||20` gets converted to.
|
||||
|
||||
```
|
||||
```yml
|
||||
---
|
||||
title: Bar: Baz
|
||||
eleventyNavigation:
|
||||
@@ -33,10 +33,11 @@ eleventyNavigation:
|
||||
---
|
||||
```
|
||||
|
||||
<!--
|
||||
You can also look at this live playground:
|
||||
|
||||
```js story
|
||||
import { html } from 'lit-html';
|
||||
import { html } from '@mdjs/mdjs-preview';
|
||||
|
||||
export const headlineConverter = () => html`
|
||||
<p>
|
||||
@@ -45,6 +46,7 @@ export const headlineConverter = () => html`
|
||||
</p>
|
||||
`;
|
||||
```
|
||||
-->
|
||||
|
||||
How it then works is very similar to https://www.11ty.dev/docs/plugins/navigation/
|
||||
|
||||
|
||||
@@ -1,25 +1,49 @@
|
||||
# First Pages >> Use JavaScript ||40
|
||||
# First Pages >> Use JavaScript || 40
|
||||
|
||||
You can use `js script` to execute JavaScript (`type="module"`).
|
||||
If you would like to add JavaScript to a page, you can do it inline using the `script` markdown directive. The script you write runs on the page as a module.
|
||||
|
||||
````
|
||||
<!-- prettier-ignore-start -->
|
||||
~~~markdown
|
||||
```js script
|
||||
console.log('foo');
|
||||
const message = 'Hello, World!';
|
||||
console.log(message);
|
||||
```
|
||||
````
|
||||
~~~
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
This can be useful for importing web components and using them in Markdown.
|
||||
Adding the above will log `Hello, World!` to the console without adding a global `message` variable.
|
||||
|
||||
````
|
||||
This can be useful for importing web components and using them in Markdown. Imagine you had some `magic-reveal` element that you wanted to use on a page:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
~~~markdown
|
||||
```js script
|
||||
import 'magic-reveal/magic-reveal.js';
|
||||
```
|
||||
|
||||
<magic-reveal>
|
||||
|
||||
This text will get magically revealed. I can **still** use Markdown as long as there is an empty line between the opening/closing tags and my text.
|
||||
This text will get magically revealed.
|
||||
|
||||
I can **still** use Markdown as long as there is an empty line
|
||||
between the opening/closing tags and my text.
|
||||
|
||||
</magic-reveal>
|
||||
```
|
||||
````
|
||||
~~~
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
or you can use `js story`, `js preview-story`, ...
|
||||
## Component Story Format
|
||||
|
||||
You can also add storybook-style CSF (v2 only) stories to a page using `js story` or `js preview-story`, just make sure to import `html` from `@mdjs/mdjs-preview` instead of from `lit` or `lit-html`.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
~~~markdown
|
||||
```js story
|
||||
import { html } from '@mdjs/mdjs-preview';
|
||||
|
||||
export const StoryPreview = () => html`
|
||||
<p>Use stories in Rocket!</p>
|
||||
`;
|
||||
```
|
||||
~~~
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
@@ -1 +1 @@
|
||||
# Go Live ||40
|
||||
# Go Live || 40
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Go Live >> Overview ||10
|
||||
# Go Live >> Overview || 10
|
||||
|
||||
A few things are usually needed before going live "for real".
|
||||
|
||||
@@ -9,17 +9,21 @@ 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.
|
||||
|
||||
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`
|
||||
|
||||
```
|
||||
```markdown copy
|
||||
---
|
||||
layout: layout-404
|
||||
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
|
||||
|
||||
A sitemap can be used to inform search engines or services about the pages your site has.
|
||||
@@ -28,24 +32,23 @@ You can create one by adding this file:
|
||||
|
||||
👉 `docs/sitemap.njk`
|
||||
|
||||
{% raw %}
|
||||
|
||||
```
|
||||
```markdown copy
|
||||
---
|
||||
layout: layout-raw
|
||||
permalink: /sitemap.xml
|
||||
eleventyExcludeFromCollections: true
|
||||
---
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
{% for page in collections.all %}
|
||||
{% raw %}{% for page in collections.all %}
|
||||
{%- if page.url !== '/404.html' -%}
|
||||
<url>
|
||||
<loc>{{ rocketConfig.absoluteBaseUrl }}{{ page.url | url }}</loc>
|
||||
<lastmod>{{ page.date.toISOString() }}</lastmod>
|
||||
<changefreq>{{ page.data.changeFreq if page.data.changeFreq else "monthly" }}</changefreq>
|
||||
</url>
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
{% endfor %}{% endraw %}
|
||||
</urlset>
|
||||
```
|
||||
|
||||
{% endraw %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Go Live >> Social Media ||20
|
||||
# Go Live >> Social Media || 20
|
||||
|
||||
Having a nice preview image for social media can be very helpful.
|
||||
For that reason Rocket creates those automatically with the title, parent title, section and your logo.
|
||||
@@ -15,7 +15,7 @@ Note: If your logo has an `<?xml>` tag it will throw an error as it will be inli
|
||||
|
||||
You can create your own image and link it with something like this
|
||||
|
||||
```
|
||||
```markdown copy
|
||||
---
|
||||
socialMediaImage: path/to/my/image.png
|
||||
---
|
||||
@@ -29,7 +29,7 @@ You can create an `11tydata.cjs` file next to your page. If your page is `docs/g
|
||||
|
||||
In there you can use the default `createSocialImage` but provide your own values.
|
||||
|
||||
```js
|
||||
```js copy
|
||||
const { createSocialImage } = require('@rocket/cli');
|
||||
|
||||
module.exports = async function () {
|
||||
@@ -39,7 +39,7 @@ module.exports = async function () {
|
||||
subTitle2: 'in 5 Minutes',
|
||||
footer: 'Rocket Guides',
|
||||
// you can also override the svg only for this page by providing
|
||||
// createSocialImageSvg: async () => '<svg>...</svg>'
|
||||
// createSocialImageSvg: async () => '{%raw%}<svg>...</svg>{%endraw%}'
|
||||
});
|
||||
return {
|
||||
socialMediaImage,
|
||||
@@ -52,13 +52,14 @@ module.exports = async function () {
|
||||
Often you want to have a unique style for your social media images.
|
||||
For that you can provide your own function which returns a string of an SVG to render the image.
|
||||
|
||||
👉 `rocket.config.mjs`
|
||||
👉 `rocket.config.js`
|
||||
|
||||
```js
|
||||
<!-- prettier-ignore-start -->
|
||||
```js copy
|
||||
import { adjustPluginOptions } from 'plugins-manager';
|
||||
|
||||
/** @type {Partial<import("@rocket/cli").RocketCliOptions>} */
|
||||
const config = {
|
||||
/** @type {import('@rocket/cli').RocketCliOptions} */
|
||||
export default ({
|
||||
setupEleventyComputedConfig: [
|
||||
adjustPluginOptions('socialMediaImage', {
|
||||
createSocialImageSvg: async ({
|
||||
@@ -95,59 +96,69 @@ const config = {
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default config;
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Using an SVG File as a src with Nunjucks
|
||||
|
||||
If you have multiple variations it may be easier to save them as SVG files and use a template system.
|
||||
|
||||
WARNING: Untested example
|
||||
<!-- prettier-ignore-start -->
|
||||
<code-tabs default-tab="rocket.config.js">
|
||||
|
||||
👉 `rocket.config.mjs`
|
||||
|
||||
{% raw %}
|
||||
|
||||
```js
|
||||
```js tab rocket.config.js
|
||||
import { adjustPluginOptions } from 'plugins-manager';
|
||||
|
||||
/** @type {Partial<import("@rocket/cli").RocketCliOptions>} */
|
||||
const config = {
|
||||
/** @type {import('@rocket/cli').RocketCliOptions} */
|
||||
export default ({
|
||||
setupEleventyComputedConfig: [
|
||||
adjustPluginOptions('socialMediaImage', {
|
||||
createSocialImageSvg: async (args = {}) => {
|
||||
// inside of the svg you can use {{ title }}
|
||||
const svgBuffer = await fs.promises.readFile('/path/to/your/svg/file');
|
||||
const svgBuffer = await fs.promises.readFile('/path/to/your/template.svg');
|
||||
const svg = logoBuffer.toString();
|
||||
return nunjucks.renderString(svg, args);
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
{% endraw %}
|
||||
});
|
||||
```
|
||||
|
||||
```svg tab /path/to/your/template.svg
|
||||
{%raw%}<svg xmlns="http://www.w3.org/2000/svg" fill="#e63946" viewBox="0 0 511.998 511.998">
|
||||
<text font-family="'Open Sans', sans-serif" font-size="39" transform="translate(422.99 408.53)">
|
||||
<tspan x="-89.26" y="12.25">{{ title }}</tspan>
|
||||
</text>
|
||||
<path d="M98.649 430.256c-46.365 28.67-71.17 30.939-78.916 23.51-7.75-7.433-6.519-32.307 20.182-79.832 24.953-44.412 65.374-96.693 113.818-147.211l-11.279-10.817c-49.33 51.442-90.583 104.845-116.163 150.373-19.228 34.22-37.848 79.134-17.375 98.766 5.84 5.6 13.599 7.935 22.484 7.935 22.269 0 51.606-14.677 75.469-29.432 44.416-27.464 96.044-70.919 145.373-122.362l-11.279-10.817c-48.446 50.519-98.987 93.095-142.314 119.887zM254.734 294.95l-18.47-17.71 10.816-11.281 18.47 17.71zM285.516 324.473l-18.47-17.71 10.816-11.28 18.47 17.71zM315.543 317.807l-73.886-70.847 10.816-11.28 73.886 70.846zM500.916 41.287c-7.769 1.59-76.412 16.062-93.897 34.294l-50.728 52.899-114.703-3.629-39.198 40.876 79.28 40.569-21.755 22.687 72.848 69.858 21.755-22.687 43.857 77.51 39.197-40.876-8.433-114.451 50.727-52.899c17.485-18.234 29.067-87.422 30.331-95.251l1.801-11.169-11.082 2.269zM228.209 161.383l19.842-20.692 93.688 2.964-48.775 50.864-64.755-33.136zm173.423 166.303l-35.822-63.308 48.776-50.865 6.886 93.482-19.84 20.691zm-69.334-50.943l-50.287-48.223L412.89 92.037l50.288 48.223-130.88 136.483zm140.711-148.707l-48.316-46.334c14.54-8.427 44.787-17.217 68.076-22.632-4.433 23.497-11.949 54.085-19.76 68.966z"/>
|
||||
<path d="M326.335 257.25l-24.628-23.614 10.816-11.28 24.628 23.615zM431.385 134.414l-11.808 12.315-11.28-10.816 11.808-12.315zM401.838 165.183l-11.28-10.816 11.807-12.314 11.28 10.816zM384.121 183.66l-11.28-10.816 11.807-12.314 11.28 10.816zM175.19 184.515l11.051 11.05-23.582 23.582-11.05-11.05zM190.903 168.796l11.05 11.052-7.863 7.86-11.05-11.052z"/>
|
||||
</svg>{%endraw%}
|
||||
```
|
||||
|
||||
</code-tabs>
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Enabling / Disabling
|
||||
|
||||
Generating images from SVG is quite fast but it can still add that's why by default during `rocket start` there will be no social media images created.
|
||||
|
||||
If you with so create them also during start you can
|
||||
|
||||
```js
|
||||
const config = {
|
||||
<!-- prettier-ignore-start -->
|
||||
```js copy
|
||||
export default ({
|
||||
start: {
|
||||
createSocialMediaImages: true,
|
||||
},
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
Similarly, if you never want to create social media images even during build then you can globally disable it via
|
||||
|
||||
```js
|
||||
const config = {
|
||||
<!-- prettier-ignore-start -->
|
||||
```js copy
|
||||
export default ({
|
||||
createSocialMediaImages: true,
|
||||
};
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
@@ -5,4 +5,19 @@ eleventyNavigation:
|
||||
order: 10
|
||||
---
|
||||
|
||||
Rocket is a fundamentally straight forward way to generate static pages while still allowing to sprinkle in some JavaScript where needed.
|
||||
Rocket helps you generate static pages from Markdown files while giving you the flexibility to sprinkle in some JavaScript where needed.
|
||||
|
||||
- [First Pages](./first-pages/getting-started/) Learn how to bootstrap and run a Rocket site
|
||||
- [Adding Pages](./first-pages/adding-pages/) Create your own content pages
|
||||
- [Linking](./first-pages/link-to-other-pages/) Link between yuor markdown pages
|
||||
- [Managing Sidebar](./first-pages/manage-sidebar/) Customize your site's navigation
|
||||
- [Use JavaScript](./first-pages/use-javascript/) Write inline scripts in markdown
|
||||
- [URLs](./first-pages/urls/) Customize your pages' permalinks
|
||||
- [Layouts](./first-pages/layouts/) Give your page a custom layout
|
||||
- [Presets](./presets/getting-started/) Customize Rocket with config presets
|
||||
- [Overriding](./presets/overriding/) Override preset templates
|
||||
- [Using Templates](./presets/using-templates/) Make use of preset templates
|
||||
- [Create Your Own](./presets/create-your-own/getting-started/) Write and publish your own presets
|
||||
- [Configuration](./configuration/getting-started/) Make Rocket your own
|
||||
- [Go Live](./go-live/overview/) Publish your site
|
||||
- [Social Media](./go-live/social-media/) Generate social images
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
# Presets >> Create your own || 90
|
||||
|
||||
A preset is a setup function and a folder including `_assets`, `_data` and `_includes` (all optional).
|
||||
|
||||
To play around with a preset you can create a folder `fire-theme`.
|
||||
|
||||
You then create the setup function for it with only one property called `path` which will allow Rocket to properly resolve it.
|
||||
|
||||
## Create a Preset Config File
|
||||
|
||||
👉 `fire-theme/fireTheme.js`
|
||||
|
||||
```js
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export function fireTheme() {
|
||||
return {
|
||||
path: path.resolve(__dirname),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Once you have that you can start filling in content you need.
|
||||
|
||||
For example a we could override the full `layout.css` by adding a it like so
|
||||
|
||||
👉 `fire-theme/layout.css`
|
||||
|
||||
```css
|
||||
body {
|
||||
background: hotpink;
|
||||
}
|
||||
```
|
||||
|
||||
Once you have that you can add it to your Rocket config.
|
||||
|
||||
NOTE: The order of presets is important, as for example in this case we take everything from `rocketLaunch` but later override via `fireTheme`.
|
||||
|
||||
👉 `rocket-config.js`
|
||||
|
||||
```js
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
import { fireTheme } from 'path/to/fire-theme/fireTheme.js';
|
||||
|
||||
export default {
|
||||
presets: [rocketLaunch(), fireTheme()],
|
||||
};
|
||||
```
|
||||
|
||||
## Publish a Preset
|
||||
|
||||
If you would like to publish a preset to use it on multiple websites or share it with your friends you can do like so.
|
||||
|
||||
1. Pick a name for the package => for this example we take `fire-theme`.
|
||||
2. Create a new folder `fire-theme`
|
||||
3. Create a folder `fire-theme/preset` copy `fireTheme.js` from [above](#create-a-preset-config-file) into `preset/fireTheme.js`
|
||||
4. Add a 👉 `package.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "fire-theme",
|
||||
"version": "0.3.0",
|
||||
"description": "Fire Theme for Rocket",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./preset/": "./preset/"
|
||||
},
|
||||
"files": ["*.js", "preset"],
|
||||
"keywords": ["rocket", "preset"]
|
||||
}
|
||||
```
|
||||
|
||||
5. Add a 👉 `index.js`
|
||||
|
||||
```js
|
||||
export { fireTheme } from './preset/fireTheme.js';
|
||||
```
|
||||
|
||||
6. Add a 👉 `README.md`
|
||||
|
||||
````
|
||||
# FireTheme
|
||||
|
||||
This is a theme/preset for [Rocket](https://rocket.modern-web.dev/).
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm i -D fire-theme
|
||||
```
|
||||
|
||||
Add it to your 👉 `rocket.config.js`
|
||||
|
||||
```js
|
||||
import { fireTheme } from 'fire-theme';
|
||||
|
||||
export default {
|
||||
presets: [fireTheme()],
|
||||
};
|
||||
```
|
||||
````
|
||||
54
docs/guides/presets/create-your-own/getting-started.md
Normal file
54
docs/guides/presets/create-your-own/getting-started.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Presets >> Create your Own >> Getting Started || 10
|
||||
|
||||
A preset is a setup function and a folder including `_assets`, `_data` and `_includes` (all optional).
|
||||
|
||||
To play around with a preset you can create a folder `fire-theme`.
|
||||
|
||||
You then create the setup function for it with only one property called `path` which will allow Rocket to properly resolve it.
|
||||
|
||||
## Create a Preset Config File
|
||||
|
||||
👉 `fire-theme/fireTheme.js`
|
||||
|
||||
```js copy
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export function fireTheme() {
|
||||
return {
|
||||
path: path.resolve(__dirname),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Once you have that you can start filling in content you need.
|
||||
|
||||
For example we could override the full `layout.css` by adding it like so
|
||||
|
||||
👉 `fire-theme/layout.css`
|
||||
|
||||
```css copy
|
||||
body {
|
||||
background: hotpink;
|
||||
}
|
||||
```
|
||||
|
||||
Once you have that you can add it to your Rocket config.
|
||||
|
||||
NOTE: The order of presets is important, as for example in this case we take everything from `rocketLaunch` but later override via `fireTheme`.
|
||||
|
||||
👉 `rocket.config.js`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js copy
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
import { fireTheme } from 'path/to/fire-theme/fireTheme.js';
|
||||
|
||||
/** @type {import('@rocket/cli').RocketCliOptions} */
|
||||
export default ({
|
||||
presets: [rocketLaunch(), fireTheme()],
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
22
docs/guides/presets/create-your-own/hooks.md
Normal file
22
docs/guides/presets/create-your-own/hooks.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Presets >> Create your Own >> Hooks || 20
|
||||
|
||||
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.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```js
|
||||
/** @type {import('@rocket/cli').RocketPreset} */
|
||||
export default ({
|
||||
async before11ty() {
|
||||
await copyDataFiles();
|
||||
},
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Preset Interface
|
||||
|
||||
The full preset interface is copied below for your reference.
|
||||
|
||||
```ts
|
||||
{% include ../../../../packages/cli/types/preset.d.ts %}
|
||||
```
|
||||
7
docs/guides/presets/create-your-own/index.md
Normal file
7
docs/guides/presets/create-your-own/index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Presets >> Create your Own || 40
|
||||
|
||||
## Contents
|
||||
|
||||
- [Getting Started](./getting-started/)
|
||||
- [Hooks](./hooks/)
|
||||
- [Publishing your Preset](./publishing/)
|
||||
60
docs/guides/presets/create-your-own/publishing.md
Normal file
60
docs/guides/presets/create-your-own/publishing.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Presets >> Create your Own >> Publishing || 100
|
||||
|
||||
If you would like to publish a preset to use it on multiple websites or share it with your friends you can do like so.
|
||||
|
||||
1. Pick a name for the package
|
||||
- use the convention `rocket-preset-${name}`
|
||||
- for this example we use `rocket-preset-fire-theme`.
|
||||
2. Create a new folder `fire-theme`
|
||||
3. Create a folder `fire-theme/preset` copy `fireTheme.js` from [above](../getting-started/) into `preset/fireTheme.js`
|
||||
4. Add a 👉 `package.json`
|
||||
|
||||
```json copy
|
||||
{
|
||||
"name": "rocket-preset-fire-theme",
|
||||
"version": "0.3.0",
|
||||
"description": "Fire Theme for Rocket",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./preset/": "./preset/"
|
||||
},
|
||||
"files": ["*.js", "preset"],
|
||||
"keywords": ["rocket", "preset"]
|
||||
}
|
||||
```
|
||||
|
||||
5. Add a 👉 `index.js`
|
||||
|
||||
```js copy
|
||||
export { fireTheme } from './preset/fireTheme.js';
|
||||
```
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
6. Add a 👉 `README.md`
|
||||
|
||||
~~~markdown copy
|
||||
# FireTheme
|
||||
|
||||
This is a theme/preset for [Rocket](https://rocket.modern-web.dev/).
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm i -D fire-theme
|
||||
```
|
||||
|
||||
Add it to your 👉 `rocket.config.js`
|
||||
|
||||
```js
|
||||
import { fireTheme } from 'fire-theme';
|
||||
|
||||
/** @type {import('@rocket/cli').RocketCliOptions} */
|
||||
export default ({
|
||||
presets: [rocketLaunch(), fireTheme()],
|
||||
});
|
||||
```
|
||||
~~~
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -1,7 +1,36 @@
|
||||
# Presets >> Getting Started ||10
|
||||
# Presets >> Getting Started || 10
|
||||
|
||||
Presets are ...
|
||||
Presets are partial rocket configs that combine any number of plugins to add specific features. Rocket is built on these presets, like `rocketLaunch`, `rocketBlog`, and `rocketSearch`
|
||||
|
||||
You can use a preset via the config...
|
||||
You can use a preset via the config by adding it to the `presets` array
|
||||
|
||||
You can load multiple presets.
|
||||
<!-- prettier-ignore-start -->
|
||||
```js copy
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
import { rocketBlog } from '@rocket/blog';
|
||||
import { rocketSearch } from '@rocket/search';
|
||||
|
||||
/** @type {import('@rocket/cli').RocketCliOptions} */
|
||||
export default ({
|
||||
presets: [rocketLaunch(), rocketBlog(), rocketSearch()],
|
||||
});
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Community Presets
|
||||
|
||||
There are a number of community-made presets available:
|
||||
|
||||
<!--
|
||||
-- Thank you for your interest in rocket. To add your preset,
|
||||
-- follow the format below. Please add your preset in alphabetical order.
|
||||
-->
|
||||
|
||||
- [rocket-preset-code-tabs](https://www.npmjs.com/package/rocket-preset-code-tabs) - Add tab elements for code blocks
|
||||
- [rocket-preset-custom-elements-manifest](https://www.npmjs.com/package/rocket-preset-custom-elements-manifest) - Documents code generation for JavaScript libraries, particularly custom elements.
|
||||
- [rocket-preset-markdown-directive](https://www.npmjs.com/package/rocket-preset-markdown-directive) - Add your own custom md code block directives
|
||||
- [rocket-preset-playground-elements](https://www.npmjs.com/package/rocket-preset-playground-elements) - Live code editors that run in-browser
|
||||
- [rocket-preset-slide-decks](https://www.npmjs.com/package/rocket-preset-slide-decks) - Slide decks in Markdown and HTML
|
||||
- [rocket-preset-webcomponents-dev](https://www.npmjs.com/package/rocket-preset-webcomponents-dev) - Live code editors that run on webcomponents.dev
|
||||
|
||||
> Want your plugin listed here? Please [create a PR](https://github.com/modernweb-dev/rocket/edit/main/docs/guides/presets/getting-started.md)!
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
# Presets || 20
|
||||
|
||||
- [Getting Started](./getting-started/)
|
||||
- [Overriding](./overriding/)
|
||||
- [Using Templates](./using-templates/)
|
||||
- [Create Your Own](./create-your-own/getting-started/)
|
||||
|
||||
@@ -4,4 +4,23 @@ All loaded presets will be combined but you can override each file.
|
||||
|
||||
Take a look at `docs/_merged_includes` and override what you want to override by placing the same filename into `_includes`.
|
||||
|
||||
For example, to override the css files loaded in the `<head>`,
|
||||
|
||||
```bash
|
||||
cp docs/_merged_includes/_joiningBlocks/head/40-stylesheets.njk \
|
||||
docs/_includes/_joiningBlocks/head/40-stylesheets.njk
|
||||
```
|
||||
|
||||
then edit the file to suit your needs.
|
||||
|
||||
Also works for `_assets`, `_data` ...
|
||||
|
||||
<inline-notification type="warning">
|
||||
|
||||
If you don't [add `.eleventyignore`](/guides/first-pages/getting-started/#setup), you may receive error messages when running `rocket build`.
|
||||
|
||||
</inline-notification>
|
||||
|
||||
```js script
|
||||
import '@rocket/launch/inline-notification/inline-notification.js';
|
||||
```
|
||||
|
||||
@@ -37,6 +37,14 @@ If you look into `docs/_merged_includes/_joiningBlocks/bottom/` you will see a f
|
||||
- `190-google-analytics.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
|
||||
|
||||
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
|
||||
|
||||
For more details please see the [Joining Blocks Docs](../../docs/presets/joining-blocks.md)
|
||||
|
||||
```js script
|
||||
import '@rocket/launch/inline-notification/inline-notification.js';
|
||||
```
|
||||
|
||||
4
netlify.toml
Normal file
4
netlify.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[[headers]]
|
||||
for = "/*"
|
||||
[headers.values]
|
||||
Content-Security-Policy = "default-src 'self'; script-src 'self' www.googletagmanager.com 'sha256-W6Gq+BvrdAAMbF8E7WHA7UPQxuUOfJM8E9mpKD0oihA=' 'sha256-vFU+IJ5dUUukI5Varwy49dN2d89DmFj7UNewqQv88sw='; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src 'self' data: fonts.gstatic.com;"
|
||||
24
package.json
24
package.json
@@ -8,16 +8,18 @@
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"analyze": "run-s analyze:* format:*",
|
||||
"analyze:analyze": "node scripts/workspaces-scripts-bin.mjs analyze",
|
||||
"build": "npm run build:packages && npm run build:site",
|
||||
"build:packages": "node scripts/workspaces-scripts-bin.mjs build:package",
|
||||
"build:site": "npm run rocket:build",
|
||||
"build:site": "run-s analyze:* rocket:build",
|
||||
"changeset": "changeset",
|
||||
"debug": "web-test-runner --watch --config web-test-runner-chrome.config.mjs",
|
||||
"debug:firefox": "web-test-runner --watch --config web-test-runner-firefox.config.mjs",
|
||||
"debug:webkit": "web-test-runner --watch --config web-test-runner-webkit.config.mjs",
|
||||
"format": "npm run format:eslint && npm run format:prettier",
|
||||
"format": "run-s format:*",
|
||||
"format:eslint": "eslint --ext .ts,.js,.mjs,.cjs . --fix",
|
||||
"format:prettier": "node node_modules/prettier/bin-prettier.js \"**/*.{ts,js,mjs,cjs,md}\" \"**/package.json\" --write --ignore-path .eslintignore",
|
||||
"format:prettier": "node node_modules/prettier/bin-prettier.js \"**/*.{ts,js,mjs,cjs,md}\" \"**/!(expected)/package.json\" --write --ignore-path .eslintignore",
|
||||
"lint": "run-p lint:*",
|
||||
"lint:eslint": "eslint --ext .ts,.js,.mjs,.cjs .",
|
||||
"lint:prettier": "node node_modules/prettier/bin-prettier.js \"**/*.{ts,js,mjs,cjs,md}\" --check --ignore-path .eslintignore",
|
||||
@@ -31,7 +33,8 @@
|
||||
"setup": "npm run setup:ts-configs && npm run build:packages",
|
||||
"setup:patches": "npx patch-package",
|
||||
"setup:ts-configs": "node scripts/generate-ts-configs.mjs",
|
||||
"start": "node packages/cli/src/cli.js start",
|
||||
"xprestart": "yarn analyze",
|
||||
"start": "node --trace-warnings packages/cli/src/cli.js start",
|
||||
"test": "yarn test:node && yarn test:web",
|
||||
"test:node": "mocha \"packages/*/test-node/**/*.test.{ts,js,mjs,cjs}\" --timeout 5000 --reporter dot --exit",
|
||||
"test:web": "web-test-runner",
|
||||
@@ -45,7 +48,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.12.0",
|
||||
"@open-wc/testing": "^2.5.32",
|
||||
"@custom-elements-manifest/analyzer": "^0.4.12",
|
||||
"@open-wc/testing": "^3.0.0-next.1",
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-typescript": "^8.1.0",
|
||||
@@ -58,12 +62,13 @@
|
||||
"@typescript-eslint/parser": "^4.13.0",
|
||||
"@web/test-runner": "^0.12.2",
|
||||
"@web/test-runner-commands": "^0.4.0",
|
||||
"@web/test-runner-playwright": "^0.8.0",
|
||||
"@web/test-runner-playwright": "^0.8.8",
|
||||
"cem-plugin-readme": "^0.1.3",
|
||||
"chai": "^4.2.0",
|
||||
"concurrently": "^5.3.0",
|
||||
"copyfiles": "^2.4.1",
|
||||
"deepmerge": "^4.2.2",
|
||||
"esbuild": "^0.8.31",
|
||||
"esbuild": "^0.12.15",
|
||||
"eslint": "^7.17.0",
|
||||
"eslint-config-prettier": "^7.1.0",
|
||||
"hanbi": "^0.4.1",
|
||||
@@ -75,14 +80,17 @@
|
||||
"onchange": "^7.1.0",
|
||||
"prettier": "^2.2.1",
|
||||
"prettier-plugin-package": "^1.3.0",
|
||||
"publish-docs": "^0.1.2",
|
||||
"puppeteer": "^9.0.0",
|
||||
"remark-emoji": "^2.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"rocket-preset-code-tabs": "^0.2.6",
|
||||
"rocket-preset-custom-elements-manifest": "^0.1.7",
|
||||
"rollup": "^2.36.1",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"sinon": "^9.2.3",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.1.3"
|
||||
"typescript": "^4.3.2"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
|
||||
@@ -1,5 +1,50 @@
|
||||
# @rocket/blog
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 70bb7a1: BREAKING CHANGE: Update to latest plugins manager to get type safe options
|
||||
|
||||
There is no longer a name string as a key for a plugin. It is identified by it's function/class. You will need to adjust your code if you are adding or adjusting plugins.
|
||||
|
||||
```diff
|
||||
- addPlugin({ name: 'my-plugin', plugin: myPlugin, options: { myFlag: true }, location: 'top' });
|
||||
+ addPlugin(myPlugin, { myFlag: true }, { location: 'top' });
|
||||
- adjustPluginOptions('my-plugin', { myFlag: true });
|
||||
+ adjustPluginOptions(myPlugin, { myFlag: true });
|
||||
```
|
||||
|
||||
For more details please see the [Changelog](https://github.com/modernweb-dev/rocket/blob/main/packages/plugins-manager/CHANGELOG.md#030) of the plugins-manager package.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- plugins-manager@0.3.0
|
||||
|
||||
## 0.3.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- e1089c5: add title to blog page
|
||||
|
||||
## 0.3.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 00f4a91: alignment + spacings for article grids
|
||||
|
||||
## 0.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a5661b8: Updates dependencies
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/blog",
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -38,6 +38,6 @@
|
||||
"testing"
|
||||
],
|
||||
"dependencies": {
|
||||
"plugins-manager": "^0.2.1"
|
||||
"plugins-manager": "^0.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ body[layout='layout-blog-details'] #sidebar-nav li.anchor a:hover::before {
|
||||
flex-wrap: wrap;
|
||||
margin: calc(-1 * var(--gap)) 0 0 calc(-1 * var(--gap));
|
||||
width: calc(100% + var(--gap));
|
||||
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.articles article {
|
||||
@@ -32,6 +34,12 @@ body[layout='layout-blog-details'] #sidebar-nav li.anchor a:hover::before {
|
||||
.articles article h2 {
|
||||
margin: 0;
|
||||
border: none;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.articles article .thumbnail {
|
||||
display: block;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.articles article .read {
|
||||
@@ -48,7 +56,7 @@ body[layout='layout-blog-details'] #sidebar-nav li.anchor a:hover::before {
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
body[layout='layout-blog-details'] #sidebar {
|
||||
body[layout='layout-blog-details'] #sidebar {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
{% if title %}
|
||||
<h1>{{title}}</h1>
|
||||
{% endif %}
|
||||
{% if cover_image %}
|
||||
<img src="{{ cover_image | url }}" alt="">
|
||||
{% endif %}
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
{% if post.data.published %}
|
||||
<article>
|
||||
{% if post.data.cover_image %}
|
||||
<a href="{{ post.url | url }}">
|
||||
<img src="{{ post.data.cover_image | url }}" alt="">
|
||||
<a href="{{ post.url | url }}" class="thumbnail" style="background-image: url({{ post.data.cover_image | url }});">
|
||||
</a>
|
||||
{% endif %}
|
||||
<div class="content">
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
<link rel="stylesheet" href="{{ '/_assets/rocket-blog.css' | asset | url }}">
|
||||
{%- if layout == 'layout-blog-overview' -%}
|
||||
<style>
|
||||
.articles article .thumbnail {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
</style>
|
||||
{%- endif -%}
|
||||
|
||||
@@ -47,6 +47,6 @@ export function rocketBlog({ section = SECTION, postCollection = POST_COLLECTION
|
||||
|
||||
return {
|
||||
path: path.resolve(__dirname),
|
||||
setupEleventyPlugins: [addPlugin({ name: 'rocket-blog', plugin: eleventyPluginRocketBlog })],
|
||||
setupEleventyPlugins: [addPlugin(eleventyPluginRocketBlog)],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# @rocket/building-rollup
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 70bb7a1: BREAKING CHANGE: Update to latest plugins manager to get type safe options
|
||||
|
||||
There is no longer a name string as a key for a plugin. It is identified by it's function/class. You will need to adjust your code if you are adding or adjusting plugins.
|
||||
|
||||
```diff
|
||||
- addPlugin({ name: 'my-plugin', plugin: myPlugin, options: { myFlag: true }, location: 'top' });
|
||||
+ addPlugin(myPlugin, { myFlag: true }, { location: 'top' });
|
||||
- adjustPluginOptions('my-plugin', { myFlag: true });
|
||||
+ adjustPluginOptions(myPlugin, { myFlag: true });
|
||||
```
|
||||
|
||||
For more details please see the [Changelog](https://github.com/modernweb-dev/rocket/blob/main/packages/plugins-manager/CHANGELOG.md#030) of the plugins-manager package.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 60e85a1: Support `picture` tags by handling `source` tags with `srcset` attributes in the rollup asset gathering build phase.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/building-rollup",
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -56,7 +56,7 @@
|
||||
"@rollup/plugin-babel": "^5.2.2",
|
||||
"@rollup/plugin-node-resolve": "^11.0.1",
|
||||
"@rollup/plugin-replace": "^2.4.2",
|
||||
"@web/rollup-plugin-html": "^1.6.0",
|
||||
"@web/rollup-plugin-html": "^1.8.0",
|
||||
"@web/rollup-plugin-import-meta-assets": "^1.0.4",
|
||||
"@web/rollup-plugin-polyfills-loader": "^1.1.0",
|
||||
"browserslist": "^4.16.1",
|
||||
|
||||
@@ -2,13 +2,13 @@ import resolve from '@rollup/plugin-node-resolve';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import babelPkg from '@rollup/plugin-babel';
|
||||
|
||||
import { metaConfigToRollupConfig } from 'plugins-manager';
|
||||
import { applyPlugins } from 'plugins-manager';
|
||||
|
||||
const { babel } = babelPkg;
|
||||
|
||||
export function createBasicConfig(userConfig) {
|
||||
const { config, metaPlugins } = createBasicMetaConfig(userConfig);
|
||||
return metaConfigToRollupConfig(config, metaPlugins);
|
||||
return applyPlugins(config, metaPlugins);
|
||||
}
|
||||
|
||||
export function createBasicMetaConfig(userConfig = { output: {} }) {
|
||||
@@ -39,14 +39,12 @@ export function createBasicMetaConfig(userConfig = { output: {} }) {
|
||||
|
||||
let metaPlugins = [
|
||||
{
|
||||
name: 'node-resolve',
|
||||
plugin: resolve,
|
||||
options: {
|
||||
moduleDirectories: ['node_modules', 'web_modules'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'babel',
|
||||
plugin: babel,
|
||||
options: {
|
||||
babelHelpers: 'bundled',
|
||||
@@ -73,7 +71,6 @@ export function createBasicMetaConfig(userConfig = { output: {} }) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'terser',
|
||||
plugin: terser,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { createSpaMetaConfig } from './createSpaConfig.js';
|
||||
import { adjustPluginOptions, metaConfigToRollupConfig } from 'plugins-manager';
|
||||
import { adjustPluginOptions, applyPlugins } from 'plugins-manager';
|
||||
import { rollupPluginHTML } from '@web/rollup-plugin-html';
|
||||
|
||||
export function createMpaConfig(userConfig) {
|
||||
const { config, metaPlugins } = createMpaMetaConfig(userConfig);
|
||||
|
||||
const final = metaConfigToRollupConfig(config, metaPlugins);
|
||||
const final = applyPlugins(config, metaPlugins);
|
||||
return final;
|
||||
}
|
||||
|
||||
@@ -12,7 +13,7 @@ export function createMpaMetaConfig(userConfig = { output: {}, setupPlugins: []
|
||||
const { config, metaPlugins } = createSpaMetaConfig(userConfig);
|
||||
|
||||
config.setupPlugins = [
|
||||
adjustPluginOptions('html', {
|
||||
adjustPluginOptions(rollupPluginHTML, {
|
||||
flattenOutput: false,
|
||||
}),
|
||||
...config.setupPlugins,
|
||||
|
||||
@@ -3,13 +3,13 @@ import { terser } from 'rollup-plugin-terser';
|
||||
import babelPkg from '@rollup/plugin-babel';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
|
||||
import { metaConfigToRollupConfig } from 'plugins-manager';
|
||||
import { applyPlugins } from 'plugins-manager';
|
||||
|
||||
const { babel } = babelPkg;
|
||||
|
||||
export function createServiceWorkerConfig(userConfig) {
|
||||
const { config, metaPlugins } = createServiceWorkerMetaConfig(userConfig);
|
||||
return metaConfigToRollupConfig(config, metaPlugins);
|
||||
return applyPlugins(config, metaPlugins);
|
||||
}
|
||||
|
||||
export function createServiceWorkerMetaConfig(userConfig = { output: {} }) {
|
||||
@@ -33,21 +33,19 @@ export function createServiceWorkerMetaConfig(userConfig = { output: {} }) {
|
||||
|
||||
let metaPlugins = [
|
||||
{
|
||||
name: 'node-resolve',
|
||||
plugin: resolve,
|
||||
options: {
|
||||
moduleDirectories: ['node_modules', 'web_modules'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'replace',
|
||||
plugin: replace,
|
||||
options: {
|
||||
'process.env.NODE_ENV': JSON.stringify(developmentMode ? 'development' : 'production'),
|
||||
preventAssignment: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'babel',
|
||||
plugin: babel,
|
||||
options: {
|
||||
babelHelpers: 'bundled',
|
||||
@@ -74,7 +72,6 @@ export function createServiceWorkerMetaConfig(userConfig = { output: {} }) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'terser',
|
||||
plugin: terser,
|
||||
options: {
|
||||
mangle: {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { rollupPluginHTML } from '@web/rollup-plugin-html';
|
||||
import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets';
|
||||
import { polyfillsLoader } from '@web/rollup-plugin-polyfills-loader';
|
||||
import { metaConfigToRollupConfig } from 'plugins-manager';
|
||||
import { applyPlugins } from 'plugins-manager';
|
||||
|
||||
import { createBasicMetaConfig } from './createBasicConfig.js';
|
||||
|
||||
export function createSpaConfig(userConfig) {
|
||||
const { config, metaPlugins } = createSpaMetaConfig(userConfig);
|
||||
return metaConfigToRollupConfig(config, metaPlugins);
|
||||
return applyPlugins(config, metaPlugins);
|
||||
}
|
||||
|
||||
export function createSpaMetaConfig(userConfig = { output: {} }) {
|
||||
@@ -30,7 +30,6 @@ export function createSpaMetaConfig(userConfig = { output: {} }) {
|
||||
const spaMetaPlugins = [
|
||||
...metaPlugins,
|
||||
{
|
||||
name: 'html',
|
||||
plugin: rollupPluginHTML,
|
||||
options: {
|
||||
rootDir,
|
||||
@@ -38,11 +37,9 @@ export function createSpaMetaConfig(userConfig = { output: {} }) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'import-meta-assets',
|
||||
plugin: importMetaAssets,
|
||||
},
|
||||
{
|
||||
name: 'polyfills-loader',
|
||||
plugin: polyfillsLoader,
|
||||
options: {
|
||||
polyfills: {},
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# 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="mailto:address@example.com"
|
||||
>contact</a
|
||||
>
|
||||
```
|
||||
|
||||
## 0.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -4,13 +4,13 @@ A fast checker for broken links/references in HTML.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
```shell
|
||||
npm i -D check-html-links
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
```bash
|
||||
npx check-html-links _site
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "check-html-links",
|
||||
"version": "0.2.2",
|
||||
"version": "0.2.3",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -37,7 +37,8 @@
|
||||
"command-line-args": "^5.1.1",
|
||||
"glob": "^7.0.0",
|
||||
"minimatch": "^3.0.4",
|
||||
"sax-wasm": "^2.0.0"
|
||||
"sax-wasm": "^2.0.0",
|
||||
"slash": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/glob": "^7.0.0"
|
||||
|
||||
@@ -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
|
||||
@@ -207,8 +219,13 @@ async function resolveLinks(links, { htmlFilePath, rootDir, ignoreUsage }) {
|
||||
|
||||
if (ignoreUsage(value)) {
|
||||
// ignore
|
||||
} else if (value.includes('mailto:')) {
|
||||
} else if (
|
||||
value.startsWith('mailto:') ||
|
||||
value.startsWith('mailto:') // = "mailto:" but html encoded
|
||||
) {
|
||||
// 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 !== '') {
|
||||
addLocalFile(htmlFilePath, anchor, usageObj);
|
||||
} else if (value.startsWith('//') || value.startsWith('http')) {
|
||||
@@ -219,6 +236,8 @@ async function resolveLinks(links, { htmlFilePath, rootDir, ignoreUsage }) {
|
||||
addLocalFile(filePath, anchor, usageObj);
|
||||
} else if (value === '' && anchor === '') {
|
||||
// no need to check it
|
||||
} else if (isNonHttpSchema(value)) {
|
||||
// not a schema we handle
|
||||
} else {
|
||||
const filePath = path.join(path.dirname(htmlFilePath), valueFile);
|
||||
addLocalFile(filePath, anchor, usageObj);
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
<a href="mailto:foo@bar.com"></a>
|
||||
<!-- encoded mailto links -->
|
||||
<a href="mailto:address@example.com"></a>
|
||||
|
||||
@@ -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>
|
||||
@@ -0,0 +1 @@
|
||||
<a href="tel:99999"></a>
|
||||
@@ -183,6 +183,16 @@ describe('validateFolder', () => {
|
||||
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 () => {
|
||||
const { errors, cleanup } = await execute('fixtures/internal-link-ignore', {
|
||||
ignoreLinkPatterns: ['./relative/*', './relative/**/*'],
|
||||
|
||||
@@ -1,5 +1,180 @@
|
||||
# @rocket/cli
|
||||
|
||||
## 0.10.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 15a82c0: Enable including script files into the simulator via `<script src=".." mdjs-use>`
|
||||
- 15a82c0: Allow only a limited set of characters for simulator includes `[a-zA-Z0-9\/\-_]`.
|
||||
Notably, there is no:
|
||||
|
||||
- `:` to prevent `http://...` includes
|
||||
- `.` so filenames as `this.is.my.js` are not supported. Also includes will be without file endings which will be added automatically
|
||||
|
||||
## 0.10.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 70bb7a1: BREAKING CHANGE: Update to latest plugins manager to get type safe options
|
||||
|
||||
There is no longer a name string as a key for a plugin. It is identified by it's function/class. You will need to adjust your code if you are adding or adjusting plugins.
|
||||
|
||||
```diff
|
||||
- addPlugin({ name: 'my-plugin', plugin: myPlugin, options: { myFlag: true }, location: 'top' });
|
||||
+ addPlugin(myPlugin, { myFlag: true }, { location: 'top' });
|
||||
- adjustPluginOptions('my-plugin', { myFlag: true });
|
||||
+ adjustPluginOptions(myPlugin, { myFlag: true });
|
||||
```
|
||||
|
||||
For more details please see the [Changelog](https://github.com/modernweb-dev/rocket/blob/main/packages/plugins-manager/CHANGELOG.md#030) of the plugins-manager package.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- Updated dependencies [70bb7a1]
|
||||
- plugins-manager@0.3.0
|
||||
- @rocket/eleventy-plugin-mdjs-unified@0.6.0
|
||||
- @rocket/building-rollup@0.4.0
|
||||
|
||||
## 0.9.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 7301a0f: Pass on rocketConfig to the eleventy function to enable conditional configurations/filters
|
||||
- 42418f2: Disable the service worker for local development
|
||||
- 5ac6aa6: Set the encoding of the simulator to utf8 via a html meta tag
|
||||
|
||||
## 0.9.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 738941a: In `rocket.config.js` you can now supply a rollup config function.
|
||||
|
||||
```js
|
||||
export default {
|
||||
rollup: config => {
|
||||
// config will be the fully generated config object after all presets have been applied
|
||||
if (config.plugins.includes('...')) {
|
||||
// change some config options
|
||||
}
|
||||
return config;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## 0.9.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- adf0f1d: use img openEnd to insert responsive image
|
||||
|
||||
## 0.9.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a5661b8: Updates dependencies
|
||||
|
||||
## 0.9.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- d91e46b: Add `bootstrap` command
|
||||
- 9978ea7: Improves typings for `addPlugin`
|
||||
- Updated dependencies [9978ea7]
|
||||
- @rocket/eleventy-plugin-mdjs-unified@0.5.1
|
||||
- plugins-manager@0.2.3
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
const { setComputedConfig, getComputedConfig } = require('./src/public/computedConfig.cjs');
|
||||
const { generateEleventyComputed } = require('./src/public/generateEleventyComputed.cjs');
|
||||
const {
|
||||
generateEleventyComputed,
|
||||
LayoutPlugin,
|
||||
TitleMetaPlugin,
|
||||
TitlePlugin,
|
||||
EleventyNavigationPlugin,
|
||||
SectionPlugin,
|
||||
SocialMediaImagePlugin,
|
||||
JoiningBlocksPlugin,
|
||||
} = require('./src/public/generateEleventyComputed.cjs');
|
||||
const { createSocialImage } = require('./src/public/createSocialImage.cjs');
|
||||
|
||||
module.exports = {
|
||||
setComputedConfig,
|
||||
getComputedConfig,
|
||||
generateEleventyComputed,
|
||||
LayoutPlugin,
|
||||
TitleMetaPlugin,
|
||||
TitlePlugin,
|
||||
EleventyNavigationPlugin,
|
||||
SectionPlugin,
|
||||
SocialMediaImagePlugin,
|
||||
JoiningBlocksPlugin,
|
||||
createSocialImage,
|
||||
};
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
/** @typedef {import('@rocket/cli/types/main').RocketCliOptions} RocketCliOptions */
|
||||
|
||||
export { setComputedConfig, getComputedConfig } from './src/public/computedConfig.cjs';
|
||||
export {
|
||||
generateEleventyComputed,
|
||||
LayoutPlugin,
|
||||
TitleMetaPlugin,
|
||||
TitlePlugin,
|
||||
EleventyNavigationPlugin,
|
||||
SectionPlugin,
|
||||
SocialMediaImagePlugin,
|
||||
JoiningBlocksPlugin,
|
||||
} from './src/public/generateEleventyComputed.cjs';
|
||||
export { createSocialImage } from './src/public/createSocialImage.cjs';
|
||||
|
||||
export { RocketCli } from './src/RocketCli.js';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/cli",
|
||||
"version": "0.8.1",
|
||||
"version": "0.10.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -57,9 +57,9 @@
|
||||
"dependencies": {
|
||||
"@11ty/eleventy": "^0.11.1",
|
||||
"@11ty/eleventy-img": "^0.9.0",
|
||||
"@rocket/building-rollup": "^0.3.0",
|
||||
"@rocket/building-rollup": "^0.4.0",
|
||||
"@rocket/core": "^0.1.2",
|
||||
"@rocket/eleventy-plugin-mdjs-unified": "^0.4.1",
|
||||
"@rocket/eleventy-plugin-mdjs-unified": "^0.6.0",
|
||||
"@rocket/eleventy-rocket-nav": "^0.3.0",
|
||||
"@rollup/plugin-babel": "^5.2.2",
|
||||
"@rollup/plugin-node-resolve": "^11.0.1",
|
||||
@@ -67,12 +67,12 @@
|
||||
"@web/dev-server": "^0.1.4",
|
||||
"@web/dev-server-rollup": "^0.3.2",
|
||||
"@web/rollup-plugin-copy": "^0.2.0",
|
||||
"check-html-links": "^0.2.2",
|
||||
"check-html-links": "^0.2.3",
|
||||
"command-line-args": "^5.1.1",
|
||||
"command-line-usage": "^6.1.1",
|
||||
"fs-extra": "^9.0.1",
|
||||
"micromatch": "^4.0.2",
|
||||
"plugins-manager": "^0.2.1",
|
||||
"plugins-manager": "^0.3.0",
|
||||
"slash": "^3.0.0",
|
||||
"utf8": "^3.0.0",
|
||||
"workbox-window": "^6.1.5"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
{% set rocketServiceWorkerUrl = '/' + rocketConfig.serviceWorkerName %}
|
||||
|
||||
<script>
|
||||
window.__rocketServiceWorkerUrl = '/{{ rocketConfig.serviceWorkerName }}';
|
||||
window.__rocketServiceWorkerUrl = '{{ rocketServiceWorkerUrl | url }}';
|
||||
</script>
|
||||
|
||||
{% if rocketConfig.command == 'build' %}
|
||||
<script type="module" inject-service-worker="" src="{{ '/_assets/scripts/registerServiceWorker.js' | asset | url }}"></script>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<html theme="light" platform="web" lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
@@ -11,21 +12,39 @@
|
||||
}
|
||||
</style>
|
||||
<script type="module">
|
||||
import { render } from 'lit-html';
|
||||
import { render } from '@mdjs/mdjs-story';
|
||||
|
||||
function sanitize(input, type) {
|
||||
return `${document.location.origin}/${input.match(/[a-zA-Z0-9\/\-_]*/)[0]}.${type}`;
|
||||
}
|
||||
|
||||
async function onHashChange() {
|
||||
const urlParts = new URLSearchParams(document.location.hash.substr(1));
|
||||
|
||||
if (urlParts.get('stylesheets')) {
|
||||
for (const stylesheet of urlParts.getAll('stylesheets')) {
|
||||
if (!document.querySelector(`link[rel="stylesheet"][href="${stylesheet}"]`)) {
|
||||
const safeStylesheetUrl = sanitize(stylesheet, 'css');
|
||||
if (!document.querySelector(`link[rel="stylesheet"][href="${safeStylesheetUrl}"]`)) {
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = stylesheet;
|
||||
link.href = safeStylesheetUrl;
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParts.get('moduleUrls')) {
|
||||
for (const moduleUrl of urlParts.getAll('moduleUrls')) {
|
||||
const safeModuleUrl = sanitize(moduleUrl, 'js');
|
||||
if (!document.querySelector(`script[type=module][src="${safeModuleUrl}"]`)) {
|
||||
const script = document.createElement('script');
|
||||
script.type = 'module';
|
||||
script.src = safeModuleUrl;
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParts.get('theme')) {
|
||||
document.documentElement.setAttribute('theme', urlParts.get('theme'));
|
||||
}
|
||||
@@ -45,7 +64,8 @@
|
||||
document.documentElement.removeAttribute('edge-distance');
|
||||
}
|
||||
|
||||
const mod = await import(urlParts.get('story-file'));
|
||||
const safeStoryUrl = sanitize(urlParts.get('story-file'), 'js');
|
||||
const mod = await import(safeStoryUrl);
|
||||
render(mod[urlParts.get('story-key')]({ shadowRoot: document }), document.body);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { rollup } from 'rollup';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { copy } from '@web/rollup-plugin-copy';
|
||||
import { rollupPluginHTML } from '@web/rollup-plugin-html';
|
||||
|
||||
import { createMpaConfig, createServiceWorkerConfig } from '@rocket/building-rollup';
|
||||
import { addPlugin, adjustPluginOptions } from 'plugins-manager';
|
||||
@@ -25,18 +26,14 @@ async function buildAndWrite(config) {
|
||||
|
||||
async function productionBuild(config) {
|
||||
const defaultSetupPlugins = [
|
||||
addPlugin({
|
||||
name: 'copy',
|
||||
plugin: copy,
|
||||
options: {
|
||||
patterns: ['!(*.md|*.html)*', '_merged_assets/_static/**/*.{png,gif,jpg,json,css,svg,ico}'],
|
||||
rootDir: config.outputDevDir,
|
||||
},
|
||||
addPlugin(copy, {
|
||||
patterns: ['!(*.md|*.html)*', '_merged_assets/_static/**/*'],
|
||||
rootDir: config.outputDevDir,
|
||||
}),
|
||||
];
|
||||
if (config.pathPrefix) {
|
||||
defaultSetupPlugins.push(
|
||||
adjustPluginOptions('html', { absolutePathPrefix: config.pathPrefix }),
|
||||
adjustPluginOptions(rollupPluginHTML, { absolutePathPrefix: config.pathPrefix }),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -54,8 +51,8 @@ async function productionBuild(config) {
|
||||
...config.setupBuildPlugins,
|
||||
],
|
||||
});
|
||||
|
||||
await buildAndWrite(mpaConfig);
|
||||
const finalConfig = typeof config.rollup === 'function' ? config.rollup(mpaConfig) : mpaConfig;
|
||||
await buildAndWrite(finalConfig);
|
||||
|
||||
const serviceWorkerSourcePath = path.resolve('docs/_merged_assets/service-worker.js');
|
||||
if (fs.existsSync(serviceWorkerSourcePath)) {
|
||||
|
||||
@@ -19,6 +19,10 @@ const { setComputedConfig } = computedConfigPkg;
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export class RocketEleventy extends Eleventy {
|
||||
/** @type{Required<import('../types/main').RocketCliOptions>} */
|
||||
// @ts-expect-error: awkward to type this in jsdoc
|
||||
config;
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {string} output
|
||||
@@ -26,11 +30,14 @@ export class RocketEleventy extends Eleventy {
|
||||
*/
|
||||
constructor(input, output, cli) {
|
||||
super(input, output);
|
||||
/** @type {*} */
|
||||
this.eleventyFiles;
|
||||
this.__rocketCli = cli;
|
||||
}
|
||||
|
||||
async write() {
|
||||
await this.__rocketCli.mergePresets();
|
||||
for (const fn of this.__rocketCli.config.__before11tyFunctions) await fn();
|
||||
await super.write();
|
||||
await this.__rocketCli.update();
|
||||
}
|
||||
@@ -45,7 +52,10 @@ export class RocketEleventy extends Eleventy {
|
||||
path.join(this.__rocketCli.config._inputDirCwdRelative, '_includes', '**'),
|
||||
];
|
||||
|
||||
ignores = ignores.filter(ignore => !keepWatching.includes(ignore));
|
||||
ignores = ignores.filter(
|
||||
/** @param {string} ignore */
|
||||
ignore => !keepWatching.includes(ignore),
|
||||
);
|
||||
// debug("Ignoring watcher changes to: %o", ignores);
|
||||
|
||||
let configOptions = this.config.chokidarConfig;
|
||||
@@ -69,6 +79,10 @@ export class RocketCli {
|
||||
/** @type {string[]} */
|
||||
errors = [];
|
||||
|
||||
/** @type{Required<import('../types/main').RocketCliOptions>} */
|
||||
// @ts-expect-error: awkward to type this in jsdoc
|
||||
config;
|
||||
|
||||
constructor({ argv } = { argv: undefined }) {
|
||||
const mainDefinitions = [
|
||||
{ name: 'command', defaultOption: true, defaultValue: 'help' },
|
||||
@@ -106,7 +120,8 @@ export class RocketCli {
|
||||
|
||||
const config = new TemplateConfig(null, relCwdPathToConfig);
|
||||
elev.config = config.getConfig();
|
||||
elev.resetConfig();
|
||||
/** @type {*} */
|
||||
(elev).resetConfig();
|
||||
elev.setConfigPathOverride(relCwdPathToConfig);
|
||||
|
||||
elev.isVerbose = false;
|
||||
@@ -120,7 +135,7 @@ export class RocketCli {
|
||||
for (const folder of ['_assets', '_data', '_includes']) {
|
||||
const to = path.join(this.config._inputDirCwdRelative, `_merged${folder}`);
|
||||
await fs.emptyDir(to);
|
||||
for (const sourceDir of this.config._presetPathes) {
|
||||
for (const sourceDir of this.config._presetPaths) {
|
||||
const from = path.join(sourceDir, folder);
|
||||
if (fs.existsSync(from)) {
|
||||
if (folder === '_includes') {
|
||||
@@ -138,7 +153,9 @@ export class RocketCli {
|
||||
*/
|
||||
async setup() {
|
||||
if (this.__isSetup === false) {
|
||||
this.config = await normalizeConfig(this.argvConfig);
|
||||
this.config =
|
||||
/** @type{Required<import('../types/main').RocketCliOptions>} */
|
||||
(await normalizeConfig(this.argvConfig));
|
||||
setComputedConfig(this.config);
|
||||
this.__isSetup = true;
|
||||
}
|
||||
@@ -147,6 +164,10 @@ export class RocketCli {
|
||||
async run() {
|
||||
await this.setup();
|
||||
|
||||
if (this.config.command === 'bootstrap') {
|
||||
return this.bootstrap();
|
||||
}
|
||||
|
||||
for (const plugin of this.config.plugins) {
|
||||
if (this.considerPlugin(plugin) && typeof plugin.setupCommand === 'function') {
|
||||
this.config = plugin.setupCommand(this.config);
|
||||
@@ -187,6 +208,45 @@ export class RocketCli {
|
||||
}
|
||||
}
|
||||
|
||||
async bootstrap() {
|
||||
const outputDir = path.join(this.config.outputDir, '..');
|
||||
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const bootstrapFilesDir = path.join(moduleDir, 'public', 'bootstrap');
|
||||
const packageJsonPath = path.join(outputDir, 'package.json');
|
||||
const gitignorePath = path.join(outputDir, '.gitignore');
|
||||
|
||||
if (!(await fs.pathExists(packageJsonPath))) {
|
||||
await fs.writeJson(packageJsonPath, {});
|
||||
}
|
||||
|
||||
await fs.copy(bootstrapFilesDir, outputDir, {
|
||||
errorOnExist: true,
|
||||
filter: file => !file.endsWith('_gitignore'),
|
||||
});
|
||||
|
||||
const packageJson = await fs.readJson(packageJsonPath);
|
||||
|
||||
await fs.writeJson(
|
||||
packageJsonPath,
|
||||
{
|
||||
...packageJson,
|
||||
type: 'module',
|
||||
scripts: {
|
||||
...packageJson.scripts,
|
||||
start: 'rocket start',
|
||||
docs: 'rocket build',
|
||||
},
|
||||
},
|
||||
{ spaces: 2 },
|
||||
);
|
||||
|
||||
await fs.ensureFile(gitignorePath);
|
||||
await fs.appendFile(
|
||||
gitignorePath,
|
||||
await fs.readFile(path.join(bootstrapFilesDir, '_gitignore'), 'utf8'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RocketPlugin} plugin
|
||||
*/
|
||||
@@ -238,7 +298,7 @@ export class RocketCli {
|
||||
async cleanup() {
|
||||
setComputedConfig({});
|
||||
if (this.eleventy) {
|
||||
this.eleventy.finish();
|
||||
// this.eleventy.finish();
|
||||
// await this.eleventy.stopWatch();
|
||||
}
|
||||
this.stop();
|
||||
|
||||
@@ -50,6 +50,7 @@ export class RocketLint {
|
||||
|
||||
const checkLinks = new CheckHtmlLinksCli();
|
||||
checkLinks.setOptions({
|
||||
...this.config.checkLinks,
|
||||
rootDir: this.config.lintInputDir,
|
||||
printOnError: false,
|
||||
continueOnError: true,
|
||||
|
||||
@@ -1,11 +1,61 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import { startDevServer } from '@web/dev-server';
|
||||
import { fromRollup } from '@web/dev-server-rollup';
|
||||
import { metaConfigToWebDevServerConfig } from 'plugins-manager';
|
||||
import { executeSetupFunctions } from 'plugins-manager';
|
||||
|
||||
/** @typedef {import('../types/main').RocketCliOptions} RocketCliOptions */
|
||||
/** @typedef {import('@web/dev-server').DevServerConfig} DevServerConfig */
|
||||
|
||||
/**
|
||||
* @param {any} config
|
||||
* @param {MetaPluginWrapable[]} metaPlugins
|
||||
* @param {object} [options]
|
||||
* @param {function | null} [options.rollupWrapperFunction]
|
||||
*/
|
||||
export function metaConfigToWebDevServerConfig(
|
||||
config,
|
||||
metaPlugins,
|
||||
{ rollupWrapperFunction = null } = {},
|
||||
) {
|
||||
if (config.plugins) {
|
||||
delete config.setupPlugins;
|
||||
delete config.setupRollupPlugins;
|
||||
return config;
|
||||
}
|
||||
|
||||
const metaPluginsNoWrap = metaPlugins.map(pluginObj => {
|
||||
pluginObj.__noWrap = true;
|
||||
return pluginObj;
|
||||
});
|
||||
|
||||
const rollupPlugins = /** @type {MetaPluginWrapable[]} */ (executeSetupFunctions(
|
||||
config.setupRollupPlugins,
|
||||
[...metaPluginsNoWrap],
|
||||
));
|
||||
|
||||
const wrappedRollupPlugins = rollupPlugins.map(pluginObj => {
|
||||
if (typeof rollupWrapperFunction === 'function' && pluginObj.__noWrap !== true) {
|
||||
pluginObj.plugin = rollupWrapperFunction(pluginObj.plugin);
|
||||
}
|
||||
return pluginObj;
|
||||
});
|
||||
|
||||
const _metaPlugins = executeSetupFunctions(config.setupPlugins, [...wrappedRollupPlugins]);
|
||||
|
||||
const plugins = _metaPlugins.map(pluginObj => {
|
||||
if (pluginObj.options) {
|
||||
return pluginObj.plugin(pluginObj.options);
|
||||
} else {
|
||||
return pluginObj.plugin();
|
||||
}
|
||||
});
|
||||
config.plugins = plugins;
|
||||
|
||||
delete config.setupPlugins;
|
||||
delete config.setupRollupPlugins;
|
||||
return config;
|
||||
}
|
||||
|
||||
export class RocketStart {
|
||||
static pluginName = 'RocketStart';
|
||||
commands = ['start'];
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
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');
|
||||
|
||||
@@ -32,7 +33,7 @@ function replaceBetween({ html, start, end, insert = '' }) {
|
||||
const i = start.line;
|
||||
const line = lines[i];
|
||||
const upToChange = line.slice(0, start.character);
|
||||
const afterChange = line.slice(end.character - 4);
|
||||
const afterChange = line.slice(end.character);
|
||||
|
||||
lines[i] = `${upToChange}${insert}${afterChange}`;
|
||||
return lines.join('\n');
|
||||
@@ -82,33 +83,54 @@ function getAttributes(data) {
|
||||
// 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) {
|
||||
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;
|
||||
// Img tag only has open tag.
|
||||
const { openStart, openEnd } = 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) {
|
||||
images.push({
|
||||
presetName,
|
||||
attributes,
|
||||
src,
|
||||
title,
|
||||
alt,
|
||||
openStart,
|
||||
closeEnd,
|
||||
});
|
||||
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,
|
||||
openEnd,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +162,7 @@ async function responsiveImages(images, { inputPath, outputDir, imagePresets = {
|
||||
|
||||
const metadata = await EleventyImage(filePath, {
|
||||
outputDir: path.join(outputDir, 'images'),
|
||||
urlPath: '/images/',
|
||||
urlPath: urlFilter('/images/'),
|
||||
...presetSettings,
|
||||
});
|
||||
const lowsrc = metadata.jpeg[0];
|
||||
@@ -194,11 +216,11 @@ async function responsiveImages(images, { inputPath, outputDir, imagePresets = {
|
||||
|
||||
function updateHtml(html, changes) {
|
||||
let newHtml = html;
|
||||
for (const change of changes) {
|
||||
for (const change of changes.reverse()) {
|
||||
newHtml = replaceBetween({
|
||||
html: newHtml,
|
||||
start: change.openStart,
|
||||
end: change.closeEnd,
|
||||
end: change.openEnd,
|
||||
insert: change.newHtml,
|
||||
});
|
||||
}
|
||||
@@ -231,7 +253,7 @@ async function insertResponsiveImages(html) {
|
||||
imagePresets: config.imagePresets,
|
||||
};
|
||||
|
||||
let images = getImages(html);
|
||||
let images = getImages(html, options);
|
||||
images = resolveFilePath(images, options);
|
||||
images = await responsiveImages(images, options);
|
||||
const newHtml = updateHtml(html, images);
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
const rocketCopy = {
|
||||
configFunction: (eleventyConfig, { _inputDirCwdRelative, filesExtensionsToCopy }) => {
|
||||
eleventyConfig.addPassthroughCopy(`${_inputDirCwdRelative}/**/*.{${filesExtensionsToCopy}}`);
|
||||
configFunction: (eleventyConfig, { _inputDirCwdRelative }) => {
|
||||
eleventyConfig.addPassthroughCopy(`${_inputDirCwdRelative}/!(*.md|*.html)*`);
|
||||
eleventyConfig.addPassthroughCopy(
|
||||
`${_inputDirCwdRelative}/!(_includes|_data|_assets|_merged_data|_merged_includes)*/**/!(*.md|*.html)*`,
|
||||
);
|
||||
eleventyConfig.addPassthroughCopy(`${_inputDirCwdRelative}/_merged_assets/_static/**/*`);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
/** @typedef {import('@web/dev-server').DevServerConfig} DevServerConfig */
|
||||
|
||||
/** @typedef {import('../types/main').RocketCliOptions} RocketCliOptions */
|
||||
/** @typedef {import('../types/main').ImagePreset} ImagePreset */
|
||||
/** @typedef {import('../types/main').RocketPlugin} RocketPlugin */
|
||||
|
||||
import path from 'path';
|
||||
@@ -19,9 +20,25 @@ import { fileURLToPath } from '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
|
||||
* @returns {Promise<RocketCliOptions>}
|
||||
* @returns {Promise<RocketCliOptions & { __before11tyFunctions: RocketCliOptions['before11ty'][] }>}
|
||||
*/
|
||||
export async function normalizeConfig(inConfig) {
|
||||
let config = {
|
||||
@@ -45,11 +62,17 @@ export async function normalizeConfig(inConfig) {
|
||||
devServer: {},
|
||||
|
||||
...inConfig,
|
||||
|
||||
/** @type{RocketCliOptions['before11ty'][]} */
|
||||
__before11tyFunctions: [],
|
||||
|
||||
/** @type{{[key: string]: ImagePreset}} */
|
||||
imagePresets: {
|
||||
responsive: {
|
||||
widths: [600, 900, 1640],
|
||||
formats: ['avif', 'jpeg'],
|
||||
sizes: '100vw',
|
||||
ignore,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -104,9 +127,9 @@ export async function normalizeConfig(inConfig) {
|
||||
const _inputDirCwdRelative = path.join(_configDirCwdRelative, config.inputDir);
|
||||
|
||||
// cli core preset is always first
|
||||
config._presetPathes = [path.join(__dirname, '..', 'preset')];
|
||||
config._presetPaths = [path.join(__dirname, '..', 'preset')];
|
||||
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);
|
||||
@@ -142,16 +165,16 @@ export async function normalizeConfig(inConfig) {
|
||||
if (preset.setupCliPlugins) {
|
||||
config.setupCliPlugins = [...config.setupCliPlugins, ...preset.setupCliPlugins];
|
||||
}
|
||||
|
||||
if (typeof preset.before11ty === 'function') {
|
||||
config.__before11tyFunctions.push(preset.before11ty);
|
||||
}
|
||||
}
|
||||
// add "local" preset
|
||||
config._presetPathes.push(path.resolve(_inputDirCwdRelative));
|
||||
config._presetPaths.push(path.resolve(_inputDirCwdRelative));
|
||||
|
||||
/** @type {MetaPlugin[]} */
|
||||
let pluginsMeta = [
|
||||
{ name: 'RocketStart', plugin: RocketStart },
|
||||
{ name: 'RocketBuild', plugin: RocketBuild },
|
||||
{ name: 'RocketLint', plugin: RocketLint },
|
||||
];
|
||||
let pluginsMeta = [{ plugin: RocketStart }, { plugin: RocketBuild }, { plugin: RocketLint }];
|
||||
|
||||
if (Array.isArray(config.setupCliPlugins)) {
|
||||
for (const setupFn of config.setupCliPlugins) {
|
||||
@@ -169,6 +192,10 @@ export async function normalizeConfig(inConfig) {
|
||||
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 🤷♂️
|
||||
|
||||
return {
|
||||
|
||||
6
packages/cli/src/public/bootstrap/_gitignore
Normal file
6
packages/cli/src/public/bootstrap/_gitignore
Normal file
@@ -0,0 +1,6 @@
|
||||
node_modules
|
||||
|
||||
## Rocket ignore files (need to be the full relative path to the folders)
|
||||
docs/_merged_data/
|
||||
docs/_merged_assets/
|
||||
docs/_merged_includes/
|
||||
3
packages/cli/src/public/bootstrap/docs/.eleventyignore
Normal file
3
packages/cli/src/public/bootstrap/docs/.eleventyignore
Normal file
@@ -0,0 +1,3 @@
|
||||
_assets
|
||||
_includes
|
||||
_data
|
||||
3
packages/cli/src/public/bootstrap/docs/index.md
Normal file
3
packages/cli/src/public/bootstrap/docs/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Welcome to Your Rocket Site
|
||||
|
||||
Add your markdown content here.
|
||||
5
packages/cli/src/public/bootstrap/rocket.config.js
Normal file
5
packages/cli/src/public/bootstrap/rocket.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
|
||||
export default {
|
||||
presets: [rocketLaunch()],
|
||||
};
|
||||
@@ -5,8 +5,10 @@ const { createSocialImage: defaultCreateSocialImage } = require('./createSocialI
|
||||
const { getComputedConfig } = require('./computedConfig.cjs');
|
||||
const { executeSetupFunctions } = require('plugins-manager');
|
||||
|
||||
function titleMetaPlugin() {
|
||||
return async data => {
|
||||
class TitleMetaPlugin {
|
||||
static dataName = 'titleMeta';
|
||||
|
||||
async execute(data) {
|
||||
if (data.titleMeta) {
|
||||
return data.titleMeta;
|
||||
}
|
||||
@@ -17,29 +19,35 @@ function titleMetaPlugin() {
|
||||
return titleMetaFromContent;
|
||||
}
|
||||
return {};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function titlePlugin() {
|
||||
return async data => {
|
||||
class TitlePlugin {
|
||||
static dataName = 'title';
|
||||
|
||||
async execute(data) {
|
||||
if (data.title) {
|
||||
return data.title;
|
||||
}
|
||||
return data.titleMeta?.title;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function eleventyNavigationPlugin() {
|
||||
return async data => {
|
||||
class EleventyNavigationPlugin {
|
||||
static dataName = 'eleventyNavigation';
|
||||
|
||||
async execute(data) {
|
||||
if (data.eleventyNavigation) {
|
||||
return data.eleventyNavigation;
|
||||
}
|
||||
return data.titleMeta?.eleventyNavigation;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function sectionPlugin() {
|
||||
return async data => {
|
||||
class SectionPlugin {
|
||||
static dataName = 'section';
|
||||
|
||||
async execute(data) {
|
||||
if (data.section) {
|
||||
return data.section;
|
||||
}
|
||||
@@ -52,11 +60,17 @@ function sectionPlugin() {
|
||||
return parts[1];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function layoutPlugin({ defaultLayout = 'layout-default' } = {}) {
|
||||
return async data => {
|
||||
class LayoutPlugin {
|
||||
static dataName = 'layout';
|
||||
|
||||
constructor({ defaultLayout = 'layout-default' } = {}) {
|
||||
this.defaultLayout = defaultLayout;
|
||||
}
|
||||
|
||||
async execute(data) {
|
||||
if (data.layout) {
|
||||
return data.layout;
|
||||
}
|
||||
@@ -66,22 +80,29 @@ function layoutPlugin({ defaultLayout = 'layout-default' } = {}) {
|
||||
return 'layout-index';
|
||||
}
|
||||
}
|
||||
return defaultLayout;
|
||||
};
|
||||
return this.defaultLayout;
|
||||
}
|
||||
}
|
||||
|
||||
function socialMediaImagePlugin(args = {}) {
|
||||
const { createSocialImage = defaultCreateSocialImage, rocketConfig = {} } = args;
|
||||
class SocialMediaImagePlugin {
|
||||
static dataName = 'socialMediaImage';
|
||||
|
||||
const cleanedUpArgs = { ...args };
|
||||
delete cleanedUpArgs.createSocialImage;
|
||||
constructor(args = {}) {
|
||||
const { createSocialImage = defaultCreateSocialImage, rocketConfig = {} } = args;
|
||||
|
||||
return async data => {
|
||||
this.cleanedUpArgs = { ...args };
|
||||
delete this.cleanedUpArgs.createSocialImage;
|
||||
|
||||
this.rocketConfig = rocketConfig;
|
||||
this.createSocialImage = createSocialImage;
|
||||
}
|
||||
|
||||
async execute(data) {
|
||||
if (data.socialMediaImage) {
|
||||
return data.socialMediaImage;
|
||||
}
|
||||
|
||||
if (rocketConfig.createSocialMediaImages === false) {
|
||||
if (this.rocketConfig.createSocialMediaImages === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,18 +116,18 @@ function socialMediaImagePlugin(args = {}) {
|
||||
const section = data.section ? ' ' + data.section[0].toUpperCase() + data.section.slice(1) : '';
|
||||
const footer = `${data.site.name}${section}`;
|
||||
|
||||
const imgUrl = await createSocialImage({
|
||||
const imgUrl = await this.createSocialImage({
|
||||
title,
|
||||
subTitle,
|
||||
footer,
|
||||
section,
|
||||
...cleanedUpArgs,
|
||||
...this.cleanedUpArgs,
|
||||
});
|
||||
return imgUrl;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function sortyByOrder(a, b) {
|
||||
function sortByOrder(a, b) {
|
||||
if (a.order > b.order) {
|
||||
return 1;
|
||||
}
|
||||
@@ -127,45 +148,50 @@ async function dirToTree(sourcePath, extra = '') {
|
||||
if (entry.isDirectory()) {
|
||||
const value = await dirToTree(sourcePath, relativePath);
|
||||
unsortedEntries.push({
|
||||
order: matches && matches.length > 0 ? parseInt(matches[1]) : 0,
|
||||
order: matches && matches.length > 0 ? parseInt(matches[1]) : 10000,
|
||||
name: entry.name,
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
unsortedEntries.push({
|
||||
order: matches && matches.length > 0 ? parseInt(matches[1]) : 0,
|
||||
order: matches && matches.length > 0 ? parseInt(matches[1]) : 10000,
|
||||
name: entry.name,
|
||||
value: relativePath,
|
||||
});
|
||||
}
|
||||
}
|
||||
const sortedTree = {};
|
||||
for (const unsortedEntry of unsortedEntries.sort(sortyByOrder)) {
|
||||
for (const unsortedEntry of unsortedEntries.sort(sortByOrder)) {
|
||||
sortedTree[unsortedEntry.name] = unsortedEntry.value;
|
||||
}
|
||||
return sortedTree;
|
||||
}
|
||||
|
||||
function joiningBlocksPlugin(rocketConfig) {
|
||||
const { _inputDirCwdRelative } = rocketConfig;
|
||||
const partialsSource = path.resolve(_inputDirCwdRelative, '_merged_includes');
|
||||
return async () => {
|
||||
const joiningBlocks = await dirToTree(partialsSource, '_joiningBlocks');
|
||||
class JoiningBlocksPlugin {
|
||||
static dataName = '_joiningBlocks';
|
||||
|
||||
constructor(rocketConfig) {
|
||||
const { _inputDirCwdRelative } = rocketConfig;
|
||||
this.partialsSource = path.resolve(_inputDirCwdRelative, '_merged_includes');
|
||||
}
|
||||
|
||||
async execute() {
|
||||
const joiningBlocks = await dirToTree(this.partialsSource, '_joiningBlocks');
|
||||
return joiningBlocks;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function generateEleventyComputed() {
|
||||
const rocketConfig = getComputedConfig();
|
||||
|
||||
let metaPlugins = [
|
||||
{ name: 'titleMeta', plugin: titleMetaPlugin },
|
||||
{ name: 'title', plugin: titlePlugin },
|
||||
{ name: 'eleventyNavigation', plugin: eleventyNavigationPlugin },
|
||||
{ name: 'section', plugin: sectionPlugin },
|
||||
{ name: 'socialMediaImage', plugin: socialMediaImagePlugin, options: { rocketConfig } },
|
||||
{ name: '_joiningBlocks', plugin: joiningBlocksPlugin, options: rocketConfig },
|
||||
{ name: 'layout', plugin: layoutPlugin },
|
||||
{ plugin: TitleMetaPlugin, options: {} },
|
||||
{ plugin: TitlePlugin, options: {} },
|
||||
{ plugin: EleventyNavigationPlugin, options: {} },
|
||||
{ plugin: SectionPlugin, options: {} },
|
||||
{ plugin: SocialMediaImagePlugin, options: { rocketConfig } },
|
||||
{ plugin: JoiningBlocksPlugin, options: rocketConfig },
|
||||
{ plugin: LayoutPlugin, options: {} },
|
||||
];
|
||||
|
||||
const finalMetaPlugins = executeSetupFunctions(
|
||||
@@ -176,13 +202,24 @@ function generateEleventyComputed() {
|
||||
const eleventyComputed = {};
|
||||
for (const pluginObj of finalMetaPlugins) {
|
||||
if (pluginObj.options) {
|
||||
eleventyComputed[pluginObj.name] = pluginObj.plugin(pluginObj.options);
|
||||
const inst = new pluginObj.plugin(pluginObj.options);
|
||||
eleventyComputed[inst.constructor.dataName] = inst.execute.bind(inst);
|
||||
} else {
|
||||
eleventyComputed[pluginObj.name] = pluginObj.plugin();
|
||||
const inst = new pluginObj.plugin();
|
||||
eleventyComputed[inst.constructor.dataName] = inst.execute.bind(inst);
|
||||
}
|
||||
}
|
||||
|
||||
return eleventyComputed;
|
||||
}
|
||||
|
||||
module.exports = { generateEleventyComputed };
|
||||
module.exports = {
|
||||
generateEleventyComputed,
|
||||
LayoutPlugin,
|
||||
TitleMetaPlugin,
|
||||
TitlePlugin,
|
||||
EleventyNavigationPlugin,
|
||||
SectionPlugin,
|
||||
SocialMediaImagePlugin,
|
||||
JoiningBlocksPlugin,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const eleventyPluginMdjsUnified = require('@rocket/eleventy-plugin-mdjs-unified');
|
||||
const eleventyRocketNav = require('@rocket/eleventy-rocket-nav');
|
||||
const remark2rehype = require('remark-rehype');
|
||||
|
||||
const { getComputedConfig } = require('../public/computedConfig.cjs');
|
||||
const rocketFilters = require('../eleventy-plugins/rocketFilters.cjs');
|
||||
@@ -9,7 +10,7 @@ const { adjustPluginOptions } = require('plugins-manager');
|
||||
const image = require('./mdjsImageHandler.cjs');
|
||||
|
||||
const defaultSetupUnifiedPlugins = [
|
||||
adjustPluginOptions('remark2rehype', {
|
||||
adjustPluginOptions(remark2rehype, {
|
||||
handlers: {
|
||||
image,
|
||||
},
|
||||
@@ -23,31 +24,24 @@ module.exports = function (eleventyConfig) {
|
||||
|
||||
let metaPlugins = [
|
||||
{
|
||||
name: 'rocket-filters',
|
||||
plugin: rocketFilters,
|
||||
options: { _inputDirCwdRelative },
|
||||
},
|
||||
{
|
||||
name: 'rocket-copy',
|
||||
plugin: rocketCopy,
|
||||
options: {
|
||||
_inputDirCwdRelative,
|
||||
filesExtensionsToCopy: 'png,gif,jpg,jpeg,svg,css,xml,json,js',
|
||||
},
|
||||
options: { _inputDirCwdRelative },
|
||||
},
|
||||
{
|
||||
name: 'eleventy-plugin-mdjs-unified',
|
||||
plugin: eleventyPluginMdjsUnified,
|
||||
options: {
|
||||
setupUnifiedPlugins: [...defaultSetupUnifiedPlugins, ...config.setupUnifiedPlugins],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'eleventy-rocket-nav',
|
||||
plugin: eleventyRocketNav,
|
||||
options: {},
|
||||
},
|
||||
{
|
||||
name: 'rocket-collections',
|
||||
plugin: rocketCollections,
|
||||
options: { _inputDirCwdRelative },
|
||||
},
|
||||
@@ -72,7 +66,7 @@ module.exports = function (eleventyConfig) {
|
||||
}
|
||||
|
||||
if (config.eleventy) {
|
||||
const returnValue = config.eleventy(eleventyConfig);
|
||||
const returnValue = config.eleventy(eleventyConfig, config);
|
||||
if (returnValue) {
|
||||
const returnString = JSON.stringify(returnValue, null, 2);
|
||||
const msg = [
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import chai from 'chai';
|
||||
import { RocketCli } from '../src/RocketCli.js';
|
||||
import path from 'path';
|
||||
import globby from 'globby';
|
||||
import fs from 'fs-extra';
|
||||
import prettier from 'prettier';
|
||||
import { fileURLToPath } from 'url';
|
||||
@@ -19,6 +20,7 @@ export function setFixtureDir(importMetaUrl) {
|
||||
* @property {boolean} stripStartEndWhitespace
|
||||
* @property {boolean} stripScripts
|
||||
* @property {boolean} formatHtml
|
||||
* @property {boolean} replaceImageHashes
|
||||
* @property {start|build} type
|
||||
*/
|
||||
|
||||
@@ -51,13 +53,20 @@ export async function readOutput(
|
||||
stripScripts = false,
|
||||
formatHtml = false,
|
||||
type = 'build',
|
||||
replaceImageHashes = false,
|
||||
} = {},
|
||||
) {
|
||||
if (!cli || !cli.config) {
|
||||
throw new Error(`No valid cli provided to readOutput - you passed a ${typeof cli}: ${cli}`);
|
||||
}
|
||||
|
||||
const outputDir = type === 'build' ? cli.config.outputDir : cli.config.outputDevDir;
|
||||
const outputDir =
|
||||
type === 'bootstrap'
|
||||
? path.join(cli.config.outputDir, '..')
|
||||
: type === 'build'
|
||||
? cli.config.outputDir
|
||||
: cli.config.outputDevDir;
|
||||
|
||||
let text = await fs.promises.readFile(path.join(outputDir, fileName));
|
||||
text = text.toString();
|
||||
if (stripToBody) {
|
||||
@@ -70,6 +79,9 @@ export async function readOutput(
|
||||
const scriptCloseTagStart = text.indexOf('</script>', scriptOpenTagEnd) + 9;
|
||||
text = text.substring(0, scriptOpenTagEnd) + text.substring(scriptCloseTagStart);
|
||||
}
|
||||
if (replaceImageHashes) {
|
||||
text = text.replace(/\/images\/([a-z0-9]+)-/g, '/images/__HASH__-');
|
||||
}
|
||||
if (formatHtml) {
|
||||
text = prettier.format(text, { parser: 'html', printWidth: 100 });
|
||||
}
|
||||
@@ -79,72 +91,78 @@ export async function readOutput(
|
||||
return text;
|
||||
}
|
||||
|
||||
export function startOutputExist(cli, fileName) {
|
||||
const outputDir = cli.config.outputDevDir;
|
||||
return fs.existsSync(path.join(outputDir, fileName));
|
||||
export async function getfixtureExpectedFiles(pathToDir) {
|
||||
const cwd = path.join(fixtureDir, pathToDir);
|
||||
const paths = await globby('**/*', { cwd, absolute: true, dot: true });
|
||||
return paths;
|
||||
}
|
||||
|
||||
export function buildOutputExist(cli, fileName) {
|
||||
const outputDir = cli.config.outputDir;
|
||||
return fs.existsSync(path.join(outputDir, fileName));
|
||||
}
|
||||
export async function execute(pathToConfig, { type = 'start', captureLog = false } = {}) {
|
||||
let log = [];
|
||||
const origLog = console.log;
|
||||
if (captureLog) {
|
||||
console.log = (...args) => {
|
||||
log = [...log, ...args];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} cli
|
||||
* @param {string} fileName
|
||||
* @param {readOutputOptions} options
|
||||
*/
|
||||
export async function readStartOutput(cli, fileName, options = {}) {
|
||||
options.type = 'start';
|
||||
return readOutput(cli, fileName, options);
|
||||
}
|
||||
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
|
||||
const configFileDir = path.dirname(configFile);
|
||||
|
||||
/**
|
||||
* @param {*} cli
|
||||
* @param {string} fileName
|
||||
* @param {readOutputOptions} options
|
||||
*/
|
||||
export async function readBuildOutput(cli, fileName, options = {}) {
|
||||
options.type = 'build';
|
||||
return readOutput(cli, fileName, options);
|
||||
}
|
||||
const cli = new RocketCli({
|
||||
argv: [type, '--config-file', configFile],
|
||||
});
|
||||
|
||||
export async function execute(cli, configFileDir) {
|
||||
await cli.setup();
|
||||
cli.config.outputDevDir = path.join(configFileDir, '__output-dev');
|
||||
cli.config.devServer.open = false;
|
||||
cli.config.devServer.port = 8080;
|
||||
cli.config.watch = false;
|
||||
cli.config.outputDir = path.join(configFileDir, '__output');
|
||||
|
||||
await fs.emptyDir(cli.config.outputDevDir);
|
||||
await fs.emptyDir(cli.config.outputDir);
|
||||
|
||||
await cli.run();
|
||||
return cli;
|
||||
|
||||
/**
|
||||
* @param {*} cli
|
||||
* @param {string} fileName
|
||||
* @param {readOutputOptions} options
|
||||
*/
|
||||
async function readOutput2(fileName, options = {}) {
|
||||
options.type = type;
|
||||
return readOutput(cli, fileName, options);
|
||||
}
|
||||
|
||||
function outputExists(fileName) {
|
||||
const outputDir = type === 'build' ? cli.config.outputDir : cli.config.outputDevDir;
|
||||
const filePath = path.join(outputDir, fileName);
|
||||
|
||||
return fs.existsSync(filePath);
|
||||
}
|
||||
|
||||
if (captureLog) {
|
||||
console.log = origLog;
|
||||
}
|
||||
return { log, readOutput: readOutput2, cli, outputExists };
|
||||
}
|
||||
|
||||
export async function executeStart(pathToConfig) {
|
||||
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
|
||||
const cli = new RocketCli({
|
||||
argv: ['start', '--config-file', configFile],
|
||||
});
|
||||
await execute(cli, path.dirname(configFile));
|
||||
return cli;
|
||||
}
|
||||
export async function executeBootstrap(pathToDir) {
|
||||
const configFileDir = path.join(fixtureDir, pathToDir.split('/').join(path.sep));
|
||||
const cli = new RocketCli({ argv: ['bootstrap'] });
|
||||
|
||||
export async function executeBuild(pathToConfig) {
|
||||
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
|
||||
const cli = new RocketCli({
|
||||
argv: ['build', '--config-file', configFile],
|
||||
});
|
||||
await execute(cli, path.dirname(configFile));
|
||||
return cli;
|
||||
}
|
||||
await cli.setup();
|
||||
cli.config.outputDevDir = path.join(configFileDir, '__output-dev');
|
||||
cli.config.devServer.open = false;
|
||||
cli.config.devServer.port = 8080;
|
||||
cli.config.watch = false;
|
||||
cli.config.outputDir = path.join(configFileDir, '__output');
|
||||
|
||||
export async function executeLint(pathToConfig) {
|
||||
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
|
||||
const cli = new RocketCli({
|
||||
argv: ['lint', '--config-file', configFile],
|
||||
});
|
||||
await execute(cli, path.dirname(configFile));
|
||||
return cli;
|
||||
await fs.emptyDir(configFileDir);
|
||||
await cli.run();
|
||||
|
||||
return { cli };
|
||||
}
|
||||
|
||||
export function trimWhiteSpace(inString) {
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import chai from 'chai';
|
||||
import chalk from 'chalk';
|
||||
import {
|
||||
executeBuild,
|
||||
executeStart,
|
||||
readBuildOutput,
|
||||
readStartOutput,
|
||||
setFixtureDir,
|
||||
} from '@rocket/cli/test-helpers';
|
||||
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
|
||||
|
||||
const { expect } = chai;
|
||||
|
||||
describe('RocketCli computedConfig', () => {
|
||||
let cli;
|
||||
let cleanupCli;
|
||||
|
||||
before(() => {
|
||||
// ignore colors in tests as most CIs won't support it
|
||||
@@ -20,90 +14,117 @@ describe('RocketCli computedConfig', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (cli?.cleanup) {
|
||||
await cli.cleanup();
|
||||
if (cleanupCli?.cleanup) {
|
||||
await cleanupCli.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('will extract a title from markdown and set first folder as section', async () => {
|
||||
cli = await executeStart('computed-config-fixtures/headlines/rocket.config.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'computed-config-fixtures/headlines/rocket.config.js',
|
||||
{ captureLog: true },
|
||||
);
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
const [indexTitle, indexSection] = indexHtml.split('\n');
|
||||
expect(indexTitle).to.equal('Root');
|
||||
expect(indexSection).to.be.undefined;
|
||||
|
||||
const subHtml = await readStartOutput(cli, 'sub/index.html');
|
||||
const subHtml = await readOutput('sub/index.html');
|
||||
const [subTitle, subSection] = subHtml.split('\n');
|
||||
expect(subTitle).to.equal('Root: Sub');
|
||||
expect(subSection).to.equal('sub');
|
||||
|
||||
const subSubHtml = await readStartOutput(cli, 'sub/subsub/index.html');
|
||||
const subSubHtml = await readOutput('sub/subsub/index.html');
|
||||
const [subSubTitle, subSubSection] = subSubHtml.split('\n');
|
||||
expect(subSubTitle).to.equal('Sub: SubSub');
|
||||
expect(subSubSection).to.equal('sub');
|
||||
|
||||
const sub2Html = await readStartOutput(cli, 'sub2/index.html');
|
||||
const sub2Html = await readOutput('sub2/index.html');
|
||||
const [sub2Title, sub2Section] = sub2Html.split('\n');
|
||||
expect(sub2Title).to.equal('Root: Sub2');
|
||||
expect(sub2Section).to.equal('sub2');
|
||||
|
||||
const withDataHtml = await readStartOutput(cli, 'with-data/index.html');
|
||||
const withDataHtml = await readOutput('with-data/index.html');
|
||||
const [withDataTitle, withDataSection] = withDataHtml.split('\n');
|
||||
expect(withDataTitle).to.equal('Set via data');
|
||||
expect(withDataSection).be.undefined;
|
||||
});
|
||||
|
||||
it('will note create a social media image in "start"', async () => {
|
||||
cli = await executeStart('computed-config-fixtures/social-images-only-build/rocket.config.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'computed-config-fixtures/social-images-only-build/rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.equal('');
|
||||
});
|
||||
|
||||
it('will create a social media image in "build"', async () => {
|
||||
cli = await executeBuild('computed-config-fixtures/social-images-only-build/rocket.config.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'computed-config-fixtures/social-images-only-build/rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
type: 'build',
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readBuildOutput(cli, 'index.html', {
|
||||
const indexHtml = await readOutput('index.html', {
|
||||
stripToBody: true,
|
||||
});
|
||||
expect(indexHtml).to.equal('/_merged_assets/11ty-img/5893749-1200.png');
|
||||
});
|
||||
|
||||
it('will create a social media image for every page', async () => {
|
||||
cli = await executeStart('computed-config-fixtures/social-images/rocket.config.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'computed-config-fixtures/social-images/rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.equal('/_merged_assets/11ty-img/c4c29ec7-1200.png');
|
||||
|
||||
const guidesHtml = await readStartOutput(cli, 'guides/index.html');
|
||||
const guidesHtml = await readOutput('guides/index.html');
|
||||
expect(guidesHtml).to.equal('/_merged_assets/11ty-img/c593a8cd-1200.png');
|
||||
|
||||
const gettingStartedHtml = await readStartOutput(
|
||||
cli,
|
||||
'guides/first-pages/getting-started/index.html',
|
||||
);
|
||||
const gettingStartedHtml = await readOutput('guides/first-pages/getting-started/index.html');
|
||||
expect(gettingStartedHtml).to.equal('/_merged_assets/11ty-img/d989ab1a-1200.png');
|
||||
});
|
||||
|
||||
it('can override the svg function globally to adjust all social media image', async () => {
|
||||
cli = await executeStart('computed-config-fixtures/social-images-override/rocket.config.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'computed-config-fixtures/social-images-override/rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.equal('/_merged_assets/11ty-img/d76265ed-1200.png');
|
||||
|
||||
const guidesHtml = await readStartOutput(cli, 'guides/index.html');
|
||||
const guidesHtml = await readOutput('guides/index.html');
|
||||
expect(guidesHtml).to.equal('/_merged_assets/11ty-img/d76265ed-1200.png');
|
||||
|
||||
const gettingStartedHtml = await readStartOutput(
|
||||
cli,
|
||||
'guides/first-pages/getting-started/index.html',
|
||||
);
|
||||
const gettingStartedHtml = await readOutput('guides/first-pages/getting-started/index.html');
|
||||
expect(gettingStartedHtml).to.equal('/_merged_assets/11ty-img/d76265ed-1200.png');
|
||||
});
|
||||
|
||||
it('will add "../" for links and image urls only within named template files', async () => {
|
||||
cli = await executeStart('computed-config-fixtures/image-link/rocket.config.js');
|
||||
const {
|
||||
cli,
|
||||
readOutput,
|
||||
} = await execute('computed-config-fixtures/image-link/rocket.config.js', { captureLog: true });
|
||||
cleanupCli = cli;
|
||||
|
||||
const namedMdContent = [
|
||||
'<p>',
|
||||
@@ -127,22 +148,22 @@ describe('RocketCli computedConfig', () => {
|
||||
'</div>',
|
||||
];
|
||||
|
||||
const templateHtml = await readStartOutput(cli, 'template/index.html', { formatHtml: true });
|
||||
const templateHtml = await readOutput('template/index.html', { formatHtml: true });
|
||||
expect(templateHtml, 'template/index.html does not match').to.equal(
|
||||
namedHtmlContent.join('\n'),
|
||||
);
|
||||
|
||||
const guidesHtml = await readStartOutput(cli, 'guides/index.html', { formatHtml: true });
|
||||
const guidesHtml = await readOutput('guides/index.html', { formatHtml: true });
|
||||
expect(guidesHtml, 'guides/index.html does not match').to.equal(
|
||||
[...namedMdContent, ...namedHtmlContent].join('\n'),
|
||||
);
|
||||
|
||||
const noAdjustHtml = await readStartOutput(cli, 'no-adjust/index.html');
|
||||
const noAdjustHtml = await readOutput('no-adjust/index.html');
|
||||
expect(noAdjustHtml, 'no-adjust/index.html does not match').to.equal(
|
||||
'<p>Nothing to adjust in here</p>',
|
||||
);
|
||||
|
||||
const rawHtml = await readStartOutput(cli, 'one-level/raw/index.html');
|
||||
const rawHtml = await readOutput('one-level/raw/index.html');
|
||||
expect(rawHtml, 'raw/index.html does not match').to.equal(
|
||||
[
|
||||
'<div>',
|
||||
@@ -159,7 +180,7 @@ describe('RocketCli computedConfig', () => {
|
||||
);
|
||||
|
||||
// for index files no '../' will be added
|
||||
const indexHtml = await readStartOutput(cli, 'index.html', { formatHtml: true });
|
||||
const indexHtml = await readOutput('index.html', { formatHtml: true });
|
||||
expect(indexHtml, 'index.html does not match').to.equal(
|
||||
[
|
||||
'<p>',
|
||||
@@ -188,19 +209,28 @@ describe('RocketCli computedConfig', () => {
|
||||
});
|
||||
|
||||
it('can be configured via setupEleventyComputedConfig', async () => {
|
||||
cli = await executeStart('computed-config-fixtures/setup/addPlugin.rocket.config.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'computed-config-fixtures/setup/addPlugin.rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.equal('test-value');
|
||||
});
|
||||
|
||||
it('always assigns layout-default exept for index.* files who get layout-index', async () => {
|
||||
cli = await executeStart('computed-config-fixtures/layout/rocket.config.js');
|
||||
const { cli, readOutput } = await execute('computed-config-fixtures/layout/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.include('<body layout="layout-index">');
|
||||
|
||||
const pageHtml = await readStartOutput(cli, 'page/index.html');
|
||||
const pageHtml = await readOutput('page/index.html');
|
||||
expect(pageHtml).to.include('<body layout="layout-default">');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,19 +2,18 @@ import chai from 'chai';
|
||||
import fetch from 'node-fetch';
|
||||
import chalk from 'chalk';
|
||||
import {
|
||||
executeBuild,
|
||||
executeLint,
|
||||
executeStart,
|
||||
execute,
|
||||
executeBootstrap,
|
||||
expectThrowsAsync,
|
||||
readBuildOutput,
|
||||
readStartOutput,
|
||||
getfixtureExpectedFiles,
|
||||
setFixtureDir,
|
||||
} from '@rocket/cli/test-helpers';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
const { expect } = chai;
|
||||
|
||||
describe('RocketCli e2e', () => {
|
||||
let cli;
|
||||
let cleanupCli;
|
||||
|
||||
before(() => {
|
||||
// ignore colors in tests as most CIs won't support it
|
||||
@@ -23,21 +22,43 @@ describe('RocketCli e2e', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (cli?.cleanup) {
|
||||
await cli.cleanup();
|
||||
if (cleanupCli?.cleanup) {
|
||||
await cleanupCli.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('can add a unified plugin via the config', async () => {
|
||||
cli = await executeStart('e2e-fixtures/unified-plugin/rocket.config.js');
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
expect(indexHtml).to.equal('<p>See a 🐶</p>');
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/unified-plugin/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.equal(`<p>See a 🐶</p>`);
|
||||
});
|
||||
|
||||
describe('bootstrap command', () => {
|
||||
it('can bootstrap a project', async () => {
|
||||
const { cli } = await executeBootstrap('e2e-fixtures/bootstrap/__output');
|
||||
cleanupCli = cli;
|
||||
|
||||
for (const p of await getfixtureExpectedFiles('e2e-fixtures/bootstrap/expected')) {
|
||||
const actual = await fs.readFile(
|
||||
p.replace('expected', '__output').replace('_gitignore', '.gitignore'),
|
||||
'utf8',
|
||||
);
|
||||
const expected = await fs.readFile(p, 'utf8');
|
||||
expect(actual, p).to.equal(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('eleventy in config', () => {
|
||||
it('can modify eleventy via an elventy function in the config', async () => {
|
||||
cli = await executeStart('e2e-fixtures/content/eleventy.rocket.config.js');
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/content/eleventy.rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.equal(
|
||||
['# BEFORE #', '<p>Content inside <code>docs/index.md</code></p>'].join('\n'),
|
||||
);
|
||||
@@ -45,7 +66,8 @@ describe('RocketCli e2e', () => {
|
||||
|
||||
it('will throw if you try to set options by returning an object', async () => {
|
||||
await expectThrowsAsync(
|
||||
() => executeStart('e2e-fixtures/content/eleventy-return.rocket.config.js'),
|
||||
() =>
|
||||
execute('e2e-fixtures/content/eleventy-return.rocket.config.js', { captureLog: true }),
|
||||
{
|
||||
errorMatch: /Error in your Eleventy config file.*/,
|
||||
},
|
||||
@@ -55,13 +77,23 @@ describe('RocketCli e2e', () => {
|
||||
|
||||
describe('setupDevAndBuildPlugins in config', () => {
|
||||
it('can add a rollup plugin via setupDevAndBuildPlugins for build command', async () => {
|
||||
cli = await executeBuild('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js');
|
||||
const inlineModule = await readBuildOutput(cli, 'e97af63d.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'e2e-fixtures/rollup-plugin/devbuild.rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
type: 'build',
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
const inlineModule = await readOutput('e97af63d.js');
|
||||
expect(inlineModule).to.equal('var a={test:"data"};console.log(a);');
|
||||
});
|
||||
|
||||
it('can add a rollup plugin via setupDevAndBuildPlugins for start command', async () => {
|
||||
cli = await executeStart('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js');
|
||||
const { cli } = await execute('e2e-fixtures/rollup-plugin/devbuild.rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const response = await fetch('http://localhost:8080/test-data.json');
|
||||
expect(response.ok).to.be.true; // no server error
|
||||
@@ -72,42 +104,89 @@ describe('RocketCli e2e', () => {
|
||||
});
|
||||
|
||||
it('can add a rollup plugin for dev & build and modify a build only plugin via the config', async () => {
|
||||
cli = await executeBuild('e2e-fixtures/rollup-plugin/devbuild-build.rocket.config.js');
|
||||
const inlineModule = await readBuildOutput(cli, 'e97af63d.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'e2e-fixtures/rollup-plugin/devbuild-build.rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
type: 'build',
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
const inlineModule = await readOutput('e97af63d.js');
|
||||
expect(inlineModule).to.equal('var a={test:"data"};console.log(a);');
|
||||
});
|
||||
|
||||
it('can adjust the inputDir', async () => {
|
||||
cli = await executeStart('e2e-fixtures/change-input-dir/rocket.config.js');
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/change-input-dir/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.equal('<p>Markdown in <code>docs/page/index.md</code></p>');
|
||||
});
|
||||
|
||||
it('can access main rocket config values via {{rocketConfig.value}}', async () => {
|
||||
cli = await executeStart('e2e-fixtures/rocket-config-in-template/rocket.config.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'e2e-fixtures/rocket-config-in-template/rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.equal(
|
||||
'<p>You can show Rocket config data like rocketConfig.absoluteBaseUrl = <a href="http://test-domain.com/">http://test-domain.com/</a></p>',
|
||||
);
|
||||
});
|
||||
|
||||
it('can add a pathPrefix that will not influence the start command', async () => {
|
||||
cli = await executeStart('e2e-fixtures/content/pathPrefix.rocket.config.js');
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/content/pathPrefix.rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const linkHtml = await readStartOutput(cli, 'link/index.html');
|
||||
const linkHtml = await readOutput('link/index.html');
|
||||
expect(linkHtml).to.equal(
|
||||
['<p><a href="../">home</a></p>', '<p><a href="/">absolute home</a></p>'].join('\n'),
|
||||
);
|
||||
const assetHtml = await readStartOutput(cli, 'use-assets/index.html');
|
||||
const assetHtml = await readOutput('use-assets/index.html');
|
||||
expect(assetHtml).to.equal('<link rel="stylesheet" href="/_merged_assets/some.css">');
|
||||
const imageHtml = await readOutput('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 () => {
|
||||
cli = await executeBuild('e2e-fixtures/content/pathPrefix.rocket.config.js');
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/content/pathPrefix.rocket.config.js', {
|
||||
captureLog: true,
|
||||
type: 'build',
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const linkHtml = await readBuildOutput(cli, 'link/index.html', {
|
||||
const linkHtml = await readOutput('link/index.html', {
|
||||
stripToBody: true,
|
||||
});
|
||||
expect(linkHtml).to.equal(
|
||||
@@ -115,15 +194,90 @@ describe('RocketCli e2e', () => {
|
||||
'\n',
|
||||
),
|
||||
);
|
||||
const assetHtml = await readBuildOutput(cli, 'use-assets/index.html');
|
||||
const assetHtml = await readOutput('use-assets/index.html');
|
||||
expect(assetHtml).to.equal(
|
||||
'<html><head><link rel="stylesheet" href="../41297ffa.css">\n\n</head><body>\n\n</body></html>',
|
||||
);
|
||||
let imageHtml = await readOutput('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 () => {
|
||||
await expectThrowsAsync(() => executeLint('e2e-fixtures/lint-links/rocket.config.js'), {
|
||||
errorMatch: /Found 1 missing reference targets/,
|
||||
await expectThrowsAsync(
|
||||
() => execute('e2e-fixtures/lint-links/rocket.config.js', { captureLog: true, type: 'lint' }),
|
||||
{
|
||||
errorMatch: /Found 1 missing reference targets/,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('can completely take over the rollup config', async () => {
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/rollup-override/rocket.config.js', {
|
||||
captureLog: true,
|
||||
type: 'build',
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readOutput('index.html', {
|
||||
stripToBody: true,
|
||||
formatHtml: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<h1 id="importing-foo">',
|
||||
' <a aria-hidden="true" tabindex="-1" href="#importing-foo"><span class="icon icon-link"></span></a',
|
||||
' >Importing foo',
|
||||
'</h1>',
|
||||
'',
|
||||
'<script type="module" src="./7338509a.js" mdjs-setup=""></script>',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
|
||||
describe('can adjust the eleventy config while having access to the rocketConfig', () => {
|
||||
it('testing start', async () => {
|
||||
const { cli, readOutput } = await execute(
|
||||
'e2e-fixtures/adjust-eleventy-config/rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.equal('<p><a href="start:/path/to/page/">link</a></p>');
|
||||
});
|
||||
|
||||
it('testing build', async () => {
|
||||
const { cli, readOutput } = await execute(
|
||||
'e2e-fixtures/adjust-eleventy-config/rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
type: 'build',
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
const indexBuildHtml = await readOutput('index.html', {
|
||||
stripToBody: true,
|
||||
});
|
||||
expect(indexBuildHtml).to.equal('<p><a href="build:/path/to/page/">link</a></p>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import chai from 'chai';
|
||||
import chalk from 'chalk';
|
||||
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers';
|
||||
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
|
||||
|
||||
const { expect } = chai;
|
||||
|
||||
describe('RocketCli images', () => {
|
||||
let cli;
|
||||
let cleanupCli;
|
||||
|
||||
before(() => {
|
||||
// ignore colors in tests as most CIs won't support it
|
||||
@@ -14,15 +14,21 @@ describe('RocketCli images', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (cli?.cleanup) {
|
||||
await cli.cleanup();
|
||||
if (cleanupCli?.cleanup) {
|
||||
await cleanupCli.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
describe('Images', () => {
|
||||
it('does render content images responsive', async () => {
|
||||
cli = await executeStart('e2e-fixtures/images/rocket.config.js');
|
||||
const indexHtml = await readStartOutput(cli, 'index.html', { formatHtml: true });
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/images/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
const indexHtml = await readOutput('index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
@@ -30,18 +36,18 @@ describe('RocketCli images', () => {
|
||||
' <picture>',
|
||||
' <source',
|
||||
' type="image/avif"',
|
||||
' srcset="/images/d67643ad-600.avif 600w, /images/d67643ad-900.avif 900w"',
|
||||
' srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w"',
|
||||
' sizes="100vw"',
|
||||
' />',
|
||||
' <source',
|
||||
' type="image/jpeg"',
|
||||
' srcset="/images/d67643ad-600.jpeg 600w, /images/d67643ad-900.jpeg 900w"',
|
||||
' srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w"',
|
||||
' sizes="100vw"',
|
||||
' />',
|
||||
' <img',
|
||||
' alt="My Image Alternative Text"',
|
||||
' rocket-image="responsive"',
|
||||
' src="/images/d67643ad-600.jpeg"',
|
||||
' src="/images/__HASH__-600.jpeg"',
|
||||
' width="600"',
|
||||
' height="316"',
|
||||
' loading="lazy"',
|
||||
@@ -53,51 +59,187 @@ describe('RocketCli images', () => {
|
||||
'</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 });
|
||||
expect(indexHtml).to.equal(
|
||||
const keepSvgHtml = await readOutput('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/d67643ad-600.avif 600w, /images/d67643ad-900.avif 900w"',
|
||||
' srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w"',
|
||||
' sizes="100vw"',
|
||||
' />',
|
||||
' <source',
|
||||
' type="image/jpeg"',
|
||||
' srcset="/images/d67643ad-600.jpeg 600w, /images/d67643ad-900.jpeg 900w"',
|
||||
' srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w"',
|
||||
' sizes="100vw"',
|
||||
' />',
|
||||
' <img',
|
||||
' alt="one"',
|
||||
' alt="My Image Alternative Text"',
|
||||
' rocket-image="responsive"',
|
||||
' src="/images/d67643ad-600.jpeg"',
|
||||
' src="/images/__HASH__-600.jpeg"',
|
||||
' width="600"',
|
||||
' height="316"',
|
||||
' loading="lazy"',
|
||||
' decoding="async"',
|
||||
' />',
|
||||
' </picture>',
|
||||
'',
|
||||
'</p>',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
const tableHtml = await readOutput('table/index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(tableHtml).to.equal(
|
||||
[
|
||||
'<table>',
|
||||
' <thead>',
|
||||
' <tr>',
|
||||
' <th>Image</th>',
|
||||
' </tr>',
|
||||
' </thead>',
|
||||
' <tbody>',
|
||||
' <tr>',
|
||||
' <td>',
|
||||
' <figure>',
|
||||
' <picture>',
|
||||
' <source',
|
||||
' type="image/avif"',
|
||||
' srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w"',
|
||||
' sizes="100vw"',
|
||||
' />',
|
||||
' <source',
|
||||
' type="image/jpeg"',
|
||||
' srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w"',
|
||||
' sizes="100vw"',
|
||||
' />',
|
||||
' <img',
|
||||
' alt="My Image Alternative Text"',
|
||||
' rocket-image="responsive"',
|
||||
' src="/images/__HASH__-600.jpeg"',
|
||||
' width="600"',
|
||||
' height="316"',
|
||||
' loading="lazy"',
|
||||
' decoding="async"',
|
||||
' />',
|
||||
' </picture>',
|
||||
' <figcaption>My Image Description</figcaption>',
|
||||
' </figure>',
|
||||
' </td>',
|
||||
' </tr>',
|
||||
' </tbody>',
|
||||
'</table>',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
|
||||
it('can configure more patterns to ignore', async () => {
|
||||
const { cli, readOutput } = await execute(
|
||||
'e2e-fixtures/images/ignore-more.rocket.config.js',
|
||||
{ captureLog: true },
|
||||
);
|
||||
cleanupCli = cli;
|
||||
const keepSvgHtml = await readOutput('ignores/index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
|
||||
// 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 () => {
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/images/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
const indexHtml = await readOutput('two-images/index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
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/d67643ad-600.avif 600w, /images/d67643ad-900.avif 900w"',
|
||||
' srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w"',
|
||||
' sizes="100vw"',
|
||||
' />',
|
||||
' <source',
|
||||
' type="image/jpeg"',
|
||||
' srcset="/images/d67643ad-600.jpeg 600w, /images/d67643ad-900.jpeg 900w"',
|
||||
' 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/d67643ad-600.jpeg"',
|
||||
' src="/images/__HASH__-600.jpeg"',
|
||||
' width="600"',
|
||||
' height="316"',
|
||||
' loading="lazy"',
|
||||
@@ -110,8 +252,14 @@ describe('RocketCli images', () => {
|
||||
});
|
||||
|
||||
it('can configure those responsive images', async () => {
|
||||
cli = await executeStart('e2e-fixtures/images/small.rocket.config.js');
|
||||
const indexHtml = await readStartOutput(cli, 'index.html', { formatHtml: true });
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/images/small.rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
const indexHtml = await readOutput('index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
@@ -119,18 +267,18 @@ describe('RocketCli images', () => {
|
||||
' <picture>',
|
||||
' <source',
|
||||
' type="image/avif"',
|
||||
' srcset="/images/d67643ad-30.avif 30w, /images/d67643ad-60.avif 60w"',
|
||||
' srcset="/images/__HASH__-30.avif 30w, /images/__HASH__-60.avif 60w"',
|
||||
' sizes="(min-width: 1024px) 30px, 60px"',
|
||||
' />',
|
||||
' <source',
|
||||
' type="image/jpeg"',
|
||||
' srcset="/images/d67643ad-30.jpeg 30w, /images/d67643ad-60.jpeg 60w"',
|
||||
' 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/d67643ad-30.jpeg"',
|
||||
' src="/images/__HASH__-30.jpeg"',
|
||||
' width="30"',
|
||||
' height="15"',
|
||||
' loading="lazy"',
|
||||
@@ -145,26 +293,32 @@ describe('RocketCli images', () => {
|
||||
});
|
||||
|
||||
it('will only render a figure & figcaption if there is a caption/title', async () => {
|
||||
cli = await executeStart('e2e-fixtures/images/small.rocket.config.js');
|
||||
const indexHtml = await readStartOutput(cli, 'no-title/index.html', { formatHtml: true });
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/images/small.rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
const indexHtml = await readOutput('no-title/index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
' <picture>',
|
||||
' <source',
|
||||
' type="image/avif"',
|
||||
' srcset="/images/d67643ad-30.avif 30w, /images/d67643ad-60.avif 60w"',
|
||||
' srcset="/images/__HASH__-30.avif 30w, /images/__HASH__-60.avif 60w"',
|
||||
' sizes="(min-width: 1024px) 30px, 60px"',
|
||||
' />',
|
||||
' <source',
|
||||
' type="image/jpeg"',
|
||||
' srcset="/images/d67643ad-30.jpeg 30w, /images/d67643ad-60.jpeg 60w"',
|
||||
' 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/d67643ad-30.jpeg"',
|
||||
' src="/images/__HASH__-30.jpeg"',
|
||||
' width="30"',
|
||||
' height="15"',
|
||||
' loading="lazy"',
|
||||
@@ -177,16 +331,23 @@ describe('RocketCli images', () => {
|
||||
});
|
||||
|
||||
it('will render an img with srcset and sizes if there is only one image format', async () => {
|
||||
cli = await executeStart('e2e-fixtures/images/single-format.rocket.config.js');
|
||||
const indexHtml = await readStartOutput(cli, 'no-title/index.html', { formatHtml: true });
|
||||
const {
|
||||
cli,
|
||||
readOutput,
|
||||
} = await execute('e2e-fixtures/images/single-format.rocket.config.js', { captureLog: true });
|
||||
cleanupCli = cli;
|
||||
const indexHtml = await readOutput('no-title/index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
' <img',
|
||||
' alt="My Image Alternative Text"',
|
||||
' rocket-image="responsive"',
|
||||
' src="/images/d67643ad-30.jpeg"',
|
||||
' srcset="/images/d67643ad-30.jpeg 30w, /images/d67643ad-60.jpeg 60w"',
|
||||
' 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"',
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
import chai from 'chai';
|
||||
import chalk from 'chalk';
|
||||
import {
|
||||
executeStart,
|
||||
readStartOutput,
|
||||
trimWhiteSpace,
|
||||
setFixtureDir,
|
||||
} from '@rocket/cli/test-helpers';
|
||||
import { execute, trimWhiteSpace, setFixtureDir } from '@rocket/cli/test-helpers';
|
||||
|
||||
const { expect } = chai;
|
||||
|
||||
describe('RocketCli mergeTemplates', () => {
|
||||
let cli;
|
||||
let cleanupCli;
|
||||
|
||||
before(() => {
|
||||
// ignore colors in tests as most CIs won't support it
|
||||
@@ -19,24 +14,37 @@ describe('RocketCli mergeTemplates', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (cli?.cleanup) {
|
||||
await cli.cleanup();
|
||||
if (cleanupCli?.cleanup) {
|
||||
await cleanupCli.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('merges it in the defined order', async () => {
|
||||
cli = await executeStart('merge-templates-fixtures/order/rocket.config.js');
|
||||
const { cli, readOutput } = await execute('merge-templates-fixtures/order/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(trimWhiteSpace(indexHtml)).to.equal(
|
||||
['<p>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'),
|
||||
);
|
||||
});
|
||||
|
||||
it('presets can overwrite in order', async () => {
|
||||
cli = await executeStart('merge-templates-fixtures/overwrite/rocket.config.js');
|
||||
const { cli, readOutput } = await execute(
|
||||
'merge-templates-fixtures/overwrite/rocket.config.js',
|
||||
{ captureLog: true },
|
||||
);
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(trimWhiteSpace(indexHtml)).to.equal(
|
||||
['<p>overwritten second</p>', '<p>third</p>', '<p>overwritten first to be last</p>'].join(
|
||||
'\n',
|
||||
@@ -45,9 +53,12 @@ describe('RocketCli mergeTemplates', () => {
|
||||
});
|
||||
|
||||
it('presets can add inbetween', async () => {
|
||||
cli = await executeStart('merge-templates-fixtures/add/rocket.config.js');
|
||||
const { cli, readOutput } = await execute('merge-templates-fixtures/add/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(trimWhiteSpace(indexHtml)).to.equal(
|
||||
[
|
||||
'<p>first</p>',
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import chai from 'chai';
|
||||
import chalk from 'chalk';
|
||||
import { executeStart, readStartOutput, setFixtureDir } from '@rocket/cli/test-helpers';
|
||||
import { execute, setFixtureDir } from '@rocket/cli/test-helpers';
|
||||
|
||||
const { expect } = chai;
|
||||
|
||||
describe('RocketCli preset', () => {
|
||||
let cli;
|
||||
let cleanupCli;
|
||||
|
||||
before(() => {
|
||||
// ignore colors in tests as most CIs won't support it
|
||||
@@ -14,21 +14,24 @@ describe('RocketCli preset', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (cli?.cleanup) {
|
||||
await cli.cleanup();
|
||||
if (cleanupCli?.cleanup) {
|
||||
await cleanupCli.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('offers a default layout (with head, header, content, footer, bottom) and raw layout', async () => {
|
||||
cli = await executeStart('preset-fixtures/default/rocket.config.js');
|
||||
const { cli, readOutput } = await execute('preset-fixtures/default/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const rawHtml = await readStartOutput(cli, 'raw/index.html');
|
||||
const rawHtml = await readOutput('raw/index.html');
|
||||
expect(rawHtml).to.equal('<p>Just raw</p>');
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.include('<body layout="layout-index">');
|
||||
|
||||
const pageHtml = await readStartOutput(cli, 'page/index.html', {
|
||||
const pageHtml = await readOutput('page/index.html', {
|
||||
stripScripts: true,
|
||||
formatHtml: true,
|
||||
});
|
||||
@@ -86,12 +89,6 @@ describe('RocketCli preset', () => {
|
||||
' </div>',
|
||||
'',
|
||||
' <footer id="main-footer"></footer>',
|
||||
'',
|
||||
' <script',
|
||||
' type="module"',
|
||||
' inject-service-worker=""',
|
||||
' src="/_merged_assets/scripts/registerServiceWorker.js"',
|
||||
' ></script>',
|
||||
' </body>',
|
||||
'</html>',
|
||||
].join('\n'),
|
||||
@@ -99,24 +96,33 @@ describe('RocketCli preset', () => {
|
||||
});
|
||||
|
||||
it('allows to add content to the head without overriding', async () => {
|
||||
cli = await executeStart('preset-fixtures/add-to-head/rocket.config.js');
|
||||
const { cli, readOutput } = await execute('preset-fixtures/add-to-head/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html');
|
||||
const indexHtml = await readOutput('index.html');
|
||||
expect(indexHtml).to.include('<meta name="added" content="at the top" />');
|
||||
});
|
||||
|
||||
it('a preset can provide an adjustImagePresets() function', async () => {
|
||||
cli = await executeStart('preset-fixtures/use-preset/rocket.config.js');
|
||||
const { cli, readOutput } = await execute('preset-fixtures/use-preset/rocket.config.js', {
|
||||
captureLog: true,
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html', { formatHtml: true });
|
||||
const indexHtml = await readOutput('index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
' <img',
|
||||
' alt="My Image Alternative Text"',
|
||||
' rocket-image="responsive"',
|
||||
' src="/images/1f847765-30.jpeg"',
|
||||
' srcset="/images/1f847765-30.jpeg 30w, /images/1f847765-60.jpeg 60w"',
|
||||
' src="/images/__HASH__-30.jpeg"',
|
||||
' srcset="/images/__HASH__-30.jpeg 30w, /images/__HASH__-60.jpeg 60w"',
|
||||
' sizes="30px"',
|
||||
' width="30"',
|
||||
' height="15"',
|
||||
|
||||
81
packages/cli/test-node/RocketCli.service-worker.test.js
Normal file
81
packages/cli/test-node/RocketCli.service-worker.test.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import chai from 'chai';
|
||||
import chalk from 'chalk';
|
||||
import { execute, 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 cleanupCli;
|
||||
|
||||
before(() => {
|
||||
// ignore colors in tests as most CIs won't support it
|
||||
chalk.level = 0;
|
||||
setFixtureDir(import.meta.url);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (cleanupCli?.cleanup) {
|
||||
await cleanupCli.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('will add a script to inject the service worker', async () => {
|
||||
const { cli, readOutput } = await execute('e2e-fixtures/service-worker/rocket.config.js', {
|
||||
captureLog: true,
|
||||
type: 'build',
|
||||
});
|
||||
cleanupCli = cli;
|
||||
|
||||
// we check the start output here as in the rollup build version it's hard to find
|
||||
const indexHtml = await readOutput('../__output-dev/index.html');
|
||||
const indexInject = getInjectServiceWorker(indexHtml);
|
||||
expect(indexInject).to.equal(
|
||||
'<script type="module" inject-service-worker="" src="/_merged_assets/scripts/registerServiceWorker.js"></script>',
|
||||
);
|
||||
expect(getServiceWorkerUrl(indexHtml)).to.equal('/service-worker.js');
|
||||
|
||||
// we check the start output here as in the rollup build version it's hard to find
|
||||
const subHtml = await readOutput('../__output-dev/sub/index.html');
|
||||
const subInject = getInjectServiceWorker(subHtml);
|
||||
expect(subInject).to.equal(
|
||||
'<script type="module" inject-service-worker="" src="/_merged_assets/scripts/registerServiceWorker.js"></script>',
|
||||
);
|
||||
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 () => {
|
||||
const { cli, readOutput } = await execute(
|
||||
'e2e-fixtures/service-worker/pathPrefix.rocket.config.js',
|
||||
{
|
||||
captureLog: true,
|
||||
type: 'build',
|
||||
},
|
||||
);
|
||||
cleanupCli = cli;
|
||||
const indexHtml = await readOutput('index.html');
|
||||
const indexInject = getInjectServiceWorker(indexHtml);
|
||||
expect(indexInject).to.equal(
|
||||
'<script type="module" inject-service-worker="" src="/my-prefix-folder/_merged_assets/scripts/registerServiceWorker.js"></script>',
|
||||
);
|
||||
expect(getServiceWorkerUrl(indexHtml)).to.equal('/my-prefix-folder/service-worker.js');
|
||||
const subHtml = await readOutput('sub/index.html');
|
||||
const subInject = getInjectServiceWorker(subHtml);
|
||||
expect(subInject).to.equal(
|
||||
'<script type="module" inject-service-worker="" src="/my-prefix-folder/_merged_assets/scripts/registerServiceWorker.js"></script>',
|
||||
);
|
||||
expect(getServiceWorkerUrl(subHtml)).to.equal('/my-prefix-folder/service-worker.js');
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user