Skip to content

Commit

Permalink
Merge branch 'main' into timerange-oversight
Browse files Browse the repository at this point in the history
  • Loading branch information
kptdobe committed Oct 18, 2024
2 parents ff1486a + 9010bcf commit ec7447b
Show file tree
Hide file tree
Showing 33 changed files with 695 additions and 89,238 deletions.
70 changes: 70 additions & 0 deletions 404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>

<head>
<title>Page not found</title>
<script type="text/javascript">
window.isErrorPage = true;
window.errorCode = '404';
</script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:title" content="Page not found">
<script src="/scripts/scripts.js" type="module" crossorigin="use-credentials"></script>
<script type="module">
window.addEventListener('load', () => {
if (document.referrer) {
const { origin, pathname } = new URL(document.referrer);
if (origin === window.location.origin) {
const backBtn = document.createElement('a');
backBtn.classList.add('button', 'error-button-back');
backBtn.href = pathname;
backBtn.textContent = 'Go back';
backBtn.title = 'Go back';
const btnContainer = document.querySelector('.button-container');
btnContainer.append(backBtn);
}
}
});
</script>
<script type="module">
import { sampleRUM } from '/scripts/lib-franklin.js';
import { applyRedirects } from '/scripts/redirects.js';
await applyRedirects();
sampleRUM('404', { source: document.referrer });
</script>
<link rel="stylesheet" href="/styles/styles.css">
<style>
main.error {
min-height: calc(100vh - var(--nav-height));
display: flex;
align-items: center;
}

main.error .error-number {
width: 100%;
}

main.error .error-number text {
font-family: monospace;
}
</style>
<link rel="stylesheet" href="/styles/lazy-styles.css">
</head>

<body>
<header></header>
<main class="error">
<div class="section">
<svg viewBox="1 0 38 18" class="error-number">
<text x="0" y="17">404</text>
</svg>
<h2 class="error-message">Page Not Found</h2>
<p class="button-container">
<a href="/" class="button secondary error-button-home">Go home</a>
</p>
</div>
</main>
<footer></footer>
</body>

</html>
4 changes: 2 additions & 2 deletions docs/admin-preview.html
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,11 @@
55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864
-231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688,
-104.0616 -231.873,-231.248 z
" fill="currentColor"></path></g></svg></div></div><div class="sc-dKGrn laenHu api-content"><div class="sc-dsLQwm diwyyM"><div class="sc-la-DxNn dSIRVR"><div class="sc-fQpRED htdgPt api-info"><h1 class="sc-iCZwEW sc-gjHHYa gfRsnu edbYXQ">AEM Admin API (Feature Preview)<!-- --> <span>(<!-- -->12.20.2<!-- -->)</span></h1><p>Download OpenAPI specification<!-- -->:<a download="openapi.json" target="_blank" class="sc-kyZTxD cwcfQE">Download</a></p><div class="sc-euGpHm sc-exayXG fwfkcU kqJXdD"><div class="sc-kwhYVV dgGfLY"><div class="sc-fyEUpq kqOgwj"> <!-- --> <span class="sc-ggPNws hrVgqq">License:<!-- --> <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache 2.0</a></span> </div></div></div><div data-role="redoc-summary" html="" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD"></div><div data-role="redoc-description" html="&lt;p&gt;AEM Admin API is used to manage the lifecycle of content and code.&lt;/p&gt;
" fill="currentColor"></path></g></svg></div></div><div class="sc-dKGrn laenHu api-content"><div class="sc-dsLQwm diwyyM"><div class="sc-la-DxNn dSIRVR"><div class="sc-fQpRED htdgPt api-info"><h1 class="sc-iCZwEW sc-gjHHYa gfRsnu edbYXQ">AEM Admin API (Feature Preview)<!-- --> <span>(<!-- -->12.22.0<!-- -->)</span></h1><p>Download OpenAPI specification<!-- -->:<a download="openapi.json" target="_blank" class="sc-kyZTxD cwcfQE">Download</a></p><div class="sc-euGpHm sc-exayXG fwfkcU kqJXdD"><div class="sc-kwhYVV dgGfLY"><div class="sc-fyEUpq kqOgwj"> <!-- --> <span class="sc-ggPNws hrVgqq">License:<!-- --> <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache 2.0</a></span> </div></div></div><div data-role="redoc-summary" html="" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD"></div><div data-role="redoc-description" html="&lt;p&gt;AEM Admin API is used to manage the lifecycle of content and code.&lt;/p&gt;
" class="sc-euGpHm sc-exayXG fwfkcU kqJXdD"><p>AEM Admin API is used to manage the lifecycle of content and code.</p>
</div></div></div></div></div><div class="sc-epzHnm bWkBKa"></div></div></div>
<script>
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.1.0","info":{"version":"12.20.2","title":"AEM Admin API (Feature Preview)","description":"AEM Admin API is used to manage the lifecycle of content and code.","license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}},"servers":[{"url":"https://admin.hlx.page"}],"components":{"securitySchemes":{"AuthCookie":{"type":"apiKey","in":"cookie","name":"auth_token"},"BearerToken":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}}}},"searchIndex":{"store":[],"index":{"version":"2.3.9","fields":["title","description"],"fieldVectors":[],"invertedIndex":[],"pipeline":[]}},"options":{"schemasExpansionLevel":2}};
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.1.0","info":{"version":"12.22.0","title":"AEM Admin API (Feature Preview)","description":"AEM Admin API is used to manage the lifecycle of content and code.","license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0.html"}},"servers":[{"url":"https://admin.hlx.page"}],"components":{"securitySchemes":{"AuthCookie":{"type":"apiKey","in":"cookie","name":"auth_token"},"BearerToken":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}}}},"searchIndex":{"store":[],"index":{"version":"2.3.9","fields":["title","description"],"fieldVectors":[],"invertedIndex":[],"pipeline":[]}},"options":{"schemasExpansionLevel":2}};

var container = document.getElementById('redoc');
Redoc.hydrate(__redoc_state, container);
Expand Down
4 changes: 2 additions & 2 deletions docs/admin.html

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"homepage": "https://github.com/adobe/helix-website#readme",
"devDependencies": {
"@adobe/rum-distiller": "^1.4.1",
"@babel/core": "7.18.0",
"@babel/eslint-parser": "7.17.0",
"@esm-bundle/chai": "4.3.4-fix.0",
Expand Down
69 changes: 69 additions & 0 deletions scripts/redirects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
function globToRegex(glob) {
return new RegExp(`^${glob.replace(/\*/g, '(.*)').replace(/\?/g, '(.)').replace(/\//g, '\\/')}$`);
}

export function activateRedirects(data) {
return data.map((o) => Object.entries(o)
.reduce((acc, [k, v]) => {
if (k.toLowerCase() === 'from') {
acc.from = globToRegex(v);
} else if (k.toLowerCase() === 'to') {
acc.to = (...replacements) => {
replacements.shift();
const result = v.replace(/(\$\d+|\*)/g, (matched) => {
if (matched.startsWith('$')) {
return replacements[matched.slice(1) - 1];
}
if (matched === '*') {
return replacements.shift();
}
return matched;
});
return result;
};
} else if (k.toLowerCase() === 'start') {
acc.start = new Date(
Date.UTC(1899, 11, 30, 0, 0, 0)
+ (v - Math.floor(v)) * 86400000 + Math.floor(v) * 86400000,
);
}
return acc;
}, {}));
}
export async function fetchRedirects(path = '/smart-redirects.json') {
const response = await fetch(path);
const redirects = await response.json();
if (redirects.data) {
return activateRedirects(redirects.data);
}
return [];
}

export async function getRedirect(redirects, path, currentURL) {
const redirect = (await redirects)
.filter((r) => typeof r.start === 'undefined' || r.start.getTime() <= Date.now())
.find((r) => r.from.test(path));
if (redirect) {
const target = redirect.to(path, ...redirect.from.exec(path).slice(1));
const targetURL = new URL(target, currentURL);
// Copy all URL parameters from currentURL to targetURL
currentURL.searchParams.forEach((value, key) => {
targetURL.searchParams.set(key, value);
});

targetURL.searchParams.set('redirect_from', path);
return targetURL.toString();
}
return null;
}

export async function applyRedirects(
redirects = fetchRedirects(),
path = window.location.pathname,
) {
const redirect = await getRedirect(redirects, path, new URL(window.location.href));
if (redirect) {
window.location.replace(redirect);
}
return path;
}
71 changes: 71 additions & 0 deletions tests/scripts/redirects.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { expect } from '@esm-bundle/chai';
import { readFile } from '@web/test-runner-commands';
import { activateRedirects, getRedirect } from '../../scripts/redirects.js';
/* eslint-env mocha */

document.body.innerHTML = await readFile({ path: './dummy.html' });
document.head.innerHTML = await readFile({ path: './head.html' });

describe.only('Redirects', () => {
it('loads redirects', async () => {
const emptyRedirects = [];
const redirects = await activateRedirects(emptyRedirects);
expect(redirects).to.deep.equal(emptyRedirects);
});

it('applies applies a simple redirect', async () => {
const exampleRedirects = [
{
from: '/foo',
to: '/bar',
start: 1,
},
];
const redirects = await activateRedirects(exampleRedirects);
const currentURL = new URL('https://example.com/foo');
const redirect = await getRedirect(redirects, '/foo', currentURL);
expect(redirect).to.equal('https://example.com/bar?redirect_from=%2Ffoo');
});

it('applies applies a redirect with a parameter', async () => {
const exampleRedirects = [
{
from: '/foo/*',
to: '/bar/*',
start: 1,
},
];
const redirects = await activateRedirects(exampleRedirects);
const currentURL = new URL('https://example.com/foo/baz');
const redirect = await getRedirect(redirects, '/foo/baz', currentURL);
expect(redirect).to.equal('https://example.com/bar/baz?redirect_from=%2Ffoo%2Fbaz');
});

it('applies applies a redirect with multiple parameters', async () => {
const exampleRedirects = [
{
from: '/foo/*/*',
to: '/bar/*/baz/*',
start: 1,
},
];
const redirects = await activateRedirects(exampleRedirects);
const currentURL = new URL('https://example.com/foo/fifi/qux');
const redirect = await getRedirect(redirects, '/foo/fifi/qux', currentURL);
expect(redirect).to.equal('https://example.com/bar/fifi/baz/qux?redirect_from=%2Ffoo%2Ffifi%2Fqux');
});

it('applies applies a redirect with multiple parameters and changed order', async () => {
const exampleRedirects = [
{
from: '/foo/*/*',
to: '/bar/$2/baz/$1',
start: 1,
},
];
const redirects = await activateRedirects(exampleRedirects);
const currentURL = new URL('https://example.com/foo/fifi/qux');
const redirect = await getRedirect(redirects, '/foo/fifi/qux', currentURL);
expect(redirect).to.equal('https://example.com/bar/qux/baz/fifi?redirect_from=%2Ffoo%2Ffifi%2Fqux');
});
});
Loading

0 comments on commit ec7447b

Please sign in to comment.