format.ts 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import type { HTMLNode, CommentOrTextAST, ElementAST, AST } from './types';
  2. export const splitHead = (str: string, sep: string) => {
  3. const idx = str.indexOf(sep);
  4. if (idx === -1) return [str];
  5. return [str.slice(0, idx), str.slice(idx + sep.length)];
  6. };
  7. const unquote = (str: string) => {
  8. const car = str.charAt(0);
  9. const end = str.length - 1;
  10. const isQuoteStart = car === '"' || car === "'";
  11. if (isQuoteStart && car === str.charAt(end)) {
  12. return str.slice(1, end);
  13. }
  14. return str;
  15. };
  16. const formatAttributes = (attributes: string[]) => {
  17. return attributes.map((attribute) => {
  18. const parts = splitHead(attribute.trim(), '=');
  19. const key = parts[0];
  20. const value = typeof parts[1] === 'string' ? unquote(parts[1]) : null;
  21. return { key, value };
  22. });
  23. };
  24. export const format = (nodes: HTMLNode[]): AST[] => {
  25. return nodes.map((node) => {
  26. if (node.type === 'element') {
  27. const children = format(node.children);
  28. const item: ElementAST = {
  29. type: 'element',
  30. tagName: node.tagName.toLowerCase(),
  31. attributes: formatAttributes(node.attributes),
  32. children,
  33. };
  34. return item;
  35. }
  36. const item: CommentOrTextAST = {
  37. type: node.type,
  38. content: node.content,
  39. };
  40. return item;
  41. });
  42. };