feat: events (#717)

This commit is contained in:
Daniel Lautzenheiser 2023-04-19 23:49:53 -04:00 committed by GitHub
parent 455bcdc0f2
commit 79877fcd1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 72 additions and 56 deletions

View File

@ -49,7 +49,7 @@ function getConfigUrl() {
}; };
const configLinkEl = document.querySelector<HTMLLinkElement>('link[rel="cms-config-url"]'); const configLinkEl = document.querySelector<HTMLLinkElement>('link[rel="cms-config-url"]');
if (configLinkEl && validTypes[configLinkEl.type] && configLinkEl.href) { if (configLinkEl && validTypes[configLinkEl.type] && configLinkEl.href) {
console.info(`Using config file path: "${configLinkEl.href}"`); console.info(`[StaticCMS] Using config file path: "${configLinkEl.href}"`);
return configLinkEl.href; return configLinkEl.href;
} }
return 'config.yml'; return 'config.yml';
@ -294,7 +294,7 @@ async function getConfigYaml(file: string): Promise<Config> {
const contentType = response.headers.get('Content-Type') ?? 'Not-Found'; const contentType = response.headers.get('Content-Type') ?? 'Not-Found';
const isYaml = contentType.indexOf('yaml') !== -1; const isYaml = contentType.indexOf('yaml') !== -1;
if (!isYaml) { if (!isYaml) {
console.info(`Response for ${file} was not yaml. (Content-Type: ${contentType})`); console.info(`[StaticCMS] Response for ${file} was not yaml. (Content-Type: ${contentType})`);
} }
return parseConfig(await response.text()); return parseConfig(await response.text());
} }
@ -338,7 +338,7 @@ export async function detectProxyServer(localBackend?: boolean | LocalBackend) {
: localBackend.url || defaultUrl.replace('localhost', location.hostname); : localBackend.url || defaultUrl.replace('localhost', location.hostname);
try { try {
console.info(`Looking for Static CMS Proxy Server at '${proxyUrl}'`); console.info(`[StaticCMS] Looking for Static CMS Proxy Server at '${proxyUrl}'`);
const res = await fetch(`${proxyUrl}`, { const res = await fetch(`${proxyUrl}`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
@ -349,14 +349,16 @@ export async function detectProxyServer(localBackend?: boolean | LocalBackend) {
type?: string; type?: string;
}; };
if (typeof repo === 'string' && typeof type === 'string') { if (typeof repo === 'string' && typeof type === 'string') {
console.info(`Detected Static CMS Proxy Server at '${proxyUrl}' with repo: '${repo}'`); console.info(
`[StaticCMS] Detected Static CMS Proxy Server at '${proxyUrl}' with repo: '${repo}'`,
);
return { proxyUrl, type }; return { proxyUrl, type };
} else { } else {
console.info(`Static CMS Proxy Server not detected at '${proxyUrl}'`); console.info(`[StaticCMS] Static CMS Proxy Server not detected at '${proxyUrl}'`);
return {}; return {};
} }
} catch { } catch {
console.info(`Static CMS Proxy Server not detected at '${proxyUrl}'`); console.info(`[StaticCMS] Static CMS Proxy Server not detected at '${proxyUrl}'`);
return {}; return {};
} }
} }

View File

@ -165,7 +165,7 @@ export function loadMedia(
.catch((error: { status?: number }) => { .catch((error: { status?: number }) => {
console.error(error); console.error(error);
if (error.status === 404) { if (error.status === 404) {
console.info('This 404 was expected and handled appropriately.'); console.info('[StaticCMS] This 404 was expected and handled appropriately.');
dispatch(mediaLoaded([])); dispatch(mediaLoaded([]));
} else { } else {
dispatch(mediaLoadFailed()); dispatch(mediaLoadFailed());

View File

@ -29,7 +29,7 @@ export async function waitUntilWithTimeout<T>(
if (waitDone) { if (waitDone) {
resolve(null); resolve(null);
} else { } else {
console.warn('Wait Action timed out'); console.warn('[StaticCMS] Wait Action timed out');
resolve(null); resolve(null);
} }
}, timeout); }, timeout);

View File

@ -676,7 +676,7 @@ export class Backend<EF extends BaseField = UnknownField, BC extends BackendClas
const result = await localForage.setItem(getEntryBackupKey(), raw); const result = await localForage.setItem(getEntryBackupKey(), raw);
return result; return result;
} catch (e) { } catch (e) {
console.warn('persistLocalDraftBackup', e); console.warn('[StaticCMS] persistLocalDraftBackup', e);
} finally { } finally {
this.backupSync.release(); this.backupSync.release();
} }
@ -691,7 +691,7 @@ export class Backend<EF extends BaseField = UnknownField, BC extends BackendClas
const result = await this.deleteAnonymousBackup(); const result = await this.deleteAnonymousBackup();
return result; return result;
} catch (e) { } catch (e) {
console.warn('deleteLocalDraftBackup', e); console.warn('[StaticCMS] deleteLocalDraftBackup', e);
} finally { } finally {
this.backupSync.release(); this.backupSync.release();
} }

View File

@ -83,7 +83,7 @@ export const API_NAME = 'Bitbucket';
function replace404WithEmptyResponse(err: FetchError) { function replace404WithEmptyResponse(err: FetchError) {
if (err && err.status === 404) { if (err && err.status === 404) {
console.info('This 404 was expected and handled appropriately.'); console.info('[StaticCMS] This 404 was expected and handled appropriately.');
return { size: 0, values: [] as BitBucketFile[] } as BitBucketSrcResult; return { size: 0, values: [] as BitBucketFile[] } as BitBucketSrcResult;
} else { } else {
return Promise.reject(err); return Promise.reject(err);
@ -235,7 +235,7 @@ export default class API {
url: `${this.repoURL}/commits`, url: `${this.repoURL}/commits`,
params: { include: branch, pagelen: '100' }, params: { include: branch, pagelen: '100' },
}).catch(e => { }).catch(e => {
console.info(`Failed getting commits for branch '${branch}'`, e); console.info(`[StaticCMS] Failed getting commits for branch '${branch}'`, e);
return []; return [];
}); });

View File

@ -126,7 +126,7 @@ export default class BitbucketBackend implements BackendClass {
); );
}) })
.catch(e => { .catch(e => {
console.warn('Failed getting BitBucket status', e); console.warn('[StaticCMS] Failed getting BitBucket status', e);
return true; return true;
}); });
@ -138,7 +138,7 @@ export default class BitbucketBackend implements BackendClass {
?.user() ?.user()
.then(user => !!user) .then(user => !!user)
.catch(e => { .catch(e => {
console.warn('Failed getting Bitbucket user', e); console.warn('[StaticCMS] Failed getting Bitbucket user', e);
return false; return false;
})) || false; })) || false;
} }
@ -373,7 +373,7 @@ export default class BitbucketBackend implements BackendClass {
.then(attributes => getLargeMediaPatternsFromGitAttributesFile(attributes as string)) .then(attributes => getLargeMediaPatternsFromGitAttributesFile(attributes as string))
.catch((err: FetchError) => { .catch((err: FetchError) => {
if (err.status === 404) { if (err.status === 404) {
console.info('This 404 was expected and handled appropriately.'); console.info('[StaticCMS] This 404 was expected and handled appropriately.');
} else { } else {
console.error(err); console.error(err);
} }

View File

@ -54,7 +54,7 @@ const GitGatewayAuthenticationPage = ({ onLogin, t }: GitGatewayAuthenticationPa
} }
if (window.netlifyIdentity) { if (window.netlifyIdentity) {
console.info('Manually initializing identity widget'); console.info('[StaticCMS] Manually initializing identity widget');
initialized = true; initialized = true;
window.netlifyIdentity.init(); window.netlifyIdentity.init();
clearInterval(interval); clearInterval(interval);

View File

@ -175,7 +175,7 @@ export default class GitGateway implements BackendClass {
.every((statusComponent: GitGatewayStatus) => statusComponent.status === 'operational'); .every((statusComponent: GitGatewayStatus) => statusComponent.status === 'operational');
}) })
.catch(e => { .catch(e => {
console.warn('Failed getting Git Gateway status', e); console.warn('[StaticCMS] Failed getting Git Gateway status', e);
return true; return true;
}); });
@ -186,7 +186,7 @@ export default class GitGateway implements BackendClass {
(await this.tokenPromise?.() (await this.tokenPromise?.()
.then(token => !!token) .then(token => !!token)
.catch(e => { .catch(e => {
console.warn('Failed getting Identity token', e); console.warn('[StaticCMS] Failed getting Identity token', e);
return false; return false;
})) || false; })) || false;
} }
@ -415,7 +415,7 @@ export default class GitGateway implements BackendClass {
.then((patterns: string[]) => ({ err: null, patterns })) .then((patterns: string[]) => ({ err: null, patterns }))
.catch((err: Error) => { .catch((err: Error) => {
if (err.message.includes('404')) { if (err.message.includes('404')) {
console.info('This 404 was expected and handled appropriately.'); console.info('[StaticCMS] This 404 was expected and handled appropriately.');
return { err: null, patterns: [] as string[] }; return { err: null, patterns: [] as string[] };
} else { } else {
return { err, patterns: [] as string[] }; return { err, patterns: [] as string[] };
@ -461,7 +461,7 @@ export default class GitGateway implements BackendClass {
const entry = items[0]; const entry = items[0];
const pointerFile = parsePointerFile(entry.data); const pointerFile = parsePointerFile(entry.data);
if (!pointerFile.sha) { if (!pointerFile.sha) {
console.warn(`Failed parsing pointer file ${path}`); console.warn(`[StaticCMS] Failed parsing pointer file ${path}`);
return { url: path, blob: new Blob() }; return { url: path, blob: new Blob() };
} }

View File

@ -354,7 +354,7 @@ export default class API {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) { } catch (err: any) {
if (err && err.status === 404) { if (err && err.status === 404) {
console.info('This 404 was expected and handled appropriately.'); console.info('[StaticCMS] This 404 was expected and handled appropriately.');
return []; return [];
} else { } else {
throw err; throw err;

View File

@ -93,7 +93,7 @@ export default class Gitea implements BackendClass {
?.user() ?.user()
.then(user => !!user) .then(user => !!user)
.catch(e => { .catch(e => {
console.warn('Failed getting Gitea user', e); console.warn('[StaticCMS] Failed getting Gitea user', e);
return false; return false;
})) || false; })) || false;

View File

@ -369,7 +369,7 @@ export default class API {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) { } catch (err: any) {
if (err && err.status === 404) { if (err && err.status === 404) {
console.info('This 404 was expected and handled appropriately.'); console.info('[StaticCMS] This 404 was expected and handled appropriately.');
return []; return [];
} else { } else {
throw err; throw err;

View File

@ -109,7 +109,7 @@ export default class GitHub implements BackendClass {
); );
}) })
.catch(e => { .catch(e => {
console.warn('Failed getting GitHub status', e); console.warn('[StaticCMS] Failed getting GitHub status', e);
return true; return true;
}); });
@ -121,7 +121,7 @@ export default class GitHub implements BackendClass {
?.getUser() ?.getUser()
.then(user => !!user) .then(user => !!user)
.catch(e => { .catch(e => {
console.warn('Failed getting GitHub user', e); console.warn('[StaticCMS] Failed getting GitHub user', e);
return false; return false;
})) || false; })) || false;
} }

View File

@ -86,7 +86,7 @@ export default class GitLab implements BackendClass {
?.user() ?.user()
.then(user => !!user) .then(user => !!user)
.catch(e => { .catch(e => {
console.warn('Failed getting GitLab user', e); console.warn('[StaticCMS] Failed getting GitLab user', e);
return false; return false;
})) || false; })) || false;

View File

@ -40,6 +40,7 @@ const ROOT_ID = 'nc-root';
// @ts-ignore // @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars, import/order // eslint-disable-next-line @typescript-eslint/no-unused-vars, import/order
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.usingClientEntryPoint = true; ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.usingClientEntryPoint = true;
@ -79,7 +80,7 @@ function bootstrap<F extends BaseField = UnknownField>(opts?: {
* Log the version number. * Log the version number.
*/ */
if (typeof STATIC_CMS_CORE_VERSION === 'string') { if (typeof STATIC_CMS_CORE_VERSION === 'string') {
console.info(`static-cms-core ${STATIC_CMS_CORE_VERSION}`); console.info(`[StaticCMS] Using @staticcms/core ${STATIC_CMS_CORE_VERSION}`);
} }
/** /**

View File

@ -18,6 +18,7 @@ import { loginUser as loginUserAction } from '@staticcms/core/actions/auth';
import { discardDraft } from '@staticcms/core/actions/entries'; import { discardDraft } from '@staticcms/core/actions/entries';
import { currentBackend } from '@staticcms/core/backend'; import { currentBackend } from '@staticcms/core/backend';
import { changeTheme } from '../actions/globalUI'; import { changeTheme } from '../actions/globalUI';
import { invokeEvent } from '../lib/registry';
import { getDefaultPath } from '../lib/util/collection.util'; import { getDefaultPath } from '../lib/util/collection.util';
import { selectTheme } from '../reducers/selectors/globalUI'; import { selectTheme } from '../reducers/selectors/globalUI';
import { useAppDispatch, useAppSelector } from '../store/hooks'; import { useAppDispatch, useAppSelector } from '../store/hooks';
@ -229,6 +230,12 @@ const App = ({
); );
}, [authenticationPage, collections, defaultPath, isFetching, user]); }, [authenticationPage, collections, defaultPath, isFetching, user]);
useEffect(() => {
setTimeout(() => {
invokeEvent({ name: 'mounted' });
});
}, []);
if (!config.config) { if (!config.config) {
return configError(t('app.app.configNotFound')); return configError(t('app.app.configNotFound'));
} }

View File

@ -62,7 +62,7 @@ function buildIssueUrl(title: string, config?: Config) {
return `${ISSUE_URL}${params.toString()}`; return `${ISSUE_URL}${params.toString()}`;
} catch (e) { } catch (e) {
console.info(e); console.error(e);
return `${ISSUE_URL}template=bug_report.md`; return `${ISSUE_URL}template=bug_report.md`;
} }
} }
@ -72,7 +72,7 @@ interface RecoveredEntryProps {
} }
const RecoveredEntry = ({ entry, t }: TranslatedProps<RecoveredEntryProps>) => { const RecoveredEntry = ({ entry, t }: TranslatedProps<RecoveredEntryProps>) => {
console.info(entry); console.info('[StaticCMS] Recovered entry', entry);
return ( return (
<> <>
<hr /> <hr />
@ -134,7 +134,7 @@ class ErrorBoundary extends Component<TranslatedProps<ErrorBoundaryProps>, Error
if (this.props.showBackup) { if (this.props.showBackup) {
const backup = await localForage.getItem<string>('backup'); const backup = await localForage.getItem<string>('backup');
if (backup) { if (backup) {
console.info(backup); console.info('[StaticCMS] Recovered backup', backup);
this.setState({ backup }); this.setState({ backup });
} }
} }

View File

@ -67,7 +67,7 @@ function inferFrontmatterFormat(str: string) {
case '{': case '{':
return getFormatOpts(Languages.JSON); return getFormatOpts(Languages.JSON);
default: default:
console.warn('Unrecognized front-matter format.'); console.warn('[StaticCMS] Unrecognized front-matter format.');
} }
} }

View File

@ -821,7 +821,7 @@ export interface EventData {
export type EventListenerOptions = Record<string, unknown>; export type EventListenerOptions = Record<string, unknown>;
export type EventListenerHandler = ( export type EventListenerHandler = (
data: EventData, data: EventData | undefined,
options: EventListenerOptions, options: EventListenerOptions,
) => Promise<EntryData | undefined | null | void>; ) => Promise<EntryData | undefined | null | void>;

View File

@ -54,7 +54,9 @@ export function commitMessageFormatter<EF extends BaseField>(
case 'author-name': case 'author-name':
return authorName || ''; return authorName || '';
default: default:
console.warn(`Ignoring unknown variable “${variable}” in commit message template.`); console.warn(
`[StaticCMS] Ignoring unknown variable “${variable}” in commit message template.`,
);
return ''; return '';
} }
}); });

View File

@ -246,7 +246,7 @@ function mergeValues<EF extends BaseField>(
let defaultEntry = values.find(e => e.locale === defaultLocale); let defaultEntry = values.find(e => e.locale === defaultLocale);
if (!defaultEntry) { if (!defaultEntry) {
defaultEntry = values[0]; defaultEntry = values[0];
console.warn(`Could not locale entry for default locale '${defaultLocale}'`); console.warn(`[StaticCMS] Could not locale entry for default locale '${defaultLocale}'`);
} }
const i18n = values const i18n = values
.filter(e => e.locale !== defaultEntry!.locale) .filter(e => e.locale !== defaultEntry!.locale)

View File

@ -26,7 +26,7 @@ import type {
WidgetValueSerializer, WidgetValueSerializer,
} from '../interface'; } from '../interface';
export const allowedEvents = ['preSave', 'postSave'] as const; export const allowedEvents = ['mounted', 'preSave', 'postSave'] as const;
export type AllowedEvent = (typeof allowedEvents)[number]; export type AllowedEvent = (typeof allowedEvents)[number];
const eventHandlers = allowedEvents.reduce((acc, e) => { const eventHandlers = allowedEvents.reduce((acc, e) => {
@ -219,7 +219,7 @@ export function registerWidget<T = unknown, F extends BaseField = UnknownField>(
} = nameOrWidgetOrWidgets; } = nameOrWidgetOrWidgets;
if (registry.widgets[widgetName]) { if (registry.widgets[widgetName]) {
console.warn(oneLine` console.warn(oneLine`
Multiple widgets registered with name "${widgetName}". Only the last widget registered with [StaticCMS] Multiple widgets registered with name "${widgetName}". Only the last widget registered with
this name will be used. this name will be used.
`); `);
} }
@ -323,22 +323,24 @@ export function registerEventListener(
registry.eventHandlers[name].push({ handler, options }); registry.eventHandlers[name].push({ handler, options });
} }
export async function invokeEvent({ name, data }: { name: AllowedEvent; data: EventData }) { export async function invokeEvent({ name, data }: { name: AllowedEvent; data?: EventData }) {
validateEventName(name); validateEventName(name);
const handlers = registry.eventHandlers[name]; const handlers = registry.eventHandlers[name];
let _data = { ...data }; console.info(`[StaticCMS] Firing event ${name}`, data);
let _data = data ? { ...data } : undefined;
for (const { handler, options } of handlers) { for (const { handler, options } of handlers) {
const result = await handler(_data, options); const result = await handler(_data, options);
if (result !== undefined) { if (_data !== undefined && result !== undefined) {
const entry = { const entry = {
..._data.entry, ..._data.entry,
data: result, data: result,
} as Entry; } as Entry;
_data = { ...data, entry }; _data = { ..._data, entry };
} }
} }
return _data.entry.data; return _data?.entry.data;
} }
export function removeEventListener({ name, handler }: EventListener) { export function removeEventListener({ name, handler }: EventListener) {

View File

@ -83,7 +83,7 @@ export async function requestWithBackoff(
if (!api.rateLimiter) { if (!api.rateLimiter) {
const timeout = error.resetSeconds || attempt * attempt; const timeout = error.resetSeconds || attempt * attempt;
console.info( console.info(
`Pausing requests for ${timeout} ${ `[StaticCMS] Pausing requests for ${timeout} ${
attempt === 1 ? 'second' : 'seconds' attempt === 1 ? 'second' : 'seconds'
} due to fetch failures:`, } due to fetch failures:`,
error.message, error.message,
@ -93,7 +93,7 @@ export async function requestWithBackoff(
setTimeout(() => { setTimeout(() => {
api.rateLimiter?.release(); api.rateLimiter?.release();
api.rateLimiter = undefined; api.rateLimiter = undefined;
console.info(`Done pausing requests`); console.info('[StaticCMS] Done pausing requests');
}, 1000 * timeout); }, 1000 * timeout);
} }
return requestWithBackoff(api, req, attempt + 1); return requestWithBackoff(api, req, attempt + 1);

View File

@ -33,7 +33,7 @@ export function asyncLock(): AsyncLock {
if (e instanceof Error && e.message !== 'leave called too many times.') { if (e instanceof Error && e.message !== 'leave called too many times.') {
throw e; throw e;
} else { } else {
console.warn('leave called too many times.'); console.warn('[StaticCMS] Leave called too many times.');
lock = semaphore(1); lock = semaphore(1);
} }
} }

View File

@ -114,7 +114,7 @@ export async function runWithLock(lock: AsyncLock, func: Function, message: stri
try { try {
const acquired = await lock.acquire(); const acquired = await lock.acquire();
if (!acquired) { if (!acquired) {
console.warn(message); console.warn('[StaticCMS]', message);
} }
const result = await func(); const result = await func();
@ -315,7 +315,7 @@ export async function allEntriesByFolder({
const localTreeInBranch = await isShaExistsInBranch(branch.name, localTree.head); const localTreeInBranch = await isShaExistsInBranch(branch.name, localTree.head);
if (!localTreeInBranch) { if (!localTreeInBranch) {
console.info( console.info(
`Can't find local tree head '${localTree.head}' in branch '${branch.name}', rebuilding local tree`, `[StaticCMS] Can't find local tree head '${localTree.head}' in branch '${branch.name}', rebuilding local tree`,
); );
return listAllFilesAndPersist(); return listAllFilesAndPersist();
} }
@ -329,12 +329,12 @@ export async function allEntriesByFolder({
getFileId, getFileId,
filterFile, filterFile,
}).catch(e => { }).catch(e => {
console.info('Failed getting diff from local tree:', e); console.info('[StaticCMS] Failed getting diff from local tree:', e);
return null; return null;
}); });
if (!diff) { if (!diff) {
console.info(`Diff is null, rebuilding local tree`); console.info(`[StaticCMS] Diff is null, rebuilding local tree`);
return listAllFilesAndPersist(); return listAllFilesAndPersist();
} }

View File

@ -10,7 +10,7 @@ function localForageTest() {
.catch(err => { .catch(err => {
if (err.code === 22) { if (err.code === 22) {
const message = 'Unable to set localStorage key. Quota exceeded! Full disk?'; const message = 'Unable to set localStorage key. Quota exceeded! Full disk?';
console.warn(message); console.warn('[StaticCMS]', message);
} }
console.info(err); console.info(err);
}); });

View File

@ -89,7 +89,7 @@ export function getGroup(entry: Entry, selectedGroup: GroupMap) {
value = matched[0]; value = matched[0];
} }
} catch (e: unknown) { } catch (e: unknown) {
console.warn(`Invalid view group pattern '${pattern}' for field '${field}'`, e); console.warn(`[StaticCMS] Invalid view group pattern '${pattern}' for field '${field}'`, e);
} }
return { return {
id: `${label}${value}`, id: `${label}${value}`,

View File

@ -50,7 +50,9 @@ function validateItem(field: ListField, item: ValueOrNestedValue) {
if (typeof item !== 'object') { if (typeof item !== 'object') {
console.warn( console.warn(
`'${field.name}' field item value value should be an object but is a '${typeof item}'`, `[StaticCMS] '${
field.name
}' field item value value should be an object but is a '${typeof item}'`,
); );
return false; return false;
} }

View File

@ -333,7 +333,7 @@ ${bodyRows.join('\n')}`;
)}${shortcodeConfig.closeTag}`; )}${shortcodeConfig.closeTag}`;
default: default:
console.warn('Unrecognized slate node, proceeding as text', `"${type}"`, chunk); console.warn('[StaticCMS] Unrecognized slate node, proceeding as text', `"${type}"`, chunk);
return children; return children;
} }
} }

View File

@ -276,7 +276,7 @@ export default function deserializeMarkdown(node: MdastNode, options: Options) {
case 'br': case 'br':
return { type: NodeTypes.paragraph, children: [{ text: '' }] }; return { type: NodeTypes.paragraph, children: [{ text: '' }] };
default: default:
console.warn('unrecognized mdx flow element', node); console.warn('[StaticCMS] Unrecognized mdx flow element', node);
break; break;
} }
} }
@ -335,7 +335,7 @@ export default function deserializeMarkdown(node: MdastNode, options: Options) {
...persistLeafFormats(children as Array<MdastNode>), ...persistLeafFormats(children as Array<MdastNode>),
} as TextNode; } as TextNode;
default: default:
console.warn('unrecognized mdx text element', node); console.warn('[StaticCMS] Unrecognized mdx text element', node);
break; break;
} }
} }
@ -356,7 +356,7 @@ export default function deserializeMarkdown(node: MdastNode, options: Options) {
return nodes.map(node => (node.type === 'text' ? { text: node.value ?? '' } : node)); return nodes.map(node => (node.type === 'text' ? { text: node.value ?? '' } : node));
default: default:
console.warn('Unrecognized mdast node, proceeding as text', node); console.warn('[StaticCMS] Unrecognized mdast node, proceeding as text', node);
return { text: node.value || '' }; return { text: node.value || '' };
} }
} }

View File

@ -92,7 +92,7 @@ CMS.registerEventListener({
}); });
``` ```
Supported events are `preSave` and `postSave`. The `preSave` hook can be used to modify the entry data like so: Supported events are `mounted`, `preSave` and `postSave`. The `preSave` hook can be used to modify the entry data like so:
```javascript ```javascript
CMS.registerEventListener({ CMS.registerEventListener({