mirror of
https://github.com/modernweb-dev/rocket.git
synced 2026-03-21 08:51:18 +00:00
Compare commits
10 Commits
@rocket/cl
...
@rocket/cl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcf8f4fe83 | ||
|
|
5330740cb3 | ||
|
|
2edd61beaa | ||
|
|
2a5fc08f35 | ||
|
|
43a7ca10c3 | ||
|
|
da39fa72f3 | ||
|
|
a0e8edfbb9 | ||
|
|
50434293bb | ||
|
|
f08f92615b | ||
|
|
1949b1e1cb |
@@ -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
|
||||
|
||||
@@ -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,17 @@
|
||||
# @rocket/cli
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rocket/cli",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.2",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -67,7 +67,7 @@
|
||||
"@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",
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -140,7 +141,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,7 +195,7 @@ 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,
|
||||
|
||||
@@ -19,6 +19,7 @@ export function setFixtureDir(importMetaUrl) {
|
||||
* @property {boolean} stripStartEndWhitespace
|
||||
* @property {boolean} stripScripts
|
||||
* @property {boolean} formatHtml
|
||||
* @property {boolean} replaceImageHashes
|
||||
* @property {start|build} type
|
||||
*/
|
||||
|
||||
@@ -51,6 +52,7 @@ export async function readOutput(
|
||||
stripScripts = false,
|
||||
formatHtml = false,
|
||||
type = 'build',
|
||||
replaceImageHashes = false,
|
||||
} = {},
|
||||
) {
|
||||
if (!cli || !cli.config) {
|
||||
@@ -70,6 +72,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 });
|
||||
}
|
||||
|
||||
@@ -102,6 +102,30 @@ describe('RocketCli e2e', () => {
|
||||
);
|
||||
const assetHtml = await readStartOutput(cli, 'use-assets/index.html');
|
||||
expect(assetHtml).to.equal('<link rel="stylesheet" href="/_merged_assets/some.css">');
|
||||
const imageHtml = await readStartOutput(cli, 'image/index.html', { replaceImageHashes: true });
|
||||
expect(imageHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
' <figure>',
|
||||
' <picture>',
|
||||
'<source type="image/avif" srcset="/images/__HASH__-600.avif 600w, /images/__HASH__-900.avif 900w" sizes="100vw">',
|
||||
'<source type="image/jpeg" srcset="/images/__HASH__-600.jpeg 600w, /images/__HASH__-900.jpeg 900w" sizes="100vw">',
|
||||
' <img',
|
||||
' alt="My Image Alternative Text" rocket-image="responsive"',
|
||||
' src="/images/__HASH__-600.jpeg"',
|
||||
' ',
|
||||
' ',
|
||||
' width="600"',
|
||||
' height="316"',
|
||||
' loading="lazy"',
|
||||
' decoding="async"',
|
||||
' />',
|
||||
' </picture>',
|
||||
' <figcaption>My Image Description</figcaption>',
|
||||
'</figure>',
|
||||
' </p>',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
|
||||
it('can add a pathPrefix that will be used in the build command', async () => {
|
||||
@@ -119,6 +143,26 @@ describe('RocketCli e2e', () => {
|
||||
expect(assetHtml).to.equal(
|
||||
'<html><head><link rel="stylesheet" href="../41297ffa.css">\n\n</head><body>\n\n</body></html>',
|
||||
);
|
||||
let imageHtml = await readBuildOutput(cli, 'image/index.html');
|
||||
imageHtml = imageHtml.replace(/\.\.\/([a-z0-9]+)\./g, '../__HASH__.');
|
||||
expect(imageHtml).to.equal(
|
||||
[
|
||||
'<html><head>',
|
||||
'</head><body><p>',
|
||||
' </p><figure>',
|
||||
' <picture>',
|
||||
'<source type="image/avif" srcset="../__HASH__.avif 600w, ../__HASH__.avif 900w" sizes="100vw">',
|
||||
'<source type="image/jpeg" srcset="../__HASH__.jpeg 600w, ../__HASH__.jpeg 900w" sizes="100vw">',
|
||||
' <img alt="My Image Alternative Text" rocket-image="responsive" src="../__HASH__.jpeg" width="600" height="316" loading="lazy" decoding="async">',
|
||||
' </picture>',
|
||||
' <figcaption>My Image Description</figcaption>',
|
||||
'</figure>',
|
||||
' <p></p>',
|
||||
'',
|
||||
'',
|
||||
'</body></html>',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
|
||||
it('smoke test for link checking', async () => {
|
||||
|
||||
@@ -22,7 +22,10 @@ describe('RocketCli images', () => {
|
||||
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 indexHtml = await readStartOutput(cli, 'index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
@@ -30,18 +33,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"',
|
||||
@@ -57,47 +60,57 @@ describe('RocketCli images', () => {
|
||||
|
||||
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 });
|
||||
const indexHtml = await readStartOutput(cli, 'two-images/index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<h2 id="one">',
|
||||
' <a aria-hidden="true" tabindex="-1" href="#one"><span class="icon icon-link"></span></a>one',
|
||||
'</h2>',
|
||||
'<p>',
|
||||
' <picture>',
|
||||
' <source',
|
||||
' type="image/avif"',
|
||||
' srcset="/images/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/d67643ad-600.jpeg"',
|
||||
' 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/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="two"',
|
||||
' rocket-image="responsive"',
|
||||
' src="/images/d67643ad-600.jpeg"',
|
||||
' src="/images/__HASH__-600.jpeg"',
|
||||
' width="600"',
|
||||
' height="316"',
|
||||
' loading="lazy"',
|
||||
@@ -111,7 +124,10 @@ 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 indexHtml = await readStartOutput(cli, 'index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
@@ -119,18 +135,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"',
|
||||
@@ -146,25 +162,28 @@ 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 indexHtml = await readStartOutput(cli, '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"',
|
||||
@@ -178,15 +197,18 @@ 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 indexHtml = await readStartOutput(cli, 'no-title/index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
' <img',
|
||||
' alt="My Image Alternative Text"',
|
||||
' rocket-image="responsive"',
|
||||
' src="/images/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"',
|
||||
|
||||
@@ -108,15 +108,18 @@ describe('RocketCli preset', () => {
|
||||
it('a preset can provide an adjustImagePresets() function', async () => {
|
||||
cli = await executeStart('preset-fixtures/use-preset/rocket.config.js');
|
||||
|
||||
const indexHtml = await readStartOutput(cli, 'index.html', { formatHtml: true });
|
||||
const indexHtml = await readStartOutput(cli, 'index.html', {
|
||||
formatHtml: true,
|
||||
replaceImageHashes: true,
|
||||
});
|
||||
expect(indexHtml).to.equal(
|
||||
[
|
||||
'<p>',
|
||||
' <img',
|
||||
' alt="My Image Alternative Text"',
|
||||
' rocket-image="responsive"',
|
||||
' src="/images/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"',
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
layout: layout-raw
|
||||
---
|
||||
|
||||

|
||||
@@ -2,4 +2,10 @@
|
||||
layout: layout-raw
|
||||
---
|
||||
|
||||

|
||||
## one
|
||||
|
||||

|
||||
|
||||
## two
|
||||
|
||||

|
||||
|
||||
@@ -25,6 +25,7 @@ const config = {
|
||||
}),
|
||||
],
|
||||
// serviceWorkerName: 'sw.js',
|
||||
// pathPrefix: '/_site/',
|
||||
|
||||
// emptyOutputDir: false,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user