checklist.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import { Plugin } from "@docusaurus/types";
  2. import fs from "fs-extra";
  3. import path from "path";
  4. type DocusaurusDoc = {
  5. unversionedId: string;
  6. id: string;
  7. title: string;
  8. description: string;
  9. source: string;
  10. sourceDirName: string;
  11. slug: string;
  12. permalink: string;
  13. draft: boolean;
  14. editUrl: string;
  15. tags: string[];
  16. version: string;
  17. lastUpdatedBy: string;
  18. lastUpdatedAt: number;
  19. formattedLastUpdatedAt: string;
  20. frontMatter: {
  21. id: string;
  22. title: string;
  23. description?: string;
  24. tags?: string[];
  25. };
  26. sidebar: string;
  27. previous?: {
  28. title: string;
  29. permalink: string;
  30. };
  31. next?: {
  32. title: string;
  33. permalink: string;
  34. };
  35. };
  36. type ContentPluginType = {
  37. default: {
  38. loadedVersions: Array<{ docs: DocusaurusDoc[] }>;
  39. };
  40. };
  41. const getDocContent = async (docPath: string) => {
  42. const accessPath = docPath.startsWith("@site/")
  43. ? docPath.replace("@site/", "./")
  44. : docPath;
  45. return new Promise<string | undefined>((resolve) => {
  46. fs.readFile(path.resolve(accessPath), (err, data) => {
  47. if (err) {
  48. resolve(undefined);
  49. }
  50. return resolve(data.toString());
  51. });
  52. });
  53. };
  54. const getChecklistItems = (docContent: string) => {
  55. const regex = /<ChecklistItem[\s\n\r\t]+id="((?:\w|\d|-|_)+)"[\s\n\r\t]*>/g;
  56. const matches = docContent.matchAll(regex);
  57. const itemIds = Array.from(matches).map((match) => match[1]);
  58. return itemIds;
  59. };
  60. const getUnitById = (id: string) => {
  61. // tutorial/<unit-name>/<ui-scope(optional)>/<tutorial-slug>
  62. const unitId = id.split("/")[1];
  63. return unitId;
  64. };
  65. export default function plugin(): Plugin {
  66. return {
  67. name: "docusaurus-plugin-refine-checklist",
  68. configureWebpack(config) {
  69. return {
  70. resolve: {
  71. alias: {
  72. "@checklists": path.join(
  73. config.resolve?.alias?.["@generated"],
  74. "docusaurus-plugin-refine-checklist",
  75. "default",
  76. ),
  77. },
  78. },
  79. };
  80. },
  81. async contentLoaded({ allContent, actions }): Promise<void> {
  82. if (!process.env.DISABLE_CHECKLISTS) {
  83. console.log("Composing Refine tutorial checklists...");
  84. const { createData } = actions;
  85. const currentVersion = (
  86. allContent[
  87. "docusaurus-plugin-content-docs"
  88. ] as ContentPluginType
  89. ).default.loadedVersions[0];
  90. const allDocs = currentVersion.docs as DocusaurusDoc[];
  91. const allTutorials: DocusaurusDoc[] = allDocs.filter(
  92. (doc) =>
  93. doc.id.startsWith("tutorial/") &&
  94. doc.id !== "tutorial/tutorial",
  95. );
  96. const tutorialsWithChecklist = await Promise.all(
  97. allTutorials.map(async (tutorial) => {
  98. const docContent = await getDocContent(tutorial.source);
  99. const checklistItemIds = getChecklistItems(
  100. docContent ?? "",
  101. );
  102. return {
  103. id: tutorial.id,
  104. unit: getUnitById(tutorial.id),
  105. title: tutorial.title,
  106. checklist: checklistItemIds.map((id, index) => ({
  107. id,
  108. index,
  109. })),
  110. };
  111. }),
  112. );
  113. const data = {
  114. items: tutorialsWithChecklist,
  115. };
  116. await createData(
  117. `tutorial-checklist-data.json`,
  118. JSON.stringify(data),
  119. );
  120. } else {
  121. const { createData } = actions;
  122. await createData(
  123. `tutorial-checklist-data.json`,
  124. JSON.stringify({ items: [] }),
  125. );
  126. }
  127. },
  128. };
  129. }