attachment.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import { Schema as SanitizeOption } from 'hast-util-sanitize';
  2. import { Plugin } from 'unified';
  3. import { visit } from 'unist-util-visit';
  4. const SUPPORTED_ATTRIBUTES = ['attachmentId', 'url', 'attachmentName'];
  5. const isAttachmentLink = (url: string) => {
  6. // https://regex101.com/r/9qZhiK/1
  7. const attachmentUrlFormat = new RegExp(/^\/(attachment)\/([^/^\n]+)$/);
  8. return url.match(attachmentUrlFormat);
  9. };
  10. export const remarkPlugin: Plugin = () => {
  11. return (tree) => {
  12. // TODO: do not use any for node.children[0].value
  13. visit(tree, (node: any) => {
  14. if (node.type === 'link') {
  15. if (isAttachmentLink(node.url)) {
  16. const pathName = node.url.split('/');
  17. const data = node.data ?? (node.data = {});
  18. data.hName = 'attachment';
  19. data.hProperties = {
  20. attachmentId: pathName[2],
  21. url: node.url,
  22. attachmentName: node.children[0].value,
  23. };
  24. // omit position to fix the key regardless of its position
  25. // see:
  26. // https://github.com/remarkjs/react-markdown/issues/703
  27. // https://github.com/remarkjs/react-markdown/issues/466
  28. //
  29. // https://github.com/remarkjs/react-markdown/blob/a80dfdee2703d84ac2120d28b0e4998a5b417c85/lib/ast-to-react.js#L201-L204
  30. // https://github.com/remarkjs/react-markdown/blob/a80dfdee2703d84ac2120d28b0e4998a5b417c85/lib/ast-to-react.js#L217-L222
  31. delete node.position;
  32. }
  33. }
  34. });
  35. };
  36. };
  37. export const sanitizeOption: SanitizeOption = {
  38. tagNames: ['attachment'],
  39. attributes: {
  40. attachment: SUPPORTED_ATTRIBUTES,
  41. },
  42. };