ForEach.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import { PugNode } from "../../Parser";
  2. import Token from "../Token";
  3. export default class ForEach extends Token {
  4. private static readonly FOREACH_CONDITION = /for(each)? (?<variable>.+?) (?<type>in|of) (?<arr>.+)$/;
  5. public parse(nodes: PugNode[]) {
  6. for(let index = 0; index < nodes.length; index++) {
  7. const node = nodes[index];
  8. // Check if it's a foreach
  9. if (node.type === "Tag" && node.name === "foreach") {
  10. let condition: RegExpMatchArray;
  11. // Check if the next node is a text node
  12. if (node.block?.nodes[0].type === "Text") {
  13. condition = ("foreach " + node.block?.nodes[0].val).match(ForEach.FOREACH_CONDITION);
  14. // Remove the text from the nodes
  15. node.block.nodes.splice(0, 1);
  16. } else {
  17. condition = ("foreach " + node.attrs.map((attr) => attr.name).join(" ")).match(ForEach.FOREACH_CONDITION);
  18. }
  19. // Check if it's an invalid foreach condition
  20. if (!condition) {
  21. throw new TypeError("Invalid foreach condition. It needs to have a variable (array) and a condition.");
  22. }
  23. const { variable, type, arr } = condition.groups;
  24. // Set the tag name
  25. node.name = "p:foreach";
  26. // Setup the attributes for the foreach
  27. node.attrs = [
  28. {
  29. name: "var",
  30. val: `"${variable}"`,
  31. mustEscape: false
  32. },
  33. {
  34. name: "type",
  35. val: `"${type}"`,
  36. mustEscape: false
  37. },
  38. {
  39. name: "array",
  40. val: `"${arr}"`,
  41. mustEscape: false
  42. }
  43. ];
  44. }
  45. // Parses the block
  46. if (node.block) {
  47. node.block.nodes = this.parse(node.block.nodes);
  48. }
  49. }
  50. return nodes;
  51. }
  52. };