您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

import-content.mjs 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import fs from "node:fs";
  2. const root = new URL("../", import.meta.url);
  3. const read = (n) =>
  4. JSON.parse(fs.readFileSync(new URL("research/" + n + ".json", root)));
  5. const base = "https://cms.aducktive.com/panel";
  6. async function asset(url, name) {
  7. const path = "/images/" + name;
  8. const r = await fetch(url, { signal: AbortSignal.timeout(25000) });
  9. if (!r.ok) throw Error(url + ": " + r.status);
  10. fs.writeFileSync(
  11. new URL("public" + path, root),
  12. Buffer.from(await r.arrayBuffer()),
  13. );
  14. return path;
  15. }
  16. const raw = read("store-products");
  17. const products = [];
  18. for (const p of raw) {
  19. const f = p.product_flat;
  20. const images = await Promise.all(
  21. p.product_images.map((im, i) => asset(im.url, `snack-${p.id}-${i}.webp`)),
  22. );
  23. const name = f.name
  24. .replace(/^(FP |VP |\(NEW\) )/, "")
  25. .replace(/\s\d+g$/, "")
  26. .toLowerCase()
  27. .replace(/\b\w/g, (c) => c.toUpperCase());
  28. const weight = f.name.match(/\d+g$/)?.[0] || "";
  29. const category = /TEMPEH/.test(f.name)
  30. ? "Tempeh chips"
  31. : /MUSHROOM/.test(f.name)
  32. ? "Mushroom crisps"
  33. : /CORNFLAKES|Cornflakes/.test(f.name)
  34. ? "Cornflakes"
  35. : "Bundles & gifts";
  36. products.push({
  37. id: p.id,
  38. name,
  39. originalName: f.name,
  40. slug: f.urlKey,
  41. price: Number(f.specialPrice || f.price),
  42. regularPrice: Number(f.price),
  43. weight,
  44. pack: f.name.startsWith("FP")
  45. ? "Family pack"
  46. : f.name.startsWith("VP")
  47. ? "Value pack"
  48. : f.name.includes("Fun Pack")
  49. ? "Fun pack"
  50. : "Bundle",
  51. category,
  52. stock: p.inventories?.qty || 0,
  53. images,
  54. isNew: f.name.includes("(NEW)"),
  55. spicy: /spicy/i.test(f.name),
  56. description: "",
  57. categories: p.categories.map((c) => c.slug),
  58. });
  59. }
  60. const story = read("story").data.attributes;
  61. const stories = await Promise.all(
  62. story.our_milestone.map(async (m, i) => ({
  63. year: m.year,
  64. text: m.desc,
  65. image: await asset(
  66. base +
  67. (m.image.data[0].attributes.formats?.medium?.url ||
  68. m.image.data[0].attributes.url),
  69. `story-${i}.webp`,
  70. ),
  71. })),
  72. );
  73. const news = await Promise.all(
  74. read("news")
  75. .data.slice(0, 12)
  76. .map(async (p, i) => {
  77. let a = p.attributes;
  78. let img = a.image.data[0]?.attributes;
  79. return {
  80. id: p.id,
  81. title: a.title,
  82. content: a.content,
  83. date: a.date,
  84. category: /retreat|Iftar/i.test(a.title)
  85. ? "Our people"
  86. : /MIHAS|AHEX|Bazaar/i.test(a.title)
  87. ? "Events"
  88. : "Brand news",
  89. image: img
  90. ? await asset(
  91. base + (img.formats?.medium?.url || img.url),
  92. `journal-${p.id}.webp`,
  93. )
  94. : "",
  95. };
  96. }),
  97. );
  98. await asset(
  99. "https://aducktive.com/favicon_io/favicon-32x32.png",
  100. "favicon.png",
  101. );
  102. fs.writeFileSync(
  103. new URL("src/content.json", root),
  104. JSON.stringify(
  105. {
  106. products,
  107. story: {
  108. description: story.desc,
  109. mission: story.our_mission,
  110. vision: story.our_vision,
  111. milestones: stories,
  112. },
  113. reviews: read("testimonials").data.attributes.comment.map((r) => ({
  114. name: r.name,
  115. message: r.message,
  116. })),
  117. social: read("social").data.attributes.social.map((s) => s.link),
  118. articles: news,
  119. },
  120. null,
  121. 2,
  122. ),
  123. );
  124. console.log(
  125. "Imported",
  126. products.length,
  127. "products and",
  128. news.length,
  129. "articles.",
  130. );