Skip to content

Commit

Permalink
fix: multi-instance problem and styles of live demo feature (#2001)
Browse files Browse the repository at this point in the history
* refactor: improve naming of useLiveDemo api

* refactor: restore live config temporarily

* fix: live demo error styles for compact demo

* fix: wrong npm dependency meta in runtime

* fix: multiple instance problem from demo context
  • Loading branch information
PeachScript committed Jan 8, 2024
1 parent 206b04e commit a80758a
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 37 deletions.
10 changes: 5 additions & 5 deletions src/client/pages/Demo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ import './index.less';
const DemoRenderPage: FC = () => {
const { id } = useParams();
const { component } = useDemo(id!) || {};
const { node: liveDemoNode, setSources } = useLiveDemo(id!);
const { node: liveDemoNode, setSource } = useLiveDemo(id!);
const finalNode = liveDemoNode || (component && createElement(component));

useEffect(() => {
const handler = (
ev: MessageEvent<{
type: string;
value: Parameters<typeof setSources>[0];
value: Parameters<typeof setSource>[0];
}>,
) => {
if (ev.data.type === 'dumi.liveDemo.setSources') {
setSources(ev.data.value);
if (ev.data.type === 'dumi.liveDemo.setSource') {
setSource(ev.data.value);
}
};

window.addEventListener('message', handler);

return () => window.removeEventListener('message', handler);
}, [setSources]);
}, [setSource]);

return finalNode;
};
Expand Down
12 changes: 6 additions & 6 deletions src/client/theme-api/useLiveDemo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ export const useLiveDemo = (id: string) => {
const { context, asset } = useDemo(id)!;
const [demoNode, setDemoNode] = useState<ReactNode>();
const [error, setError] = useState<Error | null>(null);
const setSources = useCallback(
(sources: Record<string, string>) => {
const setSource = useCallback(
(source: Record<string, string>) => {
const entryFileName = Object.keys(asset.dependencies).find(
(k) => asset.dependencies[k].type === 'FILE',
)!;
const entryFileCode = sources[entryFileName];
const entryFileCode = source[entryFileName];
const require = (v: string) => {
if (v in context) return context[v];
if (v in context!) return context![v];
throw new Error(`Cannot find module: ${v}`);
};
const exports: { default?: ComponentType } = {};
Expand Down Expand Up @@ -50,7 +50,7 @@ export const useLiveDemo = (id: string) => {
renderToStaticMarkup(newDemoNode);
console.error = oError;

// set new demo node with passing sources
// set new demo node with passing source
setDemoNode(newDemoNode);
setError(null);
} catch (err: any) {
Expand All @@ -61,5 +61,5 @@ export const useLiveDemo = (id: string) => {
[context],
);

return { node: demoNode, error, setSources };
return { node: demoNode, error, setSource };
};
20 changes: 16 additions & 4 deletions src/client/theme-default/builtins/Previewer/index.less
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
@import (reference) '../../styles/variables.less';

.@{prefix}-previewer {
@error-bar-height: 30px;

margin: 24px 0 32px;
border: 1px solid @c-border-light;
border-radius: 4px;
Expand Down Expand Up @@ -76,16 +78,26 @@
&[data-compact] {
padding: 0;
}

// error status
&[data-error][data-compact] {
min-height: @error-bar-height;

+ .@{prefix}-previewer-demo-error {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
}
}

&-demo-error {
@height: 30px;
@color: darken(desaturate(@c-error, 20%), 1%);

margin-top: -@height;
height: @height;
position: relative;
margin-top: -@error-bar-height;
height: @error-bar-height;
padding: 0 24px;
line-height: @height;
line-height: @error-bar-height;
color: @color;
font-size: 13px;
white-space: nowrap;
Expand Down
11 changes: 6 additions & 5 deletions src/client/theme-default/builtins/Previewer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const Previewer: FC<IPreviewerProps> = (props) => {
const {
node: liveDemoNode,
error: liveDemoError,
setSources: setLiveDemoSources,
setSource: setLiveDemoSource,
} = useLiveDemo(props.asset.id);
const [editorError, setEditorError] = useState<Error | null>(null);
const combineError = liveDemoError || editorError;
Expand All @@ -31,6 +31,7 @@ const Previewer: FC<IPreviewerProps> = (props) => {
data-compact={props.compact || undefined}
data-transform={props.transform || undefined}
data-iframe={props.iframe || undefined}
data-error={Boolean(combineError) || undefined}
ref={demoContainer}
>
{props.iframe ? (
Expand Down Expand Up @@ -71,19 +72,19 @@ const Previewer: FC<IPreviewerProps> = (props) => {
)}
<PreviewerActions
{...props}
onSourcesTranspile={({ err, sources }) => {
onSourceTranspile={({ err, source }) => {
if (err) {
setEditorError(err);
} else {
setEditorError(null);
setLiveDemoSources(sources);
setLiveDemoSource(source);

if (props.iframe) {
demoContainer
.current!.querySelector('iframe')!
.contentWindow!.postMessage({
type: 'dumi.liveDemo.setSources',
value: sources,
type: 'dumi.liveDemo.setSource',
value: source,
});
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/client/theme-default/slots/PreviewerActions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ export interface IPreviewerActionsProps extends IPreviewerProps {
extra?: ReactNode;
forceShowCode?: boolean;
demoContainer: HTMLDivElement | HTMLIFrameElement;
onSourcesTranspile?: (
onSourceTranspile?: (
args:
| { err: Error; sources?: null }
| { err?: null; sources: Record<string, string> },
| { err: Error; source?: null }
| { err?: null; source: Record<string, string> },
) => void;
}

Expand Down Expand Up @@ -200,10 +200,10 @@ const PreviewerActions: FC<IPreviewerActionsProps> = (props) => {
initialValue={files[i][1].value.trim()}
onTranspile={({ err, code }) => {
if (err) {
props.onSourcesTranspile?.({ err });
props.onSourceTranspile?.({ err });
} else {
props.onSourcesTranspile?.({
sources: { [files[i][0]]: code },
props.onSourceTranspile?.({
source: { [files[i][0]]: code },
});
}
}}
Expand Down
2 changes: 2 additions & 0 deletions src/features/configPlugins/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,7 @@ export function getSchemas(): Record<string, (Joi: JoiRoot) => any> {
extraRehypePlugins: getUnifiedPluginSchema,
themeConfig: (Joi) => Joi.object().optional(),
logo: (Joi) => Joi.string(),
// FIXME: remove before 2.3.0
live: (Joi) => Joi.bool().optional(),
};
}
7 changes: 7 additions & 0 deletions src/features/derivative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ export default (api: IApi) => {
);
}
} catch {}

// FIXME: remove before 2.3.0
if ('live' in api.config) {
logger.warn(
'`live` config is deprecated and live demo is always enabled now, please remove it.',
);
}
});

// skip mfsu for client api, to avoid circular resolve in mfsu mode
Expand Down
19 changes: 10 additions & 9 deletions src/loaders/markdown/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,15 @@ export const demos = {

// use raw-loader to load all source files
Object.keys(this.resolveMap).forEach((file: string) => {
// handle un-existed source file, e.g. custom tech-stack return custom dependencies
if (!asset.dependencies[file]) return;

// to avoid modify original asset object
asset = lodash.cloneDeep(asset);
asset.dependencies[
file
].value = `{{{require('-!${resolveMap[file]}?dumi-raw').default}}}`;
// skip un-existed source file, e.g. custom tech-stack return custom dependencies
// skip non-file asset because resolveMap will contains all dependencies since 2.3.0
if (asset.dependencies[file]?.type === 'FILE') {
// to avoid modify original asset object
asset = lodash.cloneDeep(asset);
asset.dependencies[
file
].value = `{{{require('-!${resolveMap[file]}?dumi-raw').default}}}`;
}
});

return JSON.stringify(asset, null, 2).replace(/"{{{|}}}"/g, '');
Expand Down Expand Up @@ -304,7 +305,7 @@ export default function mdLoader(this: any, content: string) {
getDemoSourceFiles(ret.meta.demos),
);

// re-generate cache key with latest embeds & sources data
// re-generate cache key with latest embeds & source data
const finalCacheKey = [
baseCacheKey,
getDepsCacheKey(depsMapping[this.resourcePath]),
Expand Down
1 change: 1 addition & 0 deletions src/loaders/markdown/transformer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export default async (raw: string, opts: IMdTransformerOptions) => {
'rehype-remove-comments'
);
const resolver = enhancedResolve.create.sync({
mainFields: ['browser', 'module', 'main'],
extensions: ['.js', '.jsx', '.ts', '.tsx'],
alias: opts.alias,
});
Expand Down
4 changes: 2 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ export abstract class IDumiTechStack {
| Promise<IDumiDemoProps['previewerProps']>
| IDumiDemoProps['previewerProps'];
/**
* generator for return file path of demo sources
* generator for return file path of demo source
*/
abstract generateSources?(
sources: IParsedBlockAsset['resolveMap'],
source: IParsedBlockAsset['resolveMap'],
opts: Parameters<NonNullable<IDumiTechStack['generateMetadata']>>[1],
): Promise<IParsedBlockAsset['resolveMap']> | IParsedBlockAsset['resolveMap'];
}
Expand Down

0 comments on commit a80758a

Please sign in to comment.