Compare commits

..

26 Commits

Author SHA1 Message Date
github-actions[bot]
c009801164 Version Packages 2022-03-08 14:41:55 +01:00
Thomas Allmer
60310ab3dd fix: improve performance by loading sax-wasm only once 2022-03-08 14:37:31 +01:00
github-actions[bot]
db03f69210 Version Packages 2022-03-07 19:27:03 +01:00
Thomas Allmer
e6c3d274cf feat(mdjs-core): support js client as an alias to js script 2022-03-07 19:19:24 +01:00
github-actions[bot]
f9014c15a6 Version Packages 2022-03-07 18:42:20 +01:00
Thomas Allmer
7e277cd88f feat(plugins-manager): support a wrapPlugin property for adding 2022-03-07 18:35:41 +01:00
Thomas Allmer
bc6106381c chore: lock file maintainance 2022-03-06 21:05:23 +01:00
dependabot[bot]
00bf3882f6 chore(deps-dev): bump node-fetch from 2.6.1 to 2.6.7
Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.1 to 2.6.7.
- [Release notes](https://github.com/node-fetch/node-fetch/releases)
- [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.1...v2.6.7)

---
updated-dependencies:
- dependency-name: node-fetch
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-06 20:51:33 +01:00
dependabot[bot]
543e297c5b chore(deps): bump pathval from 1.1.0 to 1.1.1
Bumps [pathval](https://github.com/chaijs/pathval) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/chaijs/pathval/releases)
- [Changelog](https://github.com/chaijs/pathval/blob/master/CHANGELOG.md)
- [Commits](https://github.com/chaijs/pathval/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: pathval
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-06 20:50:48 +01:00
dependabot[bot]
70b0ce8e1c chore(deps): bump simple-get from 3.1.0 to 3.1.1
Bumps [simple-get](https://github.com/feross/simple-get) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/feross/simple-get/releases)
- [Commits](https://github.com/feross/simple-get/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: simple-get
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-06 20:50:31 +01:00
github-actions[bot]
9f8785a885 Version Packages 2022-03-06 20:46:44 +01:00
Thomas Allmer
62637a829e chore: add changeset 2022-03-06 20:44:17 +01:00
Westbrook Johnson
81c4d7bf3c Use a more recently published prism converter for rehype 2022-03-06 20:44:17 +01:00
github-actions[bot]
08181194e2 Version Packages 2022-01-31 13:45:06 +01:00
Thomas Allmer
97cb38ccb8 fix(mdjs-core): add missing slash dependency 2022-01-31 13:43:36 +01:00
github-actions[bot]
26d3de1444 Version Packages 2022-01-30 11:48:03 +01:00
Thomas Allmer
1f141058c1 fix(drawer): add export map with /define side effect import 2022-01-30 11:45:47 +01:00
github-actions[bot]
08574c9b31 Version Packages 2022-01-05 09:34:58 +01:00
gvangeest
e81b77f236 fix(mdjs-preview): separate preview and viewer theme styling 2022-01-03 18:36:09 +01:00
qa46hx
456b8e78f0 fix(mdjs-preview): add css variable to border-color of viewer 2021-12-05 13:30:28 +01:00
github-actions[bot]
0d7ea015af Version Packages 2021-11-16 18:48:20 +01:00
Thomas Allmer
445b02872f fix: update to latest lit, @open-wc, @lion packages 2021-11-16 17:07:53 +01:00
Thomas Allmer
1a599db3ed chore: lock file maintainance 2021-11-16 08:05:37 +01:00
Thomas Allmer
6b6bed5391 chore: update remark-html 2021-11-16 08:05:37 +01:00
github-actions[bot]
30eb822151 Version Packages 2021-11-11 10:11:42 +01:00
Thomas Allmer
15a82c0e4d fix: improve mdjs preview iframe security 2021-11-11 10:05:51 +01:00
191 changed files with 977 additions and 5149 deletions

1
.gitignore vendored
View File

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

View File

@@ -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
```

View File

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

View File

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

View File

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

View File

@@ -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
```

View File

@@ -4,7 +4,7 @@ Use mdjs in your Eleventy site.
## Setup
```
```shell
npm install @rocket/eleventy-plugin-mdjs
```

View File

@@ -22,7 +22,7 @@ Read the [Introducing Check HTMl Links - no more bad links](../../blog/introduci
## Installation
```
```shell
npm i -D check-html-links
```

View File

@@ -112,16 +112,13 @@ addPlugin(MyClass, { otherProp: 'new name' }); // ts error
Many plugin systems require you to either execute a plugin function like in `rollup`.
<!-- prettier-ignore-start -->
```js
import json from '@rollup/plugin-json';
/** @type {import('rocket/cli').RocketCliConfig} */
export default ({
export default /** @type {import('rocket/cli').RocketCliConfig} */ ({
plugins: [json({ preferConst: true })],
});
```
<!-- prettier-ignore-end -->
or add it in a special way like in `eleventy`
@@ -254,6 +251,18 @@ addPlugin(myPlugin, { myFlag: true }); // ts ok
addPlugin(myPlugin, { notExisting: true }); // ts error
```
Note: There is a "hidden" feature in addPlugin that if you attach a `wrapPlugin` property to the returning function it will call `wrapPlugin` on the plugin before adding it.
```js
// example auto wrap rollup plugins for @web/dev-server
import { fromRollup } from '@web/dev-server-rollup';
const userSetupFunctions = [addPlugin(json)].map(mod => {
mod.wrapPlugin = fromRollup;
return mod;
});
```
## Adjusting Plugin Options
Adjusting options means to either

View File

@@ -23,7 +23,7 @@ Will be ordered as `First`, `Second`,
Internally `# Foo >> Bar >> Baz ||20` gets converted to.
```
```yml
---
title: Bar: Baz
eleventyNavigation:

4
netlify.toml Normal file
View File

@@ -0,0 +1,4 @@
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = "default-src 'self'; script-src 'self' www.googletagmanager.com 'sha256-W6Gq+BvrdAAMbF8E7WHA7UPQxuUOfJM8E9mpKD0oihA=' 'sha256-vFU+IJ5dUUukI5Varwy49dN2d89DmFj7UNewqQv88sw='; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src 'self' data: fonts.gstatic.com;"

View File

@@ -29,7 +29,6 @@
"postinstall": "npm run setup",
"release": "changeset publish && yarn format",
"rocket:build": "node packages/cli/src/cli.js build",
"rocket:upgrade": "node packages/cli/src/cli.js upgrade",
"search": "node packages/cli/src/cli.js search",
"setup": "npm run setup:ts-configs && npm run build:packages",
"setup:patches": "npx patch-package",
@@ -37,7 +36,7 @@
"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:node": "mocha \"packages/*/test-node/**/*.test.{ts,js,mjs,cjs}\" --timeout 5000 --reporter dot --exit",
"test:web": "web-test-runner",
"types": "run-s types:clear types:copy types:build",
"types:build": "tsc --build",
@@ -48,7 +47,7 @@
"update-package-configs": "node scripts/update-package-configs.mjs && yarn format"
},
"devDependencies": {
"@changesets/cli": "^2.12.0",
"@changesets/cli": "^2.20.0",
"@custom-elements-manifest/analyzer": "^0.4.12",
"@open-wc/testing": "^3.0.0-next.1",
"@rollup/plugin-commonjs": "^17.0.0",
@@ -76,7 +75,7 @@
"husky": "^4.3.7",
"lint-staged": "^10.5.3",
"mocha": "^8.2.1",
"node-fetch": "^2.6.1",
"node-fetch": "^2.6.7",
"npm-run-all": "^4.1.5",
"onchange": "^7.1.0",
"prettier": "^2.2.1",
@@ -85,8 +84,6 @@
"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",

View File

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

View File

@@ -1 +1,19 @@
<web-menu name="article-overview"></web-menu>
<div class="articles">
{% for post in posts %}
{% if post.data.published %}
<article>
{% if post.data.cover_image %}
<a href="{{ post.url | url }}" class="thumbnail" style="background-image: url({{ post.data.cover_image | url }});">
</a>
{% endif %}
<div class="content">
<h2>
<a href="{{ post.url | url }}">{{ post.data.title }}</a>
</h2>
<p>{{ post.data.description }}</p>
<a class="read" href="{{ post.url | url }}">...read more</a>
</div>
</article>
{% endif %}
{% endfor %}
</div>

View File

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

View File

@@ -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
```

View File

@@ -1,5 +1,24 @@
# @rocket/cli
## 0.10.2
### Patch Changes
- 60310ab: Improve performance by initializing sax-wasm only once even when it is running in parallel
- Updated dependencies [60310ab]
- @rocket/eleventy-rocket-nav@0.3.1
## 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

View File

@@ -2,6 +2,9 @@ const { setComputedConfig, getComputedConfig } = require('./src/public/computedC
const {
generateEleventyComputed,
LayoutPlugin,
TitleMetaPlugin,
TitlePlugin,
EleventyNavigationPlugin,
SectionPlugin,
SocialMediaImagePlugin,
JoiningBlocksPlugin,
@@ -13,6 +16,9 @@ module.exports = {
getComputedConfig,
generateEleventyComputed,
LayoutPlugin,
TitleMetaPlugin,
TitlePlugin,
EleventyNavigationPlugin,
SectionPlugin,
SocialMediaImagePlugin,
JoiningBlocksPlugin,

View File

@@ -4,6 +4,9 @@ export { setComputedConfig, getComputedConfig } from './src/public/computedConfi
export {
generateEleventyComputed,
LayoutPlugin,
TitleMetaPlugin,
TitlePlugin,
EleventyNavigationPlugin,
SectionPlugin,
SocialMediaImagePlugin,
JoiningBlocksPlugin,

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/cli",
"version": "0.10.0",
"version": "0.10.2",
"publishConfig": {
"access": "public"
},
@@ -60,6 +60,7 @@
"@rocket/building-rollup": "^0.4.0",
"@rocket/core": "^0.1.2",
"@rocket/eleventy-plugin-mdjs-unified": "^0.6.0",
"@rocket/eleventy-rocket-nav": "^0.3.1",
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-node-resolve": "^11.0.1",
"@web/config-loader": "^0.1.3",
@@ -70,7 +71,6 @@
"command-line-args": "^5.1.1",
"command-line-usage": "^6.1.1",
"fs-extra": "^9.0.1",
"gray-matter": "^4.0.3",
"micromatch": "^4.0.2",
"plugins-manager": "^0.3.0",
"slash": "^3.0.0",

View File

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

View File

@@ -1,7 +1,6 @@
<html theme="light" platform="web" lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="menu:exclude" content="true">
<meta charset="utf-8">
<style type="text/css">
body {
@@ -15,19 +14,37 @@
<script type="module">
import { render } from '@mdjs/mdjs-story';
function sanitize(input, type) {
return `${document.location.origin}/${input.match(/[a-zA-Z0-9\/\-_]*/)[0]}.${type}`;
}
async function onHashChange() {
const urlParts = new URLSearchParams(document.location.hash.substr(1));
if (urlParts.get('stylesheets')) {
for (const stylesheet of urlParts.getAll('stylesheets')) {
if (!document.querySelector(`link[rel="stylesheet"][href="${stylesheet}"]`)) {
const safeStylesheetUrl = sanitize(stylesheet, 'css');
if (!document.querySelector(`link[rel="stylesheet"][href="${safeStylesheetUrl}"]`)) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = stylesheet;
link.href = safeStylesheetUrl;
document.head.appendChild(link);
}
}
}
if (urlParts.get('moduleUrls')) {
for (const moduleUrl of urlParts.getAll('moduleUrls')) {
const safeModuleUrl = sanitize(moduleUrl, 'js');
if (!document.querySelector(`script[type=module][src="${safeModuleUrl}"]`)) {
const script = document.createElement('script');
script.type = 'module';
script.src = safeModuleUrl;
document.head.appendChild(script);
}
}
}
if (urlParts.get('theme')) {
document.documentElement.setAttribute('theme', urlParts.get('theme'));
}
@@ -47,7 +64,8 @@
document.documentElement.removeAttribute('edge-distance');
}
const mod = await import(urlParts.get('story-file'));
const safeStoryUrl = sanitize(urlParts.get('story-file'), 'js');
const mod = await import(safeStoryUrl);
render(mod[urlParts.get('story-key')]({ shadowRoot: document }), document.body);
}

View File

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

View File

@@ -243,9 +243,9 @@ async function insertResponsiveImages(html) {
const config = getComputedConfig();
if (!isSetup) {
await parser.prepareWasm(saxWasmBuffer);
isSetup = true;
isSetup = parser.prepareWasm(saxWasmBuffer);
}
await isSetup;
const options = {
inputPath: this.inputPath,

View File

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

View File

@@ -14,11 +14,8 @@ import { readConfig } from '@web/config-loader';
import { RocketStart } from './RocketStart.js';
import { RocketBuild } from './RocketBuild.js';
import { RocketUpgrade } from './RocketUpgrade.js';
import { RocketLint } from './RocketLint.js';
import { webMenu } from '@web/menu';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -45,7 +42,7 @@ function ignore({ src }) {
*/
export async function normalizeConfig(inConfig) {
let config = {
presets: [webMenu()],
presets: [],
setupUnifiedPlugins: [],
setupDevAndBuildPlugins: [],
setupDevPlugins: [],
@@ -53,7 +50,6 @@ export async function normalizeConfig(inConfig) {
setupEleventyPlugins: [],
setupEleventyComputedConfig: [],
setupCliPlugins: [],
setupMenus: [],
eleventy: () => {},
command: 'help',
watch: true,
@@ -102,7 +98,7 @@ export async function normalizeConfig(inConfig) {
try {
const fileConfig = await readConfig('rocket.config', userConfigFile, path.resolve(__configDir));
if (fileConfig) {
const updatedConfig = {
config = {
...config,
...fileConfig,
build: {
@@ -115,16 +111,12 @@ export async function normalizeConfig(inConfig) {
},
imagePresets: config.imagePresets,
};
if (fileConfig.presets) {
updatedConfig.presets = [...config.presets, ...fileConfig.presets];
}
if (fileConfig.imagePresets && fileConfig.imagePresets.responsive) {
updatedConfig.imagePresets.responsive = {
config.imagePresets.responsive = {
...config.imagePresets.responsive,
...fileConfig.imagePresets.responsive,
};
}
config = updatedConfig;
}
} catch (error) {
console.error('Could not read rocket config file', error);
@@ -173,9 +165,6 @@ export async function normalizeConfig(inConfig) {
if (preset.setupCliPlugins) {
config.setupCliPlugins = [...config.setupCliPlugins, ...preset.setupCliPlugins];
}
if (preset.setupMenus) {
config.setupMenus = [...config.setupMenus, ...preset.setupMenus];
}
if (typeof preset.before11ty === 'function') {
config.__before11tyFunctions.push(preset.before11ty);
@@ -185,7 +174,7 @@ export async function normalizeConfig(inConfig) {
config._presetPaths.push(path.resolve(_inputDirCwdRelative));
/** @type {MetaPlugin[]} */
let pluginsMeta = [{ plugin: RocketStart }, { plugin: RocketBuild }, { plugin: RocketLint }, { plugin: RocketUpgrade}];
let pluginsMeta = [{ plugin: RocketStart }, { plugin: RocketBuild }, { plugin: RocketLint }];
if (Array.isArray(config.setupCliPlugins)) {
for (const setupFn of config.setupCliPlugins) {

View File

@@ -33,6 +33,17 @@ class TitlePlugin {
}
}
class EleventyNavigationPlugin {
static dataName = 'eleventyNavigation';
async execute(data) {
if (data.eleventyNavigation) {
return data.eleventyNavigation;
}
return data.titleMeta?.eleventyNavigation;
}
}
class SectionPlugin {
static dataName = 'section';
@@ -170,50 +181,17 @@ class JoiningBlocksPlugin {
}
}
/**
* Removes the `xx--` prefix that is used for ordering
*
* @returns {string}
*/
class PermalinkPlugin {
static dataName = 'permalink';
execute(data) {
if (data.permalink) {
return data.permalink;
}
let filePath = data.page.filePathStem.replace(/[0-9]+--/g, '');
return filePath.endsWith('index') ? `${filePath}.html` : `${filePath}/index.html`;
}
}
/**
* @returns {Number}
*/
class MenuOrderPlugin {
static dataName = 'menu.order';
execute(data) {
const matches = data.page.fileSlug.match(/([0-9]+)--/);
if (matches) {
return parseInt(matches[1]);
}
return 0;
}
}
function generateEleventyComputed() {
const rocketConfig = getComputedConfig();
let metaPlugins = [
{ plugin: TitleMetaPlugin, options: {} }, // TODO: remove after search & social media are standalone
{ plugin: TitlePlugin, options: {} }, // TODO: remove after search & social media are standalone
{ plugin: SectionPlugin, options: {} }, // TODO: remove this
{ plugin: SocialMediaImagePlugin, options: { rocketConfig } }, // TODO: convert to standalone tool that can work with html
{ plugin: TitleMetaPlugin, options: {} },
{ plugin: TitlePlugin, options: {} },
{ plugin: EleventyNavigationPlugin, options: {} },
{ plugin: SectionPlugin, options: {} },
{ plugin: SocialMediaImagePlugin, options: { rocketConfig } },
{ plugin: JoiningBlocksPlugin, options: rocketConfig },
{ plugin: LayoutPlugin, options: {} },
{ plugin: PermalinkPlugin, options: {} },
{ plugin: MenuOrderPlugin, options: {} },
];
const finalMetaPlugins = executeSetupFunctions(
@@ -238,8 +216,9 @@ function generateEleventyComputed() {
module.exports = {
generateEleventyComputed,
LayoutPlugin,
PermalinkPlugin,
MenuOrderPlugin,
TitleMetaPlugin,
TitlePlugin,
EleventyNavigationPlugin,
SectionPlugin,
SocialMediaImagePlugin,
JoiningBlocksPlugin,

View File

@@ -37,6 +37,14 @@ module.exports = function (eleventyConfig) {
setupUnifiedPlugins: [...defaultSetupUnifiedPlugins, ...config.setupUnifiedPlugins],
},
},
{
plugin: eleventyRocketNav,
options: {},
},
{
plugin: rocketCollections,
options: { _inputDirCwdRelative },
},
];
if (Array.isArray(config.setupEleventyPlugins)) {

View File

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

View File

@@ -2,10 +2,9 @@ import chai from 'chai';
import { RocketCli } from '../src/RocketCli.js';
import path from 'path';
import globby from 'globby';
import fs, { move, remove } from 'fs-extra';
import fs from 'fs-extra';
import prettier from 'prettier';
import { fileURLToPath } from 'url';
import { existsSync } from 'fs';
const { expect } = chai;
@@ -166,37 +165,6 @@ export async function executeBootstrap(pathToDir) {
return { cli };
}
export async function executeUpgrade(pathToConfig) {
const configFile = path.join(fixtureDir, pathToConfig.split('/').join(path.sep));
const cli = new RocketCli({
argv: ['upgrade', '--config-file', configFile],
});
await cli.setup();
// restore from backup if available - in cases the test did stop in the middle
if (cli.config._inputDirCwdRelative) {
const backupDir = path.join(cli.config._inputDirCwdRelative, '..', 'docs_backup');
if (existsSync(backupDir)) {
await remove(cli.config._inputDirCwdRelative);
await move(backupDir, cli.config._inputDirCwdRelative);
}
}
await cli.run();
return {
cli,
fileExists: fileName => {
const outputDir = cli.config._inputDirCwdRelative;
return fs.existsSync(path.join(outputDir, fileName));
},
readFile: async fileName => {
// TODO: use readOutput once it's changed to read full file paths
const filePath = path.join(cli.config._inputDirCwdRelative, fileName);
const text = await fs.promises.readFile(filePath);
return text.toString();
},
};
}
export function trimWhiteSpace(inString) {
return inString
.split('\n')

View File

@@ -19,7 +19,40 @@ describe('RocketCli computedConfig', () => {
}
});
it('will not create a social media image in "start"', async () => {
it('will extract a title from markdown and set first folder as section', async () => {
const { cli, readOutput } = await execute(
'computed-config-fixtures/headlines/rocket.config.js',
{ captureLog: true },
);
cleanupCli = cli;
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 readOutput('sub/index.html');
const [subTitle, subSection] = subHtml.split('\n');
expect(subTitle).to.equal('Root: Sub');
expect(subSection).to.equal('sub');
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 readOutput('sub2/index.html');
const [sub2Title, sub2Section] = sub2Html.split('\n');
expect(sub2Title).to.equal('Root: Sub2');
expect(sub2Section).to.equal('sub2');
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 () => {
const { cli, readOutput } = await execute(
'computed-config-fixtures/social-images-only-build/rocket.config.js',
{

View File

@@ -195,7 +195,9 @@ describe('RocketCli images', () => {
});
expect(indexHtml).to.equal(
[
'<p>one</p>',
'<h2 id="one">',
' <a aria-hidden="true" tabindex="-1" href="#one"><span class="icon icon-link"></span></a>one',
'</h2>',
'<p>',
' <picture>',
' <source',
@@ -219,7 +221,9 @@ describe('RocketCli images', () => {
' />',
' </picture>',
'</p>',
'<p>two</p>',
'<h2 id="two">',
' <a aria-hidden="true" tabindex="-1" href="#two"><span class="icon icon-link"></span></a>two',
'</h2>',
'<p>',
' <picture>',
' <source',

View File

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

View File

@@ -72,7 +72,7 @@ describe('RocketCli preset', () => {
' <div class="content-area">',
' <a class="logo-link" href="/">',
' <img src="/_merged_assets/logo.svg" alt="" />',
' <span>Rocket</span>',
' <span class="sr-only">Rocket</span>',
' </a>',
' </div>',
' </header>',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,11 @@
# @rocket/eleventy-rocket-nav
## 0.3.1
### Patch Changes
- 60310ab: Improve performance by initializing sax-wasm only once even when it is running in parallel
## 0.3.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/eleventy-rocket-nav",
"version": "0.3.0",
"version": "0.3.1",
"publishConfig": {
"access": "public"
},

View File

@@ -97,6 +97,7 @@ function getHeadingsOfHtml(html) {
return { headings, insertPoint };
}
/** @type {boolean | Promise<unknown>} */
let isSetup = false;
/**
@@ -104,9 +105,9 @@ let isSetup = false;
*/
async function addPageAnchors(content) {
if (!isSetup) {
await parser.prepareWasm(saxWasmBuffer);
isSetup = true;
isSetup = parser.prepareWasm(saxWasmBuffer);
}
await isSetup;
const { headings, insertPoint } = getHeadingsOfHtml(content);
const pageAnchorsHtml = [];

View File

@@ -140,7 +140,6 @@ body[layout^='layout-home'] #main-header {
position: relative;
}
#main-header web-menu > nav,
#main-header .content-area {
display: flex;
justify-content: space-between;
@@ -156,10 +155,6 @@ body[layout^='layout-home'] #main-header {
order: 2;
}
#main-header web-menu {
order: 2;
}
#main-header a:hover {
color: var(--primary-color);
}
@@ -214,15 +209,10 @@ body[layout^='layout-home'] #main-header a:hover {
width: 100%;
}
#main-header web-menu > nav > a,
#main-header .content-area > * {
margin-right: 50px;
}
#main-header .content-area web-menu {
margin-right: 0;
}
#main-header .content-area > .social-link {
margin-right: 15px;
}
@@ -273,26 +263,26 @@ body[layout^='layout-home'] #main-header a:hover {
overflow: auto;
}
web-menu[name="index"] .light-dark-switch {
rocket-navigation .light-dark-switch {
margin-bottom: 10px;
}
web-menu[name="index"] .light-dark-switch::part(label) {
rocket-navigation .light-dark-switch::part(label) {
order: 10;
margin-left: 10px;
}
web-menu[name="index"] a {
rocket-navigation a {
text-decoration: none;
color: var(--primary-text-color);
}
web-menu[name="index"] a:hover {
rocket-navigation a:hover {
color: var(--primary-color);
}
/* line on the left to indicate current page */
web-menu[name="index"] > nav > ul > li > ul li.current ul li.anchor.current::before {
rocket-navigation > ul > li > ul li.current ul li.anchor.current::before {
content: '';
height: 1.6em;
width: 3px;
@@ -302,47 +292,58 @@ web-menu[name="index"] > nav > ul > li > ul li.current ul li.anchor.current::bef
margin-top: -2px;
}
web-menu[name="index"] li {
rocket-navigation li {
padding: 7px 0;
}
web-menu[name="index"] > nav > ul > li > ul li.current a:not(.anchor) {
rocket-navigation > ul > li > ul li.current a:not(.anchor) {
font-weight: bold;
}
web-menu[name="index"] > nav > ul > li > ul > li.current > ul > li > a {
rocket-navigation > ul > li > ul > li.current > ul > li > a {
font-weight: normal;
}
web-menu[name="index"] hr {
rocket-navigation hr {
margin: 30px -10px 10px -10px;
}
web-menu[name="index"] > nav > ul > li > span {
/* Hide below 3rd level by default */
rocket-navigation > ul > li > ul > li ul {
display: none;
}
/* Only show below 3rd level if level above is active/current */
li.current > ul,
li.active > ul {
display: block;
}
rocket-navigation > ul > li > a {
color: var(--primary-color);
font-weight: bold;
font-size: 18px;
text-transform: uppercase;
}
web-menu[name="index"] > nav > ul > li > ul a {
rocket-navigation > ul > li > ul a {
font-weight: normal;
}
web-menu[name="index"] {
rocket-navigation {
overflow: auto;
display: block;
margin-top: 40px;
padding: 0 20px;
}
web-menu[name="index"] ul {
rocket-navigation ul {
padding: 7px 0 10px 15px;
margin: 0;
list-style-type: none;
}
web-menu[name="index"] > nav > ul {
rocket-navigation > ul {
padding: 0;
position: relative;
}
@@ -421,7 +422,7 @@ li.current > ul > li.anchor {
display: none;
}
web-menu[name="index"] {
rocket-navigation {
padding: 0 25px 0 0;
}
@@ -432,7 +433,7 @@ li.current > ul > li.anchor {
}
/* for blog detail page */
web-menu[name="index"] h3 {
rocket-navigation h3 {
font-family: var(--heading-font-family, var(--primary-font-family));
font-size: 16px;
margin: 0 0 7px 0;

View File

@@ -1,3 +1,4 @@
import '@rocket/navigation/rocket-navigation.js';
import '@rocket/drawer/rocket-drawer.js';
const drawer = document.querySelector('#sidebar');

View File

@@ -1,2 +1,8 @@
<web-menu name="index"></web-menu>
{% include 'partials/mobile-sidebar-bottom.njk' %}
<rocket-navigation>
{{ collections[section] | rocketNav | rocketNavToHtml({
listItemClass: "menu-item",
activeListItemClass: "current",
activeKey: eleventyNavigation.key
}) | safe }}
{% include 'partials/mobile-sidebar-bottom.njk' %}
</rocket-navigation>

View File

@@ -0,0 +1,8 @@
{% if layout === "home.njk" and rocketLaunch.homeLayout === "background" %}
<a class="logo-link" href="{{ '/' | url }}">
<img src="{{ '/_assets/logo.svg' | asset | url }}" alt="{{ site.logoAlt }}" />
<span class="sr-only">{{ site.name }}</span>
</a>
{% else %}
{% include 'partials/_shared/logoLink.njk' %}
{% endif %}

View File

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

View File

@@ -1 +0,0 @@
<web-menu name="site"></web-menu>

View File

@@ -1,7 +1,6 @@
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="menu:exclude" content="true" />
<title>Page not found</title>
<style>
@import url('https://fonts.googleapis.com/css?family=Dosis:300,400,500');

View File

@@ -4,7 +4,6 @@ import { adjustPluginOptions } from 'plugins-manager';
import { fileURLToPath } from 'url';
import { LayoutPlugin } from '@rocket/cli';
import htmlHeading from 'rehype-autolink-headings';
import { IndexMenu } from '@web/menu';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -55,9 +54,6 @@ export function rocketLaunch() {
setupEleventyComputedConfig: [
adjustPluginOptions(LayoutPlugin, { defaultLayout: 'layout-sidebar' }),
],
setupMenus: [
adjustPluginOptions(IndexMenu, { navWrapper: nav => nav }),
],
adjustImagePresets: imagePresets => ({
...imagePresets,
responsive: {

View File

@@ -108,11 +108,6 @@ describe('RocketLaunch preset', () => {
' <body layout="layout-sidebar">',
' <header id="main-header">',
' <div class="content-area">',
' <a class="logo-link" href="/">',
' <img src="/_merged_assets/logo.svg" alt="Rocket Logo" />',
' <span>Rocket</span>',
' </a>',
'',
' <button id="mobile-menu-trigger" data-action="trigger-mobile-menu">',
' <span class="sr-only">Show Menu</span>',
' <svg',
@@ -129,11 +124,10 @@ describe('RocketLaunch preset', () => {
' </svg>',
' </button>',
'',
' <web-menu name="site">',
' <nav aria-label="site">',
' <a href="/page/" aria-current="page">Page</a>',
' </nav>',
' </web-menu>',
' <a class="logo-link" href="/">',
' <img src="/_merged_assets/logo.svg" alt="Rocket Logo" />',
' <span>Rocket</span>',
' </a>',
'',
' <launch-dark-switch class="light-dark-switch" label="Toggle darkmode"',
' >Toggle darkmode</launch-dark-switch',
@@ -194,18 +188,16 @@ describe('RocketLaunch preset', () => {
' <span>Rocket</span>',
' </a>',
'',
' <web-menu name="index">',
' <ul class="lvl-2"></ul>',
' </web-menu>',
' <div class="sidebar-bottom">',
' <hr />',
' <launch-dark-switch class="light-dark-switch" label="Toggle darkmode"',
' >Toggle darkmode</launch-dark-switch',
' >',
' <rocket-navigation>',
' <div class="sidebar-bottom">',
' <hr />',
' <launch-dark-switch class="light-dark-switch" label="Toggle darkmode"',
' >Toggle darkmode</launch-dark-switch',
' >',
'',
' <a href="https://github.com/modernweb-dev/rocket/issues">Help and Feedback</a>',
' </div>',
' <a href="https://github.com/modernweb-dev/rocket/issues">Help and Feedback</a>',
' </div>',
' </rocket-navigation>',
' </nav>',
' </rocket-drawer>',
'',
@@ -261,7 +253,7 @@ describe('RocketLaunch preset', () => {
);
});
it.skip('offers a layout-home', async () => {
it('offers a layout-home', async () => {
const { cli, readOutput } = await execute('fixtures/layout-home/rocket.config.js', {
captureLog: true,
});

View File

@@ -1,5 +1,23 @@
# Change Log
## 0.9.4
### Patch Changes
- e6c3d27: Support `js client` as an alias to `js script`
## 0.9.3
### Patch Changes
- 62637a8: Replaces `rehype-prism-template` with `rehype-prism` to get a newer version of prism with essential security updates
## 0.9.2
### Patch Changes
- 97cb38c: Add missing slash dependency
## 0.9.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@mdjs/core",
"version": "0.9.1",
"version": "0.9.4",
"publishConfig": {
"access": "public"
},
@@ -52,7 +52,7 @@
"github-markdown-css": "^4.0.0",
"plugins-manager": "^0.3.0",
"rehype-autolink-headings": "^5.0.1",
"rehype-prism-template": "^0.4.1",
"rehype-prism": "^1.0.0",
"rehype-raw": "^5.0.0",
"rehype-slug": "^4.0.1",
"rehype-stringify": "^8.0.0",
@@ -60,6 +60,7 @@
"remark-gfm": "^1.0.0",
"remark-parse": "^9.0.0",
"remark-rehype": "^8.0.0",
"slash": "^3.0.0",
"unified": "^9.2.0",
"unist-util-remove": "^2.0.1",
"unist-util-visit": "^2.0.3"
@@ -67,7 +68,7 @@
"devDependencies": {
"demo-wc-card": "^0.1.0",
"remark-autolink-headings": "^6.0.1",
"remark-html": "^13.0.1",
"remark-html": "^13.0.2",
"remark-slug": "^6.0.0",
"remark-stringify": "^9.0.1"
},

View File

@@ -16,6 +16,9 @@ function mdjsParse() {
if (node.lang === 'js' && node.meta === 'script') {
jsCode += node.value;
}
if (node.lang === 'js' && node.meta === 'client') {
jsCode += node.value;
}
});
// we can only return/modify the tree but jsCode should not be part of the tree
// so we attach it globally to the file.data
@@ -26,7 +29,9 @@ function mdjsParse() {
* @param {Node} node
*/
const removeFunction = node =>
node.type === 'code' && node.lang === 'js' && node.meta === 'script';
node.type === 'code' &&
node.lang === 'js' &&
(node.meta === 'script' || node.meta === 'client');
remove(tree, removeFunction);
return tree;

View File

@@ -12,14 +12,16 @@ const raw = require('rehype-raw');
const htmlStringify = require('rehype-stringify');
const htmlSlug = require('rehype-slug');
const htmlHeading = require('rehype-autolink-headings');
const rehypePrism = require('rehype-prism-template');
// @ts-ignore
const { executeSetupFunctions } = require('plugins-manager');
const loadLanguages = require('prismjs/components/');
const { mdjsParse } = require('./mdjsParse.js');
const { mdjsStoryParse } = require('./mdjsStoryParse.js');
const { mdjsSetupCode } = require('./mdjsSetupCode.js');
let prismLoaded = false;
/** @type {MdjsProcessPlugin[]} */
const defaultMetaPlugins = [
{ plugin: markdown, options: {} },
@@ -30,8 +32,6 @@ const defaultMetaPlugins = [
// @ts-ignore
{ plugin: remark2rehype, options: { allowDangerousHtml: true } },
// @ts-ignore
{ plugin: rehypePrism, options: {} },
// @ts-ignore
{ plugin: raw, options: {} },
// @ts-ignore
{ plugin: htmlSlug, options: {} },
@@ -54,6 +54,12 @@ const defaultMetaPlugins = [
*/
async function mdjsProcess(mdjs, { setupUnifiedPlugins = [] } = {}) {
const parser = unified();
if (!prismLoaded) {
prismLoaded = true;
const rehypePrism = (await import('rehype-prism/lib/src/index.js')).default;
loadLanguages(['md', 'shell', 'yml']);
defaultMetaPlugins.splice(6, 0, { plugin: rehypePrism, options: {} });
}
const metaPlugins = executeSetupFunctions(setupUnifiedPlugins, defaultMetaPlugins);

View File

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

View File

@@ -35,7 +35,7 @@ describe('mdjsProcess', () => {
'',
'',
'',
'<pre class="language-js"><code class="language-js"><span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function">fooPreviewStory</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>',
'<pre class="language-js"><code class="language-js"><span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">fooPreviewStory</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>',
'</code></pre>',
'',
'',

View File

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

View File

@@ -61,7 +61,7 @@ describe('mdjsStoryParse', () => {
'',
].join('\n');
const parser = unified().use(markdown).use(mdjsStoryParse).use(html);
const parser = unified().use(markdown).use(mdjsStoryParse).use(html, { sanitize: false });
const result = await parser.process(input);
expect(result.contents).to.equal(expected);
expect(/** @type {MDJSVFileData} */ (result.data).stories).to.deep.equal([
@@ -110,7 +110,7 @@ describe('mdjsStoryParse', () => {
storyTag: name => `<Story name="${name}"></Story>`,
previewStoryTag: name => `<Preview><Story name="${name}"></Story></Preview>`,
})
.use(html);
.use(html, { sanitize: false });
const result = await parser.process(input);
expect(result.contents).to.equal(expected);
});
@@ -148,7 +148,7 @@ describe('mdjsStoryParse', () => {
'',
].join('\n');
const parser = unified().use(markdown).use(mdjsStoryParse).use(html);
const parser = unified().use(markdown).use(mdjsStoryParse).use(html, { sanitize: false });
const result = await parser.process(input);
expect(result.contents).to.equal(expected);
});
@@ -186,7 +186,7 @@ describe('mdjsStoryParse', () => {
'',
].join('\n');
const parser = unified().use(markdown).use(mdjsStoryParse).use(html);
const parser = unified().use(markdown).use(mdjsStoryParse).use(html, { sanitize: false });
const result = await parser.process(input);
expect(result.contents).to.equal(expected);
});
@@ -242,7 +242,7 @@ describe('mdjsStoryParse', () => {
'',
].join('\n');
const parser = unified().use(markdown).use(mdjsStoryParse).use(html);
const parser = unified().use(markdown).use(mdjsStoryParse).use(html, { sanitize: false });
const result = await parser.process(input);
expect(result.contents).to.equal(expected);
});

View File

@@ -28,12 +28,6 @@ declare module 'rehype-autolink-headings' {
export = unified.Plugin;
}
declare module 'rehype-prism-template' {
import unified from 'unified';
export = unified.Plugin;
}
declare module 'unist-util-remove' {
import unified from 'unified';

View File

@@ -1,5 +1,29 @@
# @mdjs/mdjs-preview
## 0.5.6
### Patch Changes
- e81b77f: Change theme attribute into preview-theme attribute to separate theme styling of the preview section and the full mdjs viewer.
- 456b8e7: Add css variable to style border-color of the mdjs-viewer
## 0.5.5
### Patch Changes
- 445b028: Update to latest lit, @open-wc, @lion packages
## 0.5.4
### Patch Changes
- 15a82c0: Enable including script files into the simulator via `<script src=".." mdjs-use>`
- 15a82c0: Allow only a limited set of characters for simulator includes `[a-zA-Z0-9\/\-_]`.
Notably, there is no:
- `:` to prevent `http://...` includes
- `.` so filenames as `this.is.my.js` are not supported. Also includes will be without file endings which will be added automatically
## 0.5.3
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@mdjs/mdjs-preview",
"version": "0.5.3",
"version": "0.5.6",
"publishConfig": {
"access": "public"
},
@@ -20,8 +20,8 @@
"./define": "./src/define/define.js"
},
"scripts": {
"prepublishOnly": "publish-docs --github-url https://github.com/modernweb-dev/rocket/ --git-root-dir ../../",
"debug": "cd ../../ && npm run debug -- --group mdjs-preview",
"prepublishOnly": "publish-docs --github-url https://github.com/modernweb-dev/rocket/ --git-root-dir ../../",
"test": "npm run test:web",
"test:web": "cd ../../ && npm run test:web -- --group mdjs-preview"
},
@@ -32,9 +32,9 @@
"src"
],
"dependencies": {
"@lion/accordion": "^0.6.1",
"@open-wc/scoped-elements": "^2.0.0-next.3",
"lit": "^2.0.0-rc.2"
"@lion/accordion": "^0.7.2",
"@open-wc/scoped-elements": "^2.0.0",
"lit": "^2.0.0"
},
"types": "dist-types/index.d.ts"
}

View File

@@ -10,6 +10,16 @@ import {
} from './mdjsViewerSharedStates.js';
import { addResizeHandler } from './resizeHandler.js';
/**
* @param {string} input
* @param {'js'|'css'} type
* @returns {string}
*/
function sanitize(input, type) {
const url = new URL(input);
return url.pathname.slice(1, (type.length + 1) * -1);
}
/**
* @typedef {object} StoryOptions
* @property {HTMLElement | null} StoryOptions.shadowRoot
@@ -51,7 +61,7 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
platforms: { type: Array },
size: { type: String },
sizes: { type: Array },
theme: { type: String, reflect: true },
previewTheme: { type: String, reflect: true, attribute: 'preview-theme' },
themes: { type: Array },
language: { type: String },
languages: { type: Array },
@@ -72,7 +82,7 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
this.__supportsClipboard = 'clipboard' in navigator;
this.__copyButtonText = 'Copy Code';
this.theme = 'light';
this.previewTheme = 'light';
/** @type {{ key: string, name: string }[]} */
this.themes = [
// { key: 'light', name: 'Light' },
@@ -273,11 +283,10 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
if (!mdjsSetupScript) {
throw new Error('Could not find a <script type="module" src="..." mdjs-setup></script>');
}
const params = new URLSearchParams();
params.set('story-file', mdjsSetupScript.src);
params.set('story-file', sanitize(mdjsSetupScript.src, 'js'));
params.set('story-key', this.key);
params.set('theme', this.theme);
params.set('theme', this.previewTheme);
params.set('platform', this.platform);
params.set('language', this.language);
params.set('edge-distance', this.edgeDistance.toString());
@@ -287,7 +296,16 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
]);
for (const link of links) {
if (link.href) {
params.append('stylesheets', link.href);
params.append('stylesheets', sanitize(link.href, 'css'));
}
}
const moduleUrls = /** @type {HTMLScriptElement[]} */ ([
...document.querySelectorAll('script[type=module][mdjs-use]'),
]);
for (const moduleUrl of moduleUrls) {
if (moduleUrl.src) {
params.append('moduleUrls', sanitize(moduleUrl.src, 'js'));
}
}
@@ -421,20 +439,20 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
@change=${
/** @param {Event} ev */ ev => {
if (ev.target) {
this.theme = /** @type {HTMLInputElement} */ (ev.target).value;
this.previewTheme = /** @type {HTMLInputElement} */ (ev.target).value;
}
}
}
>
${this.themes.map(
theme => html`
<label class="${this.theme === theme.key ? 'selected' : ''}">
<span>${theme.name}</span>
previewTheme => html`
<label class="${this.previewTheme === previewTheme.key ? 'selected' : ''}">
<span>${previewTheme.name}</span>
<input
type="radio"
name="theme"
value="${theme.key}"
?checked=${this.theme === theme.key}
value="${previewTheme.key}"
?checked=${this.previewTheme === previewTheme.key}
/>
</label>
`,
@@ -668,11 +686,11 @@ export class MdJsPreview extends ScopedElementsMixin(LitElement) {
}
:host(:not([device-mode])) #wrapper {
border: 2px solid #4caf50;
border: 2px solid var(--primary-lines-color, #4caf50);
}
iframe {
border: 2px solid #4caf50;
border: 2px solid var(--primary-lines-color, #4caf50);
background: #fff;
}

View File

@@ -1,7 +1,7 @@
const _sharedStates = {
platform: 'web',
size: 'webSmall',
theme: 'light',
previewTheme: 'light',
language: 'en',
autoHeight: true,
deviceMode: false,

View File

@@ -1,5 +1,11 @@
# @mdjs/mdjs-story
## 0.3.1
### Patch Changes
- 445b028: Update to latest lit, @open-wc, @lion packages
## 0.3.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@mdjs/mdjs-story",
"version": "0.3.0",
"version": "0.3.1",
"publishConfig": {
"access": "public"
},
@@ -31,7 +31,7 @@
"src"
],
"dependencies": {
"lit": "^2.0.0-rc.2"
"lit": "^2.0.0"
},
"types": "dist-types/index.d.ts"
}

View File

@@ -1,5 +1,11 @@
# plugins-manager
## 0.3.1
### Patch Changes
- 7e277cd: Add a "hidden" feature in addPlugin that if you attach a `wrapPlugin` property to the returning function it will call `wrapPlugin` on the plugin before adding it.
## 0.3.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "plugins-manager",
"version": "0.3.0",
"version": "0.3.1",
"publishConfig": {
"access": "public"
},

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
/**
* @template {import('../types/main').Plugin} T
* @param {T} plugin
@@ -12,6 +13,10 @@ export function addPlugin(plugin, options = {}, { how = 'after', location = 'bot
if (plugins === undefined) {
plugins = [];
}
// @ts-ignore
const usePlugin = addPluginFn.wrapPlugin ? addPluginFn.wrapPlugin(plugin) : plugin;
// only add if name is not already in the meta plugin list
if (plugins.findIndex(pluginObj => pluginObj.plugin === plugin) === -1) {
let index = -1;
@@ -40,7 +45,7 @@ export function addPlugin(plugin, options = {}, { how = 'after', location = 'bot
}
plugins.splice(index, 0, {
plugin,
plugin: usePlugin,
options,
});
}

View File

@@ -109,4 +109,18 @@ describe('addPlugin', () => {
});
expect(config.plugins).to.deep.equal(['-- newFirst last Plugin --']);
});
it('[advanced] can add a `wrapPlugin` property to the function itself which will call it on the plugin on init', async () => {
function myWrapper(plugin) {
return () => 'wrapped' + plugin();
}
const config = applyPlugins({
setupPlugins: [addPlugin(insertPlugin)].map(mod => {
mod.wrapPlugin = myWrapper;
return mod;
}),
});
expect(config.plugins).to.deep.equal(['wrapped-- first last Plugin --']);
});
});

View File

@@ -1,5 +1,11 @@
# @rocket/search
## 0.5.1
### Patch Changes
- 445b028: Update to latest lit, @open-wc, @lion packages
## 0.5.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@rocket/search",
"version": "0.5.0",
"version": "0.5.1",
"publishConfig": {
"access": "public"
},
@@ -42,10 +42,10 @@
"search"
],
"dependencies": {
"@lion/combobox": "^0.8.0",
"@lion/core": "^0.18.0",
"@lion/listbox": "^0.10.1",
"@open-wc/scoped-elements": "^2.0.0-next.3",
"@lion/combobox": "^0.8.6",
"@lion/core": "^0.19.0",
"@lion/listbox": "^0.10.7",
"@open-wc/scoped-elements": "^2.0.0",
"chalk": "^4.0.0",
"minisearch": "^3.0.2",
"plugins-manager": "^0.3.0",

View File

@@ -189,7 +189,7 @@ export class RocketSearchCombobox extends LionCombobox {
}
static get properties() {
return /** @type {typeof LionCombobox['properties'] & { showInput: import("lit-element").PropertyDeclaration } } */ ({
return /** @type {typeof LionCombobox['properties'] & { showInput: import("lit").PropertyDeclaration } } */ ({
showInput: { type: Boolean, reflect: true, attribute: 'show-input' },
});
}

View File

@@ -1,277 +0,0 @@
# Web Menu
Gathers information about your static html pages and creates menus for it.
## Features
- Very fast (uses wasm & html streaming for parsing)
- Comes with multiple pre defined menus like site, breadcrumb, tableOfContents, ...
- Menus are accessible and fully style able
- Works with any tool that outputs html
- Typically reduces the tools build time by offloading menu generation
- Flexible rendering system for menus via 4 plain javascript functions (render, list, listItem, link)
- Low dependency count
## Installation
```
npm i -D @web/menu
```
## Usage
```
npx web-menu
```
## Usage as a html user
Write your html as you normally would but don't include any menus.
Where you want to place a menu put `<web-menu type="site"></web-menu>`.
When you run `npx web-menu` it will insert the menu into this tag.
e.g.
You write
```html
<header>
<p>...</p>
<web-menu type="site"></web-menu>
</header>
```
and it will become
```html
<header>
<p>...</p>
<web-menu name="site">
<nav aria-label="site">
<a href="/about/">About</a>
<a href="/components/" aria-current="page">Components</a>
</nav>
</web-menu>
</header>
```
## Configuration file
You can put configurations at
- `config/web-menu.js`
- `config/web-menu.mjs`
- `web-menu.config.js`
- `web-menu.config.mjs`
```js
export default {
docsDir: 'my-menu/',
outputDir:
}
```
<details>
<summary>Types of the config file</summary>
<div>
TODO: inline types
</div>
</details>
## Add your own menu type
```js
import { Menu } from '@web/menu';
class MyMenu extends Menu {
static name = 'my-menu';
async render() {
return '--- My Menu ---';
}
}
export default {
docsDir: 'my-html-site/',
plugins: [addPlugin(MyMenu)],
};
```
## Menu types
1. **site**
- starts at level 1
- flat list of links
- commonly used as a top bar navigation of "sections"
```html
<web-menu name="site">
<nav aria-label="site">
<a href="/about/">About</a>
<a href="/components/" aria-current="page">Components</a>
</nav>
</web-menu>
```
2. **index**
- starts at level 2
- nested ul/li list
- level 2 becomes a not clickable category heading if it has children
- level 3+ becomes a `detail/summary` element needing a click if it has children
- ideally used in combination with `site`
```html
<web-menu name="index">
<nav aria-label="index">
<ul class="lvl-2">
<li class="web-menu-active">
<span>Content</span>
<ul class="lvl-3">
<li class="web-menu-active">
<details open>
<summary>Accordion</summary>
<ul class="lvl-4">
<li class="web-menu-current">
<a href="/components/content/accordion/overview/" aria-current="page"
>Overview</a
>
</li>
<li><a href="/components/content/accordion/api/">API</a></li>
</ul>
</details>
</li>
</ul>
</li>
<li>
<span>Inputs</span>
<ul class="lvl-3">
<li><a href="/components/inputs/input-text/">Input Text</a></li>
<li><a href="/components/inputs/textarea/">Textarea</a></li>
</ul>
</li>
</ul>
</nav>
</web-menu>
```
3. **breadcrumb**
- starts at root and goes the tree up to the current page
- flat ol/li list
```html
<web-menu name="breadcrumb">
<nav aria-label="Breadcrumb">
<ol>
<li class="web-menu-active"><a href="/">Home</a></li>
<li class="web-menu-active"><a href="/components/">Components</a></li>
<li class="web-menu-current">
<a href="/components/button-blue/" aria-current="page">Button Blue</a>
</li>
</ol>
</nav>
</web-menu>
```
4. **articleOverview**
- shows a flat list of pages
- includes multiple meta data like cover image, heading, subHeading, authors, ...
- typically displayed as a grid
```html
<web-menu name="article-overview">
<div>
<article class="post">
<div class="cover">
<a href="/blog/new-year-new-challenge/" tabindex="-1" aria-hidden="true">
<figure>
<img src="..." />
</figure>
</a>
</div>
<a href="/blog/new-year-new-challenge/">
<h2>New year means new challenges</h2>
</a>
<div class="description">
<a href="/blog/new-year-new-challenge/" tabindex="-1">
<p>It is a new year and there are new challenges awaiting.</p>
</a>
</div>
</article>
<article class="post">
<div class="cover">
<a href="/blog/comparing-apple-to-oranges/" tabindex="-1" aria-hidden="true">
<figure>
<img src="..." />
</figure>
</a>
</div>
<a href="/blog/comparing-apple-to-oranges/">
<h2>Comparing apple to oranges</h2>
</a>
<div class="description">
<a href="/blog/comparing-apple-to-oranges/" tabindex="-1">
<p>Say you have an apple and you then find an orange - what would you do?</p>
</a>
</div>
</article>
</div>
</web-menu>
```
5. **tableOfContents**
- lists the headlines of the current page in a hierarchy
- nested ol/li list
```html
<web-menu name="table-of-contents">
<aside>
<h2>Contents</h2>
<nav aria-label="Table of Contents">
<ol class="lvl-2">
<li>
<a href="#every-headline">Every headline</a>
<ol class="lvl-3">
<li><a href="#will-be">will be</a></li>
</ol>
</li>
<li><a href="#to-the">to the</a></li>
<li><a href="#main-level">main level</a></li>
</ol>
</nav>
</aside>
</web-menu>
```
6. **next**
- shows the next page in the tree
- is either the first child or he next sibling
```html
<web-menu name="next">
<a href="/second.html">
<span>next</span>
<span>Second</span>
</a>
</web-menu>
```
7. **previous**
- shows the previous page in the tree
- is either the previous sibling or the parent
```html
<web-menu name="previous">
<a href="/first.html">
<span>previous</span>
<span>First</span>
</a>
</web-menu>
```

View File

@@ -1,24 +0,0 @@
NICE TO HAVE:
- Contribute to tree-model and "modernize it" es6, esm, types https://github.com/joaonuno/tree-model-js/issues/84
- Blog needs support for tags & hero image
- Pagination
## Usage as a @web/dev-server users
Run it in parallel?
## Usage as an eleventy user
Run it in parallel?
## Usage as as ???
- astro
- next.js
- hugo
- gatsby
- jenkyll
- nuxt
- hexo
- docusaurus

View File

@@ -1,6 +0,0 @@
export { buildTree } from './src/buildTree.js';
export { findCurrentNode } from './src/findCurrentNode.js';
export { WebMenuCli } from './src/WebMenuCli.js';
export { webMenu } from './preset/webMenu.js';
export { Menu } from './src/Menu.js';
export { IndexMenu } from './src/menus/IndexMenu.js';

View File

@@ -1,44 +0,0 @@
{
"name": "@web/menu",
"version": "0.0.0",
"publishConfig": {
"access": "public"
},
"description": "A fast low dependency menu renderer for html sites",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/modernweb-dev/rocket.git",
"directory": "packages/web-menu"
},
"author": "Modern Web <hello@modern-web.dev> (https://modern-web.dev/)",
"homepage": "https://rocket.modern-web.dev/docs/tools/web-menu/",
"main": "./index.js",
"bin": {
"web-menu": "src/cli.js"
},
"type": "module",
"exports": {
".": "./index.js"
},
"scripts": {
"test": "mocha test-node/**/*.test.{js,cjs} test-node/*.test.{js,cjs}",
"test:watch": "onchange 'src/**/*.{js,cjs}' 'test-node/**/*.{js,cjs}' -- npm test",
"types:copy": "copyfiles \"./types/**/*.d.ts\" dist-types/"
},
"files": [
"*.js",
"dist",
"dist-types",
"preset",
"src"
],
"dependencies": {
"colorette": "^2.0.16",
"commander": "^8.2.0",
"plugins-manager": "^0.3.0",
"sax-wasm": "^2.0.0",
"tree-model": "^1.0.7"
},
"types": "dist-types/index.d.ts"
}

View File

@@ -1,31 +0,0 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
/** @typedef {import('@rocket/cli').RocketCliOptions} RocketCliOptions */
import { WebMenuCli } from '@web/menu';
export class RocketMenuCliPlugin {
static pluginName = 'RocketMenu';
commands = ['start', 'build', 'lint'];
/**
* @param {object} options
* @param {RocketCliOptions} options.config
* @param {any} options.argv
*/
async setup({ config, argv }) {
this.__argv = argv;
this.webMenu = new WebMenuCli();
this.webMenu.setOptions({
docsDir: config.outputDevDir,
outputDir: config.outputDevDir,
setupPlugins: config.setupMenus,
});
}
async updated() {
if (this.webMenu) {
await this.webMenu.run();
}
}
}

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