文件
mynode/packages/htmlpack/utils/parseHtmlAsync.ts
chen 301194963b
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
feat: Initial clean release of CHM
2026-11-04 11:29:39 +08:00

80 行
1.6 KiB
TypeScript

import * as htmlparser2 from '@joplin/fork-htmlparser2';
export type HtmlAttrs = Record<string, string>;
interface Callbacks {
onopentag: (name: string, attrs: HtmlAttrs)=> Promise<void>;
ontext: (text: string)=> Promise<void>;
onclosetag: (name: string)=> Promise<void>;
}
enum EventTypes {
OpenTag,
Text,
CloseTag,
}
interface OpenTagEvent {
type: EventTypes.OpenTag;
name: string;
attrs: HtmlAttrs;
}
interface TextEvent {
type: EventTypes.Text;
decodedText: string;
}
interface CloseTagEvent {
type: EventTypes.CloseTag;
name: string;
}
type ParserEvent = OpenTagEvent|TextEvent|CloseTagEvent;
const parseHtmlAsync = async (html: string, callbacks: Callbacks) => {
const events: ParserEvent[] = [];
const parser = new htmlparser2.Parser({
onopentag: (name: string, attrs: HtmlAttrs) => {
events.push({
type: EventTypes.OpenTag,
name,
attrs,
});
},
ontext: (decodedText: string) => {
events.push({
type: EventTypes.Text,
decodedText,
});
},
onclosetag: (name: string) => {
events.push({
type: EventTypes.CloseTag,
name,
});
},
}, { decodeEntities: true });
parser.write(html);
parser.end();
for (const event of events) {
if (event.type === EventTypes.OpenTag) {
await callbacks.onopentag(event.name, event.attrs);
} else if (event.type === EventTypes.CloseTag) {
await callbacks.onclosetag(event.name);
} else if (event.type === EventTypes.Text) {
await callbacks.ontext(event.decodedText);
} else {
const exhaustivenessCheck: never = event;
throw new Error(`Unknown event type: ${exhaustivenessCheck}`);
}
}
};
export default parseHtmlAsync;