sanitize-markdown.ts 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import { dynamicImport } from '@cspell/dynamic-import';
  2. import type { Root, Code } from 'mdast';
  3. import type * as RemarkParse from 'remark-parse';
  4. import type * as RemarkStringify from 'remark-stringify';
  5. import type * as Unified from 'unified';
  6. import type * as UnistUtilVisit from 'unist-util-visit';
  7. interface ModuleCache {
  8. remarkParse?: typeof RemarkParse.default;
  9. remarkStringify?: typeof RemarkStringify.default;
  10. unified?: typeof Unified.unified;
  11. visit?: typeof UnistUtilVisit.visit;
  12. }
  13. let moduleCache: ModuleCache = {};
  14. const initializeModules = async(): Promise<void> => {
  15. if (moduleCache.remarkParse != null && moduleCache.remarkStringify != null && moduleCache.unified != null && moduleCache.visit != null) {
  16. return;
  17. }
  18. const [{ default: remarkParse }, { default: remarkStringify }, { unified }, { visit }] = await Promise.all([
  19. dynamicImport<typeof RemarkParse>('remark-parse', __dirname),
  20. dynamicImport<typeof RemarkStringify>('remark-stringify', __dirname),
  21. dynamicImport<typeof Unified>('unified', __dirname),
  22. dynamicImport<typeof UnistUtilVisit>('unist-util-visit', __dirname),
  23. ]);
  24. moduleCache = {
  25. remarkParse,
  26. remarkStringify,
  27. unified,
  28. visit,
  29. };
  30. };
  31. export const sanitizeMarkdown = async(markdown: string): Promise<string> => {
  32. await initializeModules();
  33. const {
  34. remarkParse, remarkStringify, unified, visit,
  35. } = moduleCache;
  36. if (remarkParse == null || remarkStringify == null || unified == null || visit == null) {
  37. throw new Error('Failed to initialize required modules');
  38. }
  39. const sanitize = () => {
  40. return (tree: Root) => {
  41. visit(tree, 'code', (node: Code) => {
  42. if (node.lang === 'drawio') {
  43. node.value = '<!-- drawio content replaced -->';
  44. }
  45. });
  46. };
  47. };
  48. const processor = unified()
  49. .use(remarkParse)
  50. .use(sanitize)
  51. .use(remarkStringify);
  52. return processor.processSync(markdown).toString();
  53. };