Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion docs-app/app/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,27 @@ import config from 'docs-app/config/environment';
import { properLinks } from 'ember-primitives/proper-links';

@properLinks({
ignore: ['/tests'],
ignore: [
// Fallback to Prember
'/1-get-started/intro',
'/2-accessibility/intro',
'/3-components/external-link',
'/3-components/link',
'/3-components/modal',
'/3-components/popover',
'/3-components/portal-targets',
'/3-components/portal',
'/3-components/shadowed',
'/3-components/switch',
'/3-components/toggle',
'/4-helpers/service',
'/5-utils/color-scheme',
'/5-utils/iframe',
'/5-utils/proper-links',
'/6-forms/1-intro',
'/6-forms/2-switch',
'/tests',
],
})
export default class Router extends EmberRouter {
location = config.locationType;
Expand Down
24 changes: 24 additions & 0 deletions docs-app/config/fastboot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* global ReadableStream, WritableStream, TransformStream */
module.exports = function () {
return {
buildSandboxGlobals(defaultGlobals) {
return Object.assign({}, defaultGlobals, {
fetch,
AbortController,
ReadableStream:
typeof ReadableStream !== 'undefined'
? ReadableStream
: require('node:stream/web').ReadableStream,
WritableStream:
typeof WritableStream !== 'undefined'
? WritableStream
: require('node:stream/web').WritableStream,
TransformStream:
typeof TransformStream !== 'undefined'
? TransformStream
: require('node:stream/web').TransformStream,
Headers: typeof Headers !== 'undefined' ? Headers : undefined,
});
},
};
};
60 changes: 52 additions & 8 deletions docs-app/ember-cli-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,29 @@ const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const sortBy = require('lodash.sortby');

module.exports = function (defaults) {
let environment = EmberApp.env();
let isProduction = environment === 'production';

const app = new EmberApp(defaults, {
// Add options here
'ember-cli-babel': {
enableTypeScriptTransform: true,
},
prember: {
enabled: isProduction || process.env.PREMBER === 'true',
urls: async function () {
let data = await urlsForPrerender();

let pages = data.map((markdownUrl) => markdownUrl.replace(/\.md$/, ''));

console.debug('pre-rendered pages', pages);

return pages;
},
},
fastboot: {
hostWhitelist: [/^localhost:\d+/, 'ember-primitives.pages.dev'],
}
});

// Use `app.import` to add additional libraries to the generated
Expand All @@ -32,7 +50,7 @@ module.exports = function (defaults) {
variants = [{ name: 'deployed-dev-build', runtime: 'browser', optimizeForProduction }];
}

return require('@embroider/compat').compatBuild(app, _Webpack, {
const compiledApp = require('@embroider/compat').compatBuild(app, _Webpack, {
extraPublicTrees: [],
staticAddonTrees: true,
staticAddonTestSupportTrees: true,
Expand Down Expand Up @@ -71,6 +89,8 @@ module.exports = function (defaults) {
},
},
});

return require('prember').prerender(app, compiledApp);
};

const { createUnplugin } = require('unplugin');
Expand Down Expand Up @@ -115,19 +135,17 @@ const createManifest = createUnplugin((options) => {
name: 'create-manifest',
async buildStart() {
const path = await import('node:path');
const { globbySync } = await import('globby');

let paths = globbySync(include, {
cwd: path.join(process.cwd(), src),
expandDirectories: true,
let reshaped = await buildManifest({
src,
include,
exclude,
});

paths = paths.filter((path) => !exclude.some((pattern) => path.match(pattern)));

await this.emitFile({
type: 'asset',
fileName: path.join(dest, name),
source: JSON.stringify(reshape(paths)),
source: JSON.stringify(reshaped),
});
},
watchChange(id) {
Expand All @@ -136,6 +154,32 @@ const createManifest = createUnplugin((options) => {
};
});

async function urlsForPrerender() {
let manifest = await buildManifest({
src: 'public/docs',
include: '**/*',
exclude: [],
});

return manifest.list.flat().map((tutorial) => tutorial.path);
}

async function buildManifest(options) {
const { src, include, exclude } = options;

const path = await import('node:path');
const { globbySync } = await import('globby');

let paths = globbySync(include, {
cwd: path.join(process.cwd(), src),
expandDirectories: true,
});

paths = paths.filter((path) => !exclude.some((pattern) => path.match(pattern)));

return reshape(paths);
}

/**
* @param {string[]} paths
*/
Expand Down
4 changes: 4 additions & 0 deletions docs-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"lint:prettier": "pnpm -w exec lint prettier",
"lint:types": "glint",
"start": "concurrently 'ember serve' 'pnpm _syncPnpm --watch' --names 'docs serve,docs sync deps'",
"start:prod": "concurrently 'ember serve --environment=production' 'pnpm _syncPnpm --watch' --names 'serve prod,sync deps'",
"start:prember": "PREMBER=true concurrently 'ember serve --environment=production' 'pnpm _syncPnpm --watch' --names 'serve prod,sync deps'",
"test": "ember test",
"test:ember": "ember test",
"_syncPnpm": "pnpm sync-dependencies-meta-injected"
Expand Down Expand Up @@ -81,6 +83,7 @@
"ember-cli": "~5.2.0",
"ember-cli-app-version": "^6.0.0",
"ember-cli-babel": "^8.0.0",
"ember-cli-fastboot": "^4.1.1",
"ember-cli-htmlbars": "^6.3.0",
"ember-cli-inject-live-reload": "^2.1.0",
"ember-cli-sri": "^2.1.1",
Expand All @@ -103,6 +106,7 @@
"globby": "^13.2.2",
"loader.js": "^4.7.0",
"pnpm-sync-dependencies-meta-injected": "0.0.9",
"prember": "^2.0.0",
"prettier": "^3.0.2",
"prettier-plugin-ember-template-tag": "^1.0.2",
"qunit": "^2.19.3",
Expand Down
49 changes: 42 additions & 7 deletions ember-primitives/src/color-scheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,54 @@ export function sync() {
}

export const prefers = {
dark: () => window.matchMedia('(prefers-color-scheme: dark)').matches,
light: () => window.matchMedia('(prefers-color-scheme: light)').matches,
custom: (name: string) => window.matchMedia(`(prefers-color-scheme: ${name})`).matches,
none: () => window.matchMedia('(prefers-color-scheme: no-preference)').matches,
dark: () => {
// Fastboot has no graceful fallbacks
if (typeof matchMedia === 'undefined') return;

return window.matchMedia('(prefers-color-scheme: dark)').matches;
},
light: () => {
// Fastboot has no graceful fallbacks
if (typeof matchMedia === 'undefined') return;

return window.matchMedia('(prefers-color-scheme: light)').matches;
},
custom: (name: string) => {
// Fastboot has no graceful fallbacks
if (typeof matchMedia === 'undefined') return;

return window.matchMedia(`(prefers-color-scheme: ${name})`).matches;
},
none: () => {
// Fastboot has no graceful fallbacks
if (typeof matchMedia === 'undefined') return;

return window.matchMedia('(prefers-color-scheme: no-preference)').matches;
},
};

const LOCAL_PREF_KEY = 'ember-primitives/color-scheme#local-preference';

export const localPreference = {
isSet: () => Boolean(localPreference.read()),
read: () => localStorage.getItem(LOCAL_PREF_KEY),
update: (value: string) => localStorage.setItem(LOCAL_PREF_KEY, value),
delete: () => localStorage.removeItem(LOCAL_PREF_KEY),
read: () => {
// Fastboot has no graceful fallbacks
if (typeof localStorage === 'undefined') return;

return localStorage.getItem(LOCAL_PREF_KEY);
},
update: (value: string) => {
// Fastboot has no graceful fallbacks
if (typeof localStorage === 'undefined') return;

return localStorage.setItem(LOCAL_PREF_KEY, value);
},
delete: () => {
// Fastboot has no graceful fallbacks
if (typeof localStorage === 'undefined') return;

return localStorage.removeItem(LOCAL_PREF_KEY);
},
};

export function getColorScheme(element?: HTMLElement) {
Expand Down
3 changes: 3 additions & 0 deletions ember-primitives/src/proper-links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ export function properLinks<Instance extends {}, Klass = { new (...args: any[]):
* This function only requires that a framework object with an owner is passed.
*/
export function setup(parent: object, ignore?: string[]) {
// Fastboot has no graceful fallbacks
if (typeof document === 'undefined') return;

const handler = (event: MouseEvent) => {
/**
* event.target may not be an anchor,
Expand Down
Loading