Skip to content

Commit 3046f52

Browse files
committed
fix(tools): property knobs, layouts
1 parent 1863fce commit 3046f52

File tree

8 files changed

+194
-84
lines changed

8 files changed

+194
-84
lines changed

package-lock.json

Lines changed: 4 additions & 44 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/pfe-tools/dev-server/plugins/dev-server-templates.ts

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,50 @@ import type { Context, Next } from 'koa';
55
import { readFile } from 'node:fs/promises';
66
import { dirname, join } from 'node:path';
77
import { fileURLToPath } from 'node:url';
8+
import { glob } from 'glob';
89

910
import nunjucks from 'nunjucks';
1011

1112
import { Manifest } from '../../custom-elements-manifest/lib/Manifest.js';
1213

13-
function isPFEManifest(x: Manifest) {
14-
return x.packageJson?.name === '@patternfly/elements';
14+
const env = nunjucks.configure(join(dirname(fileURLToPath(import.meta.url)), 'templates'));
15+
env.addFilter('log', x => (console.log(x), x)); // eslint-disable-line no-console
16+
// TODO: regexing html is stupid
17+
const MOD_STYLE_RE = /(<script type="module">.*<\/script>)|(<style>.*<\/style>)/g;
18+
env.addFilter('noModulesOrStyles', x => x.replaceAll(MOD_STYLE_RE, ''));
19+
env.addFilter('noElement', (x, tagName) => x.replaceAll(new RegExp(`<${tagName}>.*</${tagName}>`, 'gm'), ''));
20+
env.addFilter('getSourceControlUrl', function(
21+
manifest: Manifest,
22+
sourceControlURLPrefix: string,
23+
cwd: string,
24+
) {
25+
if (!manifest || !sourceControlURLPrefix) {
26+
return '';
27+
} else {
28+
return `${sourceControlURLPrefix.replace('tree/main/', '')}${(
29+
`tree/main${
30+
manifest.path.replace(cwd, '')
31+
.replace('/custom-elements.json', '/')}`
32+
)}`;
33+
}
34+
});
35+
36+
async function getElementsPkgJson(config: PfeDevServerInternalConfig) {
37+
let dir = config.elementsDir;
38+
let pkgPath;
39+
while (dir !== config.rootDir && !pkgPath) {
40+
[pkgPath] = await glob('package.json', { cwd: dir, absolute: true });
41+
if (!pkgPath) {
42+
dir = dirname(dir);
43+
}
44+
}
45+
try {
46+
if (pkgPath) {
47+
return JSON.parse(await readFile(pkgPath, 'utf8'));
48+
}
49+
} catch {
50+
return;
51+
}
1552
}
1653

1754
/**
@@ -21,16 +58,15 @@ function isPFEManifest(x: Manifest) {
2158
async function waitForManifestFileThenReadIt(config: PfeDevServerInternalConfig) {
2259
let count = 0;
2360
let manifests = Manifest.getAll(config.rootDir);
24-
while (count < 1000 && manifests.find(isPFEManifest)?.manifest === null) {
61+
while (count < 1000 && manifests.length < 0) {
2562
await new Promise(r => setTimeout(r, 50));
2663
count++;
2764
manifests = Manifest.getAll(config.rootDir);
2865
}
2966
return manifests;
3067
}
3168

32-
async function getDemos(config: PfeDevServerInternalConfig) {
33-
const manifests = await waitForManifestFileThenReadIt(config);
69+
function getDemos(config: PfeDevServerInternalConfig, manifests: Manifest[]) {
3470
return manifests
3571
.flatMap(manifest =>
3672
manifest
@@ -47,20 +83,31 @@ async function getTemplateContent(demo?: DemoRecord) {
4783
}
4884
}
4985

86+
async function getManifest(
87+
config: PfeDevServerInternalConfig,
88+
manifests: Manifest[],
89+
demo?: DemoRecord,
90+
) {
91+
const elementsPkgJson = await getElementsPkgJson(config);
92+
const manifest =
93+
demo?.manifest ?? manifests.find(x => x.packageJson?.name === elementsPkgJson.name);
94+
return manifest;
95+
}
96+
5097
/**
5198
* Render the demo page whenever there's a trailing slash
5299
* @param config Normalized dev server options
53100
*/
54101
export function pfeDevServerTemplateMiddleware(config: PfeDevServerInternalConfig) {
55-
const env = nunjucks.configure(join(dirname(fileURLToPath(import.meta.url)), 'templates'));
56102
return async function(ctx: Context, next: Next): Promise<void> {
57103
const { method, path } = ctx;
58104
if (config.loadDemo && !(method !== 'HEAD' && method !== 'GET' || path.includes('.'))) {
105+
const manifests = await waitForManifestFileThenReadIt(config);
59106
const url = new URL(ctx.request.url, `http://${ctx.request.headers.host}`);
60-
const demos = await getDemos(config);
107+
const demos = getDemos(config, manifests);
61108
const demo = demos.find(x => x.permalink === url.pathname);
62-
const manifest = demo?.manifest;
63109
const templateContent = await getTemplateContent(demo);
110+
const manifest = await getManifest(config, manifests, demo);
64111
ctx.cwd = process.cwd();
65112
ctx.type = 'html';
66113
ctx.status = 200;

tools/pfe-tools/dev-server/plugins/templates/index.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,15 @@
130130
import '@patternfly/elements/pf-switch/pf-switch.js';
131131
import '@patternfly/elements/pf-text-input/pf-text-input.js';
132132
import '@patternfly/elements/pf-text-area/pf-text-area.js';
133+
// TODO: typescript couldn't tolerate importing this
134+
// but in truth, it belongs in pft-element-knobs.ts
135+
import ZeroMd from 'zero-md';
136+
customElements.define('pft-knobs-markdown', class extends ZeroMd {
137+
async load() {
138+
await super.load()
139+
this.template = ``;
140+
}
141+
});
133142
</script>
134143
<pft-element-knobs tag="{{ demo.tagName }}">
135144
<template>

tools/pfe-tools/elements/lib/knobs.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,29 @@ export interface AttributeKnobInfo<E> extends KnobInfo<E> {
2424
values: string[];
2525
}
2626

27+
export interface PropertyKnobInfo<E> extends KnobInfo<E> {
28+
isBoolean: boolean;
29+
isEnum: boolean;
30+
isNullable: boolean;
31+
isNumber: boolean;
32+
isOptional: boolean;
33+
isSerializable: boolean;
34+
values: string[];
35+
}
36+
2737
export type ContentKnobInfo<E> = KnobInfo<E>;
2838

2939
export type KnobRenderer<T, E extends HTMLElement = HTMLElement> = (
3040
this: PftElementKnobs<E>,
3141
member: T,
3242
info:
33-
T extends Attribute ? AttributeKnobInfo<E>
43+
T extends ClassField ? PropertyKnobInfo<E>
44+
: T extends Attribute ? AttributeKnobInfo<E>
3445
: T extends Slot[] ? ContentKnobInfo<E>
3546
: KnobInfo<E>,
3647
) => unknown;
3748

49+
export type PropertyRenderer<E extends HTMLElement> = KnobRenderer<ClassField, E>;
3850
export type AttributeRenderer<E extends HTMLElement> = KnobRenderer<Attribute, E>;
3951
export type ContentRenderer<E extends HTMLElement> = KnobRenderer<Slot[], E>;
4052

@@ -58,3 +70,11 @@ export const dedent = (str: string): string => {
5870
return match ? stripped.replace(new RegExp(`^${match[0]}`, 'gm'), '') : str;
5971
};
6072

73+
export const isSerializable = (x: unknown): boolean => {
74+
try {
75+
JSON.stringify(x);
76+
return true;
77+
} catch {
78+
return false;
79+
}
80+
};

tools/pfe-tools/elements/pft-element-knobs.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,16 @@ dl#slot-descriptions {
2323
overflow: scroll;
2424
background-color: var(--pf-global--BackgroundColor--200, #f0f0f0);
2525
}
26+
27+
header {
28+
display: flex;
29+
align-items: center;;
30+
gap: 1em;
31+
& pft-knobs-markdown {
32+
display: inline;
33+
& .markdown-body,
34+
& p {
35+
display: contents;
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)