Advertisement
Guest User

Untitled

a guest
Apr 28th, 2017
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 43.92 KB | None | 0 0
  1. /*
  2. * This script converts API data from Backlog Syntax to Markdown.
  3. * It can also output to Markdown and JSON.
  4. */
  5.  
  6. // Lib Imports
  7. const fs = require('fs');
  8. const path = require('path');
  9. const chalk = require('chalk');
  10. const readline = require('readline');
  11.  
  12. // App configuration imports
  13. const backlogConfig = require('./backlog-config').en;
  14. const topicsConfig = require('./topics-config');
  15. // List of top-level topics that get their own section
  16. let backlogTopLevelTopics = backlogConfig.topLevelTopics;
  17.  
  18.  
  19. // CLI arguments
  20. const outputFormat = process.argv[2].toLowerCase();
  21. const inputPathArgument = process.argv[3];
  22. const outputPathArgument = process.argv[4];
  23.  
  24. // bwiki libs
  25. const STATUS = require('./status-codes');
  26. const reportStatus = STATUS.reportStatus;
  27.  
  28. // Readline
  29. let rl;
  30.  
  31. reportStatus(STATUS.STARTING_HUGO);
  32.  
  33. /**
  34. * Extracts data, adds Hugo-specific front-matter
  35. * @param {string} inputPathArgument - path to unconverted file
  36. */
  37. fs.readFile(inputPathArgument, 'utf8', (err, data) => {
  38. switch (outputFormat) {
  39. case "md":
  40. case "markdown":
  41. saveAsMarkdown(data);
  42. break;
  43. case "json":
  44. saveAsJson(data);
  45. break;
  46. case "hugo":
  47. buildForHugo(data);
  48. break;
  49. default:
  50. console.error(STATUS.ERROR_PARSE);
  51. }
  52. });
  53.  
  54. /*
  55. * Save input string as outputPathArgument in markdown
  56. */
  57. function saveAsMarkdown(data) {
  58. reportStatus(STATUS.BEGIN_MARKDOWN_CONVERT);
  59. convertToMarkdownSyntax(data)
  60. .then((markdownData) => {
  61. reportStatus(STATUS.FINISH_CONVERT);
  62. reportStatus(STATUS.WRITING_TO_FILE);
  63. fs.writeFile(outputPathArgument, markdownData, 'utf8', function(err) {
  64. if (err) {
  65. return console.log(chalk.red(err))
  66. }
  67. });
  68. });
  69. }
  70.  
  71. /*
  72. * Save input string as outputPathArgument as JSON
  73. */
  74. function saveAsJson(data) {
  75. reportStatus(STATUS.BEGIN_MARKDOWN_INTERIM_CONVERT);
  76. convertToMarkdownSyntax(data)
  77. .then((markdownData) => {
  78.  
  79. reportStatus(STATUS.FINISH_CONVERT);
  80.  
  81. reportStatus(STATUS.BEGIN_JSON_CONVERT);
  82.  
  83. let lines = markdownData.split('\n');
  84.  
  85. extractTopics(lines).then((topics) => {
  86. reportStatus(STATUS.FINISH_CONVERT);
  87. reportStatus(STATUS.WRITING_TO_FILE);
  88. fs.writeFile(outputPathArgument, JSON.stringify(topics), 'utf8', function(err) {
  89. if (err) {
  90. return console.log(chalk.red(err))
  91. }
  92. });
  93. });
  94. });
  95. }
  96.  
  97. /**
  98. * Extracts data, adds Hugo-specific front-matter
  99. * @param {string} data - text string containing all API data
  100. */
  101. function buildForHugo(data) {
  102. reportStatus(STATUS.BEGIN_HUGO_BUILD);
  103. convertToMarkdownSyntax(data)
  104. .then((markdownData) => {
  105.  
  106. let lines = markdownData.split('\n');
  107.  
  108. extractTopics(lines).then((topics) => {
  109.  
  110. // Hard code value for now
  111. let app = "backlog";
  112. let now = Date.now();
  113.  
  114. // For each topic,
  115. for (let topicNumber in topics) {
  116.  
  117. let currentTopic = topics[topicNumber];
  118. let topicTitle = currentTopic.topicName;
  119. let topicFilename =
  120. topicTitle
  121. .toLowerCase()
  122. .replace(/ /g, "-")
  123. .replace(/\?/g, "")
  124. .replace(/\//g, "-");
  125. let urlParameter = "";
  126.  
  127. // Conditionally add urlParameter
  128. if (backlogConfig.urlMaps.hasOwnProperty(topicFilename)) {
  129. urlParameter = `url = "${backlogConfig.urlMaps[topicFilename]}"`;
  130. } else {
  131. urlParameter = `url = /docs/backlog/api/2/${topicFilename}`;
  132. }
  133.  
  134. // Don't change indentation,
  135. // it seems to break ES6 template string's newlines.
  136. let topicFrontMatter =
  137. `
  138. +++
  139. isApi = false
  140. weight = ${currentTopic.topicWeight}
  141. title = "${topicTitle}"
  142. fileName = "${topicFilename}"
  143. apps = "${app}"
  144. ${urlParameter}
  145. +++\n
  146. `.substring(1);
  147.  
  148. let topicContent = currentTopic.topicContent.trim();
  149. let newTopicItem = "";
  150.  
  151. newTopicItem = newTopicItem + topicFrontMatter + topicContent;
  152.  
  153. if (topicsConfig.blacklist.includes(topicFilename)) {
  154. console.log(`"${topicFilename}.md" has been skipped, since it should not be included. Check topics-config.js for details.`)
  155. } else {
  156. fs.writeFile(`content/${app}/${topicFilename}.md`, newTopicItem, 'utf8', function(err) {
  157. if (err) {
  158. return console.log(chalk.red(err))
  159. }
  160. });
  161. }
  162.  
  163. for (let subtopicNumber in currentTopic.subtopics) {
  164.  
  165. let currentSubtopic = currentTopic.subtopics[subtopicNumber];
  166. let subtopicTitle = currentSubtopic.subtopicName;
  167. let subtopicFilename =
  168. subtopicTitle
  169. .toLowerCase()
  170. .replace(/ /g, "-")
  171. .replace(/\?/g, "")
  172. .replace(/\./g, "")
  173. .replace(/\//g, "-");
  174.  
  175. // Remove parenthesis, if exists
  176. subtopicFilename =
  177. subtopicFilename
  178. .replace(/\(/g, '')
  179. .replace(/\)/g, '');
  180.  
  181.  
  182. let subtopicUrlParameter = `url = "/docs/backlog/api/2/${subtopicFilename}"`;
  183. let subtopicFrontMatter =
  184. `
  185. +++
  186. isApi = ${currentSubtopic.isApi}
  187. weight = ${currentSubtopic.subtopicWeight}
  188. group = "${topicTitle}"
  189. title = "${subtopicTitle}"
  190. fileName = "${subtopicFilename}"
  191. apps = "${app}"
  192. ${subtopicUrlParameter}
  193. +++\n
  194. `.substring(1);
  195.  
  196. let subtopicContent = currentSubtopic.subtopicContent.trim();
  197. let newSubtopicItem = "";
  198.  
  199. newSubtopicItem = newSubtopicItem + subtopicFrontMatter + subtopicContent;
  200.  
  201. if (topicTitle == "Version history" && subtopicTitle != "API Libraries") {
  202. console.log(`Version History individual versions shouldn't be saved to disk, so one such file has been skipped: ${subtopicTitle}`);
  203. } else if (topicsConfig.blacklist.includes(subtopicFilename)) {
  204. console.log(`"${subtopicFilename}.md" has been skipped, since it should not be included. Check topics-config.js for details.`)
  205. } else {
  206. fs.writeFile(`content/${app}/${subtopicFilename}.md`, newSubtopicItem, 'utf8', function(err) {
  207. if (err) {
  208. return console.log(chalk.red(err))
  209. }
  210. });
  211. }
  212. }
  213. }
  214. });
  215. });
  216. reportStatus(STATUS.WRITING_TO_FILE);
  217. reportStatus(STATUS.FINISH_CONVERT);
  218. }
  219.  
  220.  
  221. /**
  222. * Extract text and add semantic markers by converting to JSON
  223. * @param {string} lines - text string containing all API data
  224. */
  225. function extractTopics(lines) {
  226. return new Promise((resolve, reject) => {
  227.  
  228. // Use pointers to build object inside for loop
  229. let topics = [];
  230. let newTopic = {};
  231. let newTopicName = "";
  232. let newTopicContent = "";
  233. let newTopicWeight = 0;
  234.  
  235. let subtopics = {};
  236. let newSubtopic = {};
  237. let newSubtopicName = "";
  238. let newSubtopicContent = "";
  239. let newSubtopicWeight = 0;
  240. let recordingTopic = false;
  241. let recordingSubtopic = false;
  242.  
  243. let currentLineIsNewTopic = false;
  244. let currentLineIsNewSubtopic = false;
  245. let nextLineIsNewTopic = false;
  246. let nextLineIsNewSubtopic = false;
  247. let completed = false;
  248.  
  249. try {
  250.  
  251. // For each line
  252. for (let i = 0; i < lines.length; i++) {
  253.  
  254. let currentLine = lines[i];
  255. let nextIndex = i + 1;
  256. let nextLine = lines[nextIndex];
  257.  
  258. // Check "nextLine" status
  259. if (currentLine != null && nextLine != null) {
  260. currentLineIsNewTopic = currentLine.substring(0, 2) == "# ";
  261. currentLineIsNewSubtopic = currentLine.substring(0, 3) == "## ";
  262. nextLineIsNewTopic = nextLine.substring(0, 2) == "# ";
  263. nextLineIsNewSubtopic = nextLine.substring(0, 3) == "## ";
  264. }
  265.  
  266. /***************************
  267. * Check whether to capture
  268. ***************************/
  269. if (currentLineIsNewTopic) {
  270. let topicName = currentLine.substring(2);
  271. newTopicName = topicName;
  272. recordingTopic = true;
  273. }
  274.  
  275. if (nextLineIsNewSubtopic) {
  276. recordingTopic = false;
  277. }
  278.  
  279. if (currentLineIsNewSubtopic) {
  280. let subTopicName = currentLine.substring(3);
  281. newSubtopicName = subTopicName;
  282. recordingSubtopic = true;
  283. }
  284.  
  285. /******************************
  286. * Capture Lines (conditionally)
  287. ******************************/
  288. if ((recordingTopic && !currentLineIsNewSubtopic) || backlogTopLevelTopics.includes(newTopicName)) {
  289. newTopicContent += `${currentLine} \n`;
  290. }
  291.  
  292. if (recordingSubtopic && !currentLineIsNewTopic) {
  293. newSubtopicContent += `${currentLine} \n`;
  294. }
  295.  
  296. /*****************
  297. * Record content
  298. *****************/
  299.  
  300. // Save SUBTOPIC
  301. if ((nextLineIsNewSubtopic || nextLineIsNewTopic) && newSubtopicName.length > 0) {
  302.  
  303. // build and record subtopic as property of newTopic
  304. let keyName = newSubtopicName.toLowerCase().replace(/ /g, "-").replace(/\?/g, "");
  305. newSubtopic.subtopicName = newSubtopicName;
  306. newSubtopic.subtopicContent = newSubtopicContent.trim();
  307. newSubtopic.subtopicWeight = newSubtopicWeight;
  308.  
  309. // Only API items have the keyword "Role" as a field
  310. if (newSubtopicContent.includes("### Method \n")) {
  311. newSubtopic.isApi = true;
  312. } else {
  313. newSubtopic.isApi = false;
  314. }
  315.  
  316. subtopics[keyName.toString()] = newSubtopic;
  317.  
  318. // Wipe data for next subtopic
  319. newSubtopic = {};
  320. newSubtopicName = "";
  321. newSubtopicContent = "";
  322. nextLineIsNewSubtopic = false;
  323. // Increment subtopic weight (don't reset)
  324. newSubtopicWeight++;
  325. }
  326.  
  327. // Save TOPIC.
  328. let isLastLine = (lines[i + 1] == null);
  329. if ((nextLineIsNewTopic || isLastLine) && i > 1) {
  330.  
  331. // Build newTopic to be returned
  332. newTopic.topicName = newTopicName;
  333. newTopic.subtopics = subtopics;
  334. newTopic.topicContent = newTopicContent.trim();
  335. newTopic.topicWeight = newTopicWeight;
  336. topics.push(newTopic);
  337.  
  338. // Reset newTopic and relevant fields
  339. newTopic = {};
  340. newTopicName = "";
  341. newSubtopic = {};
  342. newTopicContent = "";
  343. subtopics = {};
  344. nextLineIsNewTopic = false;
  345.  
  346. // Increment topic weight (don't reset)
  347. newTopicWeight++;
  348. }
  349.  
  350. }
  351. } catch (err) {
  352. console.error(`${STATUS.ERROR_PARSE}. \n ${err}`);
  353. }
  354.  
  355. // Resolve
  356. resolve(topics);
  357.  
  358. // Reject
  359. reject(new Error(STATUS.ERROR_PARSE));
  360. });
  361. }
  362.  
  363. /**
  364. * Converts Backlog syntax STRING to valid Markdown
  365. * @param {string} data - path to raw data from file
  366. */
  367. function convertToMarkdownSyntax(data) {
  368. return new Promise((resolve, reject) => {
  369.  
  370.  
  371. // Convert * to #
  372. let result = data.replace(/\*/g, '#');
  373. // Convert {code} to ```
  374. result = result.replace(/({code})/g, '```');
  375. result = result.replace(/({\/code})/g, '```\n');
  376. // Convert [[a:b]] to [a](b)
  377. result = result.replace(/(\[\[)([^\:]+)\:(([^\s]+))(\]\])/g, '[$2]($3)');
  378. result = result.replace(/(&br;)/g, "<br>");
  379.  
  380.  
  381. let lines = result.split('\n');
  382.  
  383. /**
  384. * CUSTOM HARD-CODED PARSERS FOR BACKLOG SYNTAX
  385. */
  386. // PARSE CODE KEYWORDS
  387. let codeKeywords = [
  388. "role", "url", "method", "scope"
  389. ];
  390. // PARSE RESPONSE EXAMPLES
  391. let responseExampleKeywords = [
  392. "response example"
  393. ];
  394. // URL PARAMETERS + QUERY PARAMETERS
  395. let formKeywords = [
  396. "url parameters",
  397. "query parameters",
  398. "response description",
  399. "custom fields (text)",
  400. "custom fields (numeric)",
  401. "custom fields (date)",
  402. "custom fields (list)"
  403. ];
  404. // FORM PARAMETERS
  405. let formParametersKeywords = [
  406. "form parameters"
  407. ];
  408.  
  409. let keywords = codeKeywords.concat(responseExampleKeywords, formKeywords, formParametersKeywords);
  410.  
  411. for (let i = 0; i < lines.length; i++) {
  412.  
  413. let prevLine = (i > 0) ? lines[i] : null;
  414. let currentLine = lines[i];
  415. let lineContent = currentLine.substring(2).toLowerCase().trim();
  416. let nextLine = lines[i + 1];
  417. let nextNextLine = lines[i + 2];
  418.  
  419. // Some quick validation because I noticed inconsistencies
  420. // if ( (currentLine.substring(0, 3) === "## ")
  421. // && (i - 1 > 0)
  422. // && (lines[i-1].length > 0)) {
  423. // // lines.splice(i-1, 0, "\n");
  424. // lines[i-1] = "\n";
  425. // }
  426.  
  427. // Set section headers to <h4>
  428. if (keywords.includes(lineContent)) {
  429. if (nextLine.length > 0) {
  430. // If this section has content, trim and markdownify
  431. lines[i] = `### ${currentLine.substring(2).trim()}`;
  432. } else {
  433. // Otherwise, remove array entries to keep markdown files clean
  434. lines.splice(i - 1, 3, "");
  435. i -= 2;
  436. }
  437. }
  438.  
  439. if (codeKeywords.includes(lineContent) && nextLine.length > 0) {
  440.  
  441. lines.splice(i + 1, 0, `\`\`\``);
  442.  
  443. // Account for multiple
  444. let offset = 2;
  445.  
  446. while (lines[i + offset].length > 0) {
  447. offset += 1;
  448. }
  449.  
  450. lines.splice(i + offset, 0, `\`\`\``);
  451. }
  452.  
  453. if (responseExampleKeywords.includes(lineContent) && nextLine.length > 0) {
  454. // Restructure
  455. lines.splice(i + 1, 0, `#### Status Line / Response Header`);
  456.  
  457. // Account for potential multiple lines
  458.  
  459. let offset = 5;
  460. while (lines[i + offset] != '```') {
  461. offset += 1;
  462. }
  463. lines.splice(i + offset + 1, 0, `#### Response Body`);
  464. }
  465.  
  466.  
  467. if (formKeywords.includes(lineContent) && nextLine.length > 0) {
  468.  
  469. // If there's a table
  470. lines.splice(i + 1, 0, 'Parameter Name | Type | Description');
  471. lines.splice(i + 2, 0, '---|---|---');
  472.  
  473. let offset = 3;
  474.  
  475. // while the first character is "|", trim to make valid syntax
  476. while (lines[i + offset].substring(0, 1) == "|") {
  477. lines[i + offset] = lines[i + offset].slice(1, -1).trim();
  478. offset += 1;
  479. }
  480. }
  481.  
  482. if (formParametersKeywords.includes(lineContent) && nextLine.length > 0) {
  483.  
  484. lines.splice(i + 1, 0, `\`\`\``);
  485. lines.splice(i + 3, 0, `\`\`\``);
  486. lines.splice(i + 4, 0, ``);
  487.  
  488. if (lines[i + 5].substring(0, 1) == "|") {
  489. // Remove first and last | character
  490.  
  491. let offset = 5;
  492.  
  493. // wipe lines until you hit a blank line
  494. while (lines[i + offset].length != 0) {
  495. lines[i + offset] = lines[i + offset].slice(1, -1).trim();
  496. offset += 1;
  497. }
  498. lines.splice(i + 6, 0, `\-\-\-\- | \-\-\-\- | \-\-\-\-`);
  499. }
  500. }
  501.  
  502. }
  503.  
  504.  
  505. // Reassemble
  506. result = lines.join('\n');
  507.  
  508. // Return markdown-ified data
  509. if (result.length > 1) {
  510. resolve(result);
  511. } else {
  512. reject(new Error(STATUS.ERROR_PARSE));
  513. }
  514. });
  515. }
  516.  
  517. "use strict"
  518. /*
  519. * This script converts Japanese API data from Backlog Syntax to Markdown.
  520. * It can also output to Markdown and JSON.
  521. */
  522.  
  523. // Lib Imports
  524. const fs = require('fs');
  525. const path = require('path');
  526. const chalk = require('chalk');
  527. const readline = require('readline');
  528.  
  529. // App configuration imports
  530. const backlogConfig = require('./backlog-config').ja;
  531. const topicsConfig = require('./topics-config');
  532. // List of top-level topics that get their own section
  533. const backlogTopLevelTopics = backlogConfig.topLevelTopics;
  534.  
  535. // CLI arguments
  536. const outputFormat = process.argv[2].toLowerCase();
  537. const inputPathArgument = process.argv[3];
  538. const outputPathArgument = process.argv[4];
  539.  
  540. // bwiki libs
  541. const STATUS = require('./status-codes');
  542. const reportStatus = STATUS.reportStatus;
  543.  
  544. // Readline
  545. let rl;
  546.  
  547. reportStatus(STATUS.STARTING_HUGO);
  548.  
  549. /**
  550. * Extracts data, adds Hugo-specific front-matter
  551. * @param {string} inputPathArgument - path to unconverted file
  552. */
  553. fs.readFile(inputPathArgument, 'utf8', (err, data) => {
  554. switch (outputFormat) {
  555. case "md":
  556. case "markdown":
  557. saveAsMarkdown(data);
  558. break;
  559. case "json":
  560. saveAsJson(data);
  561. break;
  562. case "hugo":
  563. buildForHugo(data);
  564. break;
  565. default:
  566. console.error(STATUS.ERROR_PARSE);
  567. }
  568. });
  569.  
  570. /*
  571. * Save input string as outputPathArgument in markdown
  572. */
  573. function saveAsMarkdown(data) {
  574. reportStatus(STATUS.BEGIN_MARKDOWN_CONVERT);
  575. convertToMarkdownSyntax(data)
  576. .then((markdownData) => {
  577. reportStatus(STATUS.FINISH_CONVERT);
  578. reportStatus(STATUS.WRITING_TO_FILE);
  579. fs.writeFile(outputPathArgument, markdownData, 'utf8', function(err) {
  580. if (err) {
  581. return console.log(chalk.red(err))
  582. }
  583. });
  584. });
  585. }
  586.  
  587. /*
  588. * Save input string as outputPathArgument as JSON
  589. */
  590. function saveAsJson(data) {
  591. reportStatus(STATUS.BEGIN_MARKDOWN_INTERIM_CONVERT);
  592. convertToMarkdownSyntax(data)
  593. .then((markdownData) => {
  594.  
  595. reportStatus(STATUS.FINISH_CONVERT);
  596.  
  597. reportStatus(STATUS.BEGIN_JSON_CONVERT);
  598.  
  599. let lines = markdownData.split('\n');
  600.  
  601. extractTopics(lines).then((topics) => {
  602. reportStatus(STATUS.FINISH_CONVERT);
  603. reportStatus(STATUS.WRITING_TO_FILE);
  604. fs.writeFile(outputPathArgument, JSON.stringify(topics), 'utf8', function(err) {
  605. if (err) {
  606. return console.log(chalk.red(err))
  607. }
  608. });
  609. });
  610. });
  611. }
  612.  
  613. /**
  614. * Extracts data, adds Hugo-specific front-matter
  615. * @param {string} data - text string containing all API data
  616. */
  617. function buildForHugo(data) {
  618. reportStatus(STATUS.BEGIN_HUGO_BUILD);
  619. convertToMarkdownSyntax(data)
  620. .then((markdownData) => {
  621.  
  622. let lines = markdownData.split('\n');
  623.  
  624. let headingsList = JSON.parse(fs.readFileSync('./api-data/headings-list.json', ''));
  625. let subheadingsList = JSON.parse(fs.readFileSync('./api-data/subheadings-list.json', ''));
  626. extractTopics(lines).then((topics) => {
  627.  
  628. // Hard code value for now
  629. let app = "backlog";
  630.  
  631. // For each topic,
  632.  
  633. // for (let topicNumber of topics) {
  634. for (let i = 0; i < topics.length; i++) {
  635.  
  636.  
  637. // let currentTopic = topicNumber;
  638. let currentTopic = topics[i];
  639. let topicTitle = currentTopic.topicName;
  640.  
  641. // console.log(chalk.blue(topicTitle))
  642. let topicFilename =
  643. topicTitle
  644. .toLowerCase()
  645. .replace(/ /g, "-")
  646. .replace(/\?/g, "")
  647. .replace(/\//g, "-");
  648.  
  649. let urlParameter = "";
  650.  
  651. // Conditionally add urlParameter
  652. if (backlogConfig.urlMaps.hasOwnProperty(topicFilename)) {
  653. urlParameter = `url = "${backlogConfig.urlMaps[topicFilename]}"`;
  654. } else {
  655. topicFilename =
  656. currentTopic.topicName
  657. .toLowerCase()
  658. .replace(/ /g, "-")
  659. .replace(/\?/g, "")
  660. .replace(/\//g, "-");
  661. urlParameter = `url = "/ja/docs/backlog/api/2/${topicFilename}"`;
  662. }
  663.  
  664. // Don't change indentation,
  665. // it seems to break ES6 template string's newlines.
  666. let topicFrontMatter =
  667. `
  668. +++
  669. isApi = false
  670. weight = ${currentTopic.topicWeight}
  671. title = "${currentTopic.japaneseTopicName}"
  672. fileName = "${topicFilename}"
  673. ${urlParameter}
  674. +++\n
  675. `.substring(1);
  676.  
  677. let topicContent = currentTopic.topicContent;
  678. let newTopicItem = "";
  679.  
  680. newTopicItem = newTopicItem + topicFrontMatter + topicContent;
  681.  
  682. if (topicsConfig.blacklist.includes(topicFilename)) {
  683. console.log(`"${topicFilename}.md" has been skipped, since it should not be included. Check topics-config.js for details.`)
  684. } else {
  685. console.log(chalk.green(`Successfully saved: ${topicFilename}.ja.md`));
  686. fs.writeFile(`content/${app}/${topicFilename}.ja.md`, newTopicItem, 'utf8', function(err) {
  687. if (err) {
  688. return console.log(chalk.red(err))
  689. }
  690. });
  691. }
  692.  
  693. try {
  694.  
  695. for (let subtopicKey in currentTopic.subtopics) {
  696.  
  697. let currentSubtopic = currentTopic.subtopics[subtopicKey];
  698. // let currentSubtopic = subtopicKey;
  699. let subtopicTitle = currentSubtopic.subtopicName;
  700. let subtopicFilename =
  701. subtopicTitle
  702. .toLowerCase()
  703. .replace(/ /g, "-")
  704. .replace(/\?/g, "")
  705. .replace(/\./g, "")
  706. .replace(/\//g, "-")
  707.  
  708. // Remove parenthesis, if exists
  709. .replace(/\(/g, '')
  710. .replace(/\)/g, '');
  711.  
  712. let subtopicUrlParameter = `url = "/ja/docs/backlog/api/2/${subtopicFilename}"`;
  713. let subtopicFrontMatter =
  714. `
  715. +++
  716. isApi = ${currentSubtopic.isApi}
  717. weight = ${currentSubtopic.subtopicWeight}
  718. group = "${topicTitle}"
  719. title = "${currentSubtopic.japaneseSubtopicName}"
  720. fileName = "${subtopicFilename}"
  721. ${subtopicUrlParameter}
  722. +++\n
  723. `.substring(1);
  724.  
  725. let subtopicContent = currentSubtopic.subtopicContent.trim();
  726. let newSubtopicItem = "";
  727.  
  728. newSubtopicItem = newSubtopicItem + subtopicFrontMatter + subtopicContent;
  729.  
  730. if (topicTitle == "Version history" && subtopicTitle != "API Libraries") {
  731. console.log(`Version History individual versions shouldn't be saved to disk, so one such file has been skipped: ${chalk.red(subtopicTitle)}`);
  732. } else if (topicsConfig.blacklist.includes(subtopicFilename)) {
  733. console.log(`"${subtopicFilename}.md" has been skipped, since it should not be included. Check topics-config.js for details.`)
  734. } else {
  735. fs.writeFile(`content/${app}/${subtopicFilename}.ja.md`, newSubtopicItem, 'utf8', function(err) {
  736. if (err) {
  737. return console.log(chalk.red(err))
  738. }
  739. });
  740. }
  741. }
  742.  
  743. } catch (e) {
  744. console.error(chalk.red(e));
  745. }
  746.  
  747. }
  748. });
  749. });
  750. reportStatus(STATUS.WRITING_TO_FILE);
  751. reportStatus(STATUS.FINISH_CONVERT);
  752. }
  753.  
  754.  
  755. /**
  756. * Extract text and add semantic markers by converting to JSON
  757. * @param {string} lines - text string containing all API data
  758. */
  759. function extractTopics(lines) {
  760. return new Promise((resolve, reject) => {
  761.  
  762. // Use pointers to build object inside for loop
  763. let topics = [];
  764. let newTopic = {};
  765. let newTopicName = "";
  766. let newTopicContent = "";
  767. let newTopicWeight = 0;
  768.  
  769. let subtopics = {};
  770. let newSubtopic = {};
  771. let newSubtopicName = "";
  772. let newSubtopicContent = "";
  773. let newSubtopicWeight = 0;
  774. let recordingTopic = false;
  775. let recordingSubtopic = false;
  776.  
  777. let currentLineIsNewTopic = false;
  778. let currentLineIsNewSubtopic = false;
  779. let nextLineIsNewTopic = false;
  780. let nextLineIsNewSubtopic = false;
  781. let completed = false;
  782.  
  783. let headingsList = JSON.parse(fs.readFileSync('./api-data/headings-list.json', ''));
  784. let subheadingsList = JSON.parse(fs.readFileSync('./api-data/subheadings-list.json', ''));
  785.  
  786.  
  787. try {
  788.  
  789. // For each line
  790. for (let i = 0; i < lines.length; i++) {
  791.  
  792. let currentLine = lines[i];
  793. let nextIndex = i + 1;
  794. let nextLine = lines[nextIndex];
  795.  
  796. // Check "nextLine" status
  797. if (currentLine != null && nextLine != null) {
  798. currentLineIsNewTopic = currentLine.substring(0, 2) == "# ";
  799. currentLineIsNewSubtopic = currentLine.substring(0, 3) == "## ";
  800. nextLineIsNewTopic = nextLine.substring(0, 2) == "# ";
  801. nextLineIsNewSubtopic = nextLine.substring(0, 3) == "## ";
  802. }
  803.  
  804. /***************************
  805. * Check whether to capture
  806. ***************************/
  807. if (currentLineIsNewTopic) {
  808. let topicName = currentLine.substring(2);
  809. newTopicName = topicName;
  810. recordingTopic = true;
  811. }
  812.  
  813. if (nextLineIsNewSubtopic) {
  814. recordingTopic = false;
  815. }
  816.  
  817. if (currentLineIsNewSubtopic) {
  818. let subTopicName = currentLine.substring(3);
  819. newSubtopicName = subTopicName;
  820. recordingSubtopic = true;
  821. }
  822.  
  823. /******************************
  824. * Capture Lines (conditionally)
  825. ******************************/
  826. if ((recordingTopic && !currentLineIsNewSubtopic) || backlogTopLevelTopics.includes(newTopicName)) {
  827. newTopicContent += `${currentLine} \n`;
  828. }
  829.  
  830. if (recordingSubtopic && !currentLineIsNewTopic) {
  831. newSubtopicContent += `${currentLine} \n`;
  832. }
  833. /*****************
  834. * Record content
  835. *****************/
  836.  
  837. // Save SUBTOPIC
  838. if ((nextLineIsNewSubtopic || nextLineIsNewTopic) && newSubtopicName.length > 0) {
  839.  
  840. newSubtopic.japaneseSubtopicName = newSubtopicName;
  841. newSubtopic.subtopicName = subheadingsList.shift().toString();
  842. newSubtopic.subtopicContent = newSubtopicContent.trim();
  843. newSubtopic.subtopicWeight = newSubtopicWeight;
  844.  
  845. let keyName = newSubtopic.subtopicName.toString().toLowerCase().replace(/ /g, "-").replace(/\?/g, "");
  846.  
  847. // Only API items have the keyword "Role" as a field
  848. if (newSubtopicContent.includes("### メソッド \n")) {
  849. newSubtopic.isApi = true;
  850. } else {
  851. newSubtopic.isApi = false;
  852. }
  853.  
  854. if(keyName != null) {
  855. subtopics[keyName] = newSubtopic;
  856. }
  857.  
  858.  
  859. // Wipe data for next subtopic
  860. newSubtopic = {};
  861. newSubtopicName = "";
  862. newSubtopicContent = "";
  863. nextLineIsNewSubtopic = false;
  864. // Increment subtopic weight (don't reset)
  865. newSubtopicWeight++;
  866. }
  867.  
  868. // Save TOPIC.
  869. let isLastLine = (lines[i + 1] == null);
  870. if ((nextLineIsNewTopic || isLastLine) && i > 1) {
  871.  
  872. // Build newTopic to be returned
  873. newTopic.japaneseTopicName = newTopicName;
  874. newTopic.topicName = headingsList.shift();
  875. newTopic.subtopics = subtopics;
  876. newTopic.topicContent = newTopicContent.trim();
  877. newTopic.topicWeight = newTopicWeight;
  878. topics.push(newTopic);
  879.  
  880. // Reset newTopic and relevant fields
  881. newTopic = {};
  882. newTopicName = "";
  883. newSubtopic = {};
  884. newTopicContent = "";
  885. subtopics = {};
  886. nextLineIsNewTopic = false;
  887.  
  888. // Increment topic weight (don't reset)
  889. newTopicWeight++;
  890. }
  891. }
  892. } catch (err) {
  893. console.error(`${STATUS.ERROR_PARSE}. \n ${err}`);
  894. }
  895.  
  896. // Resolve
  897. resolve(topics);
  898.  
  899. // Reject
  900. reject(new Error(STATUS.ERROR_PARSE));
  901. });
  902. }
  903.  
  904. /**
  905. * Converts Backlog syntax STRING to valid Markdown
  906. * @param {string} data - path to raw data from file
  907. */
  908. function convertToMarkdownSyntax(data) {
  909. return new Promise((resolve, reject) => {
  910.  
  911. // Convert * to #
  912. let result = data.replace(/\*/g, '#');
  913.  
  914. // Convert {code} to ```
  915. result = result.replace(/({code})/g, '```');
  916. result = result.replace(/({\/code})/g, '```\n');
  917. // Convert [[a:b]] to [a](b)
  918. result = result.replace(/(\[\[)([^\:]+)\:(([^\s]+))(\]\])/g, '[$2]($3)');
  919. result = result.replace(/(&br;)/g, "<br>");
  920.  
  921. let lines = result.split('\n');
  922.  
  923. /**
  924. * CUSTOM HARD-CODED PARSERS FOR BACKLOG SYNTAX
  925. */
  926. // PARSE CODE KEYWORDS
  927. let codeKeywords = [
  928. "権限", "url", "メソッド", "scope"
  929. ];
  930. // PARSE RESPONSE EXAMPLES
  931. let responseExampleKeywords = [
  932. "レスポンス例"
  933. ];
  934. // URL PARAMETERS + QUERY PARAMETERS
  935. let formKeywords = [
  936. "URL パラメーター",
  937. "リクエストパラメーター",
  938. "レスポンス説明",
  939. "カスタム属性を指定した検索 (テキスト属性)",
  940. "カスタム属性を指定した検索 (数値属性)",
  941. "カスタム属性を指定した検索 (日付属性)",
  942. "カスタム属性を指定した検索 (リスト属性)"
  943. ];
  944. // FORM PARAMETERS
  945. let formParametersKeywords = [
  946. "リクエストパラメーター"
  947. ];
  948.  
  949. let keywords = codeKeywords.concat(responseExampleKeywords, formKeywords, formParametersKeywords);
  950.  
  951.  
  952. for (let i = 0; i < lines.length; i++) {
  953.  
  954. let prevLine = (i > 0) ? lines[i] : null;
  955. let currentLine = lines[i];
  956. let lineContent = currentLine.substring(2).toLowerCase().trim();
  957. let nextLine = lines[i + 1];
  958. let nextNextLine = lines[i + 2];
  959.  
  960.  
  961. // Set section headers to <h4>
  962. if (keywords.includes(lineContent)) {
  963. if (nextLine.length > 0) {
  964. // If this section has content, trim and markdownify
  965. lines[i] = `### ${currentLine.substring(2).trim()}`;
  966. } else {
  967. // Otherwise, remove array entries to keep markdown files clean
  968. lines.splice(i - 1, 3, "");
  969. i -= 2;
  970. }
  971. }
  972.  
  973.  
  974. if (codeKeywords.includes(lineContent) && nextLine.length > 0) {
  975.  
  976. lines.splice(i + 1, 0, `\`\`\``);
  977.  
  978. // Account for multiple
  979.  
  980. let offset = 2;
  981.  
  982. while (lines[i + offset].length > 0) {
  983. offset += 1;
  984. }
  985.  
  986. lines.splice(i + offset, 0, `\`\`\``);
  987. }
  988.  
  989. if (responseExampleKeywords.includes(lineContent) && nextLine.length > 0) {
  990. // Restructure
  991. lines.splice(i + 1, 0, `#### ステータスライン / レスポンスヘッダ`);
  992.  
  993. // Account for potential multiple lines
  994.  
  995. let offset = 5;
  996. while (lines[i + offset] != '```') {
  997. offset += 1;
  998. }
  999. lines.splice(i + offset + 1, 0, `#### レスポンスボディ`);
  1000. }
  1001.  
  1002.  
  1003. if (formKeywords.includes(lineContent) && nextLine.length > 0) {
  1004. lines.splice(i + 1, 0, 'パラメーター名 | 型 | 内容');
  1005. lines.splice(i + 2, 0, '---|---|---');
  1006. // If there's a table
  1007.  
  1008. let offset = 3;
  1009.  
  1010. // while the first character is "|", trim to make valid syntax
  1011. while (lines[i + offset].substring(0, 1) == "|") {
  1012. lines[i + offset] = lines[i + offset].slice(1, -1).trim();
  1013. offset += 1;
  1014. }
  1015. }
  1016.  
  1017. if (formParametersKeywords.includes(lineContent) && nextLine.length > 0) {
  1018.  
  1019. lines.splice(i + 1, 0, `\`\`\``);
  1020. lines.splice(i + 3, 0, `\`\`\``);
  1021. lines.splice(i + 4, 0, ``);
  1022.  
  1023. if (lines[i + 5].substring(0, 1) == "|") {
  1024. // Remove first and last | character
  1025.  
  1026. let offset = 5;
  1027.  
  1028. // wipe lines until you hit a blank line
  1029. while (lines[i + offset].length != 0) {
  1030. lines[i + offset] = lines[i + offset].slice(1, -1).trim();
  1031. offset += 1;
  1032. }
  1033. lines.splice(i + 6, 0, `\-\-\-\- | \-\-\-\- | \-\-\-\-`);
  1034. }
  1035. }
  1036.  
  1037. }
  1038.  
  1039. // Reassemble
  1040. result = lines.join('\n');
  1041.  
  1042. // Return markdown-ified data
  1043. if (result.length > 1) {
  1044. resolve(result);
  1045. } else {
  1046. reject(new Error(STATUS.ERROR_PARSE));
  1047. }
  1048. });
  1049. }
  1050.  
  1051. /*
  1052. * This script converts Japanese API data from Backlog Syntax to Markdown.
  1053. * It can also output to Markdown and JSON.
  1054. */
  1055.  
  1056. // Lib Imports
  1057. const fs = require('fs');
  1058. const path = require('path');
  1059. const chalk = require('chalk');
  1060. const readline = require('readline');
  1061.  
  1062. // App configuration imports
  1063. const backlogConfig = require('./backlog-config').en;
  1064. const backlogTopLevelTopics = backlogConfig.topLevelTopics;
  1065. const topicsConfig = require('./topics-config');
  1066.  
  1067. // CLI arguments
  1068. const inputPathArgument = process.argv[2];
  1069.  
  1070. // bwiki libs
  1071. const STATUS = require('./status-codes');
  1072. const reportStatus = STATUS.reportStatus;
  1073.  
  1074. // Readline
  1075. let rl;
  1076.  
  1077. let headingsList = [];
  1078. let subheadingsList = [];
  1079.  
  1080. fs.readFile(inputPathArgument, 'utf8', (err, data) => {
  1081. generateHeadingsList(data);
  1082. });
  1083.  
  1084. /**
  1085. * Extracts data, adds Hugo-specific front-matter
  1086. * @param {string} data - text string containing all API data
  1087. */
  1088. function generateHeadingsList(data) {
  1089. reportStatus(STATUS.GENERATING_TRANSLATION_MAP);
  1090. convertToMarkdownSyntax(data)
  1091. .then((markdownData) => {
  1092.  
  1093. let lines = markdownData.split('\n');
  1094.  
  1095. extractTopics(lines).then((topics) => {
  1096.  
  1097. // For each topic
  1098. for (let topicNumber in topics) {
  1099.  
  1100. let currentTopic = topics[topicNumber];
  1101. let topicTitle = currentTopic.topicName;
  1102.  
  1103. headingsList.push(topicTitle);
  1104.  
  1105. for (let subtopicNumber in currentTopic.subtopics) {
  1106.  
  1107. let currentSubtopic = currentTopic.subtopics[subtopicNumber];
  1108. let subtopicTitle = currentSubtopic.subtopicName;
  1109. let subtopicFilename =
  1110. subtopicTitle
  1111. .toLowerCase()
  1112. .replace(/\s/g, "-")
  1113. .replace(/\?/g, "")
  1114. .replace(/\//g, "-")
  1115. .replace(/\./g, "")
  1116. .replace(/\(/g, "")
  1117. .replace(/\)/g, "");
  1118.  
  1119. subheadingsList.push(subtopicTitle);
  1120. }
  1121. }
  1122. fs.writeFile('api-data/headings-list.json', JSON.stringify(headingsList), 'utf8');
  1123. fs.writeFile('api-data/subheadings-list.json', JSON.stringify(subheadingsList), 'utf8');
  1124. });
  1125. });
  1126. reportStatus(STATUS.GENERATING_TRANSLATION_MAP_DONE);
  1127. reportStatus(STATUS.FINISH_CONVERT);
  1128. }
  1129.  
  1130.  
  1131. /**
  1132. * Extract text and add semantic markers by converting to JSON
  1133. * @param {string} lines - text string containing all API data
  1134. */
  1135. function extractTopics(lines) {
  1136. return new Promise((resolve, reject) => {
  1137.  
  1138. // Use pointers to build object inside for loop
  1139. let topics = [];
  1140. let newTopic = {};
  1141. let newTopicName = "";
  1142. let newTopicContent = "";
  1143. let newTopicWeight = 0;
  1144.  
  1145. let subtopics = {};
  1146. let newSubtopic = {};
  1147. let newSubtopicName = "";
  1148. let newSubtopicContent = "";
  1149. let newSubtopicWeight = 0;
  1150. let recordingTopic = false;
  1151. let recordingSubtopic = false;
  1152.  
  1153. let currentLineIsNewTopic = false;
  1154. let currentLineIsNewSubtopic = false;
  1155. let nextLineIsNewTopic = false;
  1156. let nextLineIsNewSubtopic = false;
  1157. let completed = false;
  1158.  
  1159. // List of top-level topics that get their own section
  1160. let backlogTopLevelTopics = backlogConfig.topLevelTopics;
  1161.  
  1162. try {
  1163.  
  1164. // For each line
  1165. for (let i = 0; i < lines.length; i++) {
  1166.  
  1167. let currentLine = lines[i];
  1168. let nextIndex = i + 1;
  1169. let nextLine = lines[nextIndex];
  1170.  
  1171. // Check "nextLine" status
  1172. if (currentLine != null && nextLine != null) {
  1173. currentLineIsNewTopic = currentLine.substring(0, 2) == "# ";
  1174. currentLineIsNewSubtopic = currentLine.substring(0, 3) == "## ";
  1175. nextLineIsNewTopic = nextLine.substring(0, 2) == "# ";
  1176. nextLineIsNewSubtopic = nextLine.substring(0, 3) == "## ";
  1177. }
  1178.  
  1179. /***************************
  1180. * Check whether to capture
  1181. ***************************/
  1182. if (currentLineIsNewTopic) {
  1183. let topicName = currentLine.substring(2);
  1184. newTopicName = topicName;
  1185. recordingTopic = true;
  1186. }
  1187.  
  1188. if(nextLineIsNewSubtopic) {
  1189. recordingTopic = false;
  1190. }
  1191.  
  1192. if (currentLineIsNewSubtopic) {
  1193. let subTopicName = currentLine.substring(3);
  1194. newSubtopicName = subTopicName;
  1195. recordingSubtopic = true;
  1196. }
  1197.  
  1198. /******************************
  1199. * Capture Lines (conditionally)
  1200. ******************************/
  1201. if ((recordingTopic && !currentLineIsNewSubtopic) || backlogTopLevelTopics.includes(newTopicName)) {
  1202. newTopicContent += `${currentLine} \n`;
  1203. }
  1204.  
  1205. if (recordingSubtopic && !currentLineIsNewTopic) {
  1206. newSubtopicContent += `${currentLine} \n`;
  1207. }
  1208. /*****************
  1209. * Record content
  1210. *****************/
  1211.  
  1212.  
  1213. // Save TOPIC.
  1214. let isLastLine = (lines[i+1] == null);
  1215. if ((nextLineIsNewTopic || isLastLine ) && i > 1) {
  1216.  
  1217. // Build newTopic to be returned
  1218. newTopic.topicName = newTopicName;
  1219. newTopic.subtopics = subtopics;
  1220. newTopic.topicContent = newTopicContent.trim();
  1221. newTopic.topicWeight = newTopicWeight;
  1222. topics.push(newTopic);
  1223.  
  1224. // Reset newTopic and relevant fields
  1225. newTopic = {};
  1226. newTopicName = "";
  1227. newSubtopic = {};
  1228. newTopicContent = "";
  1229. subtopics = {};
  1230. nextLineIsNewTopic = false;
  1231.  
  1232. // Increment topic weight (don't reset)
  1233. newTopicWeight++;
  1234. }
  1235.  
  1236. // Save SUBTOPIC
  1237. if (nextLineIsNewSubtopic && newSubtopicName.length > 0) {
  1238.  
  1239. // build and record subtopic as property of newTopic
  1240. let keyName = newSubtopicName.toLowerCase().replace(/ /g, "-").replace(/\?/g, "");
  1241. newSubtopic.subtopicName = newSubtopicName;
  1242. newSubtopic.subtopicContent = newSubtopicContent.trim();
  1243. newSubtopic.subtopicWeight = newSubtopicWeight;
  1244.  
  1245. // Only API items have the keyword "Role" as a field
  1246. if (newSubtopicContent.includes("### Method \n")) {
  1247. newSubtopic.isApi = true;
  1248. } else {
  1249. newSubtopic.isApi = false;
  1250. }
  1251.  
  1252. subtopics[keyName.toString()] = newSubtopic;
  1253.  
  1254. // Wipe data for next subtopic
  1255. newSubtopic = {};
  1256. newSubtopicName = "";
  1257. newSubtopicContent = "";
  1258. nextLineIsNewSubtopic = false;
  1259. // Increment subtopic weight (don't reset)
  1260. newSubtopicWeight++;
  1261. }
  1262. }
  1263. } catch (err) {
  1264. console.error(`${STATUS.ERROR_PARSE}. \n ${err}`);
  1265. }
  1266.  
  1267. // Resolve
  1268. resolve(topics);
  1269.  
  1270. // Reject
  1271. reject(new Error(STATUS.ERROR_PARSE));
  1272. });
  1273. }
  1274.  
  1275. /**
  1276. * Converts Backlog syntax STRING to valid Markdown
  1277. * @param {string} data - path to raw data from file
  1278. */
  1279. function convertToMarkdownSyntax(data) {
  1280. return new Promise((resolve, reject) => {
  1281.  
  1282. // Convert * to #
  1283. let result = data.replace(/\*/g, '#');
  1284. try {
  1285.  
  1286. // Convert {code} to ```
  1287. result = result.replace(/({code})/g, '```');
  1288. result = result.replace(/({\/code})/g, '```\n');
  1289. // Convert [[a:b]] to [a](b)
  1290. result = result.replace(/(\[\[)([^\:]+)\:(([^\s]+))(\]\])/g, '[$2]($3)');
  1291. result = result.replace(/(&br;)/g, "<br>");
  1292.  
  1293. } catch (e) {
  1294. console.error("Error while performing regex: " + e);
  1295. }
  1296.  
  1297.  
  1298. let lines = result.split('\n');
  1299.  
  1300.  
  1301. /**
  1302. * CUSTOM HARD-CODED PARSERS FOR BACKLOG SYNTAX
  1303. */
  1304. // PARSE CODE KEYWORDS
  1305. let codeKeywords = [
  1306. "role", "url", "method", "scope"
  1307. ];
  1308. // PARSE RESPONSE EXAMPLES
  1309. let responseExampleKeywords = [
  1310. "response example"
  1311. ];
  1312. // URL PARAMETERS + QUERY PARAMETERS
  1313. let formKeywords = [
  1314. "url parameters",
  1315. "query parameters",
  1316. "response description",
  1317. "custom fields (text)",
  1318. "custom fields (numeric)",
  1319. "custom fields (date)",
  1320. "custom fields (list)"
  1321. ];
  1322. // FORM PARAMETERS
  1323. let formParametersKeywords = [
  1324. "form parameters"
  1325. ];
  1326.  
  1327. let keywords = codeKeywords.concat(responseExampleKeywords, formKeywords, formParametersKeywords);
  1328.  
  1329. for (let i = 0; i < lines.length; i++) {
  1330.  
  1331. let prevLine = (i > 0) ? lines[i] : null;
  1332. let currentLine = lines[i];
  1333. let lineContent = currentLine.substring(2).toLowerCase().trim();
  1334. let nextLine = lines[i + 1];
  1335. let nextNextLine = lines[i + 2];
  1336.  
  1337. // Set section headers to <h4>
  1338. if (keywords.includes(lineContent)) {
  1339. if (nextLine.length > 0) {
  1340. // If this section has content, trim and markdownify
  1341. lines[i] = `### ${currentLine.substring(2).trim()}`;
  1342. } else {
  1343. // Otherwise, remove array entries to keep markdown files clean
  1344. lines.splice(i - 1, 3, "");
  1345. i -= 2;
  1346. }
  1347. }
  1348.  
  1349. if (codeKeywords.includes(lineContent) && nextLine.length > 0) {
  1350.  
  1351. lines.splice(i + 1, 0, `\`\`\``);
  1352.  
  1353. // Account for multiple
  1354. let offset = 2;
  1355.  
  1356. while (lines[i + offset].length > 0) {
  1357. offset += 1;
  1358. }
  1359.  
  1360. lines.splice(i + offset, 0, `\`\`\``);
  1361. }
  1362.  
  1363. if (responseExampleKeywords.includes(lineContent) && nextLine.length > 0) {
  1364. // Restructure
  1365. lines.splice(i + 1, 0, `#### Status Line / Response Header`);
  1366.  
  1367. // Account for potential multiple lines
  1368.  
  1369. let offset = 5;
  1370. while (lines[i + offset] != '```') {
  1371. offset += 1;
  1372. }
  1373. lines.splice(i + offset + 1, 0, `#### Response Body`);
  1374. }
  1375.  
  1376.  
  1377. if (formKeywords.includes(lineContent) && nextLine.length > 0) {
  1378.  
  1379. // If there's a table
  1380. lines.splice(i + 1, 0, 'Parameter Name | Type | Description');
  1381. lines.splice(i + 2, 0, '---|---|---');
  1382.  
  1383. let offset = 3;
  1384.  
  1385. // while the first character is "|", trim to make valid syntax
  1386. while (lines[i + offset].substring(0, 1) == "|") {
  1387. lines[i + offset] = lines[i + offset].slice(1, -1).trim();
  1388. offset += 1;
  1389. }
  1390. }
  1391.  
  1392. if (formParametersKeywords.includes(lineContent) && nextLine.length > 0) {
  1393.  
  1394. lines.splice(i + 1, 0, `\`\`\``);
  1395. lines.splice(i + 3, 0, `\`\`\``);
  1396. lines.splice(i + 4, 0, ``);
  1397.  
  1398. if (lines[i + 5].substring(0, 1) == "|") {
  1399. // Remove first and last | character
  1400.  
  1401. let offset = 5;
  1402.  
  1403. // wipe lines until you hit a blank line
  1404. while (lines[i + offset].length != 0) {
  1405. lines[i + offset] = lines[i + offset].slice(1, -1).trim();
  1406. offset += 1;
  1407. }
  1408. lines.splice(i + 6, 0, `\-\-\-\- | \-\-\-\- | \-\-\-\-`);
  1409. }
  1410. }
  1411.  
  1412. }
  1413.  
  1414.  
  1415. // Reassemble
  1416. result = lines.join('\n');
  1417.  
  1418. // Return markdown-ified data
  1419. if (result.length > 1) {
  1420. resolve(result);
  1421. } else {
  1422. reject(new Error(STATUS.ERROR_PARSE));
  1423. }
  1424. });
  1425. }
  1426.  
  1427. // backlog-config
  1428.  
  1429. let backlogConfig = {};
  1430. backlogConfig.en = {
  1431. // These topics are in the sidebar
  1432. topLevelTopics: [
  1433. "Version history",
  1434. "Backlog API Overview",
  1435. "Error Response",
  1436. "Authentication & Authorization"
  1437. ],
  1438. urlMaps: {
  1439. "backlog-api-overview": "/docs/backlog/",
  1440. "authentication-&-authorization": "/docs/backlog/auth",
  1441. "error-response": "/docs/backlog/error-response",
  1442. "version-history": "/docs/backlog/changes",
  1443. "oauth-20" : "/docs/backlog/api/2/oauth2"
  1444. }
  1445. };
  1446.  
  1447. backlogConfig.ja = {
  1448. topLevelTopics: [
  1449. "変更履歴",
  1450. "Backlog API とは",
  1451. "エラーレスポンス",
  1452. "認証と認可"
  1453. ],
  1454. urlMaps: {
  1455. "backlog-api-overview": "/ja/docs/backlog/",
  1456. "authentication-&-authorization": "/ja/docs/backlog/auth",
  1457. "error-response": "/ja/docs/backlog/error-response",
  1458. "version-history": "/ja/docs/backlog/changes",
  1459. "oauth-20" : "/ja/docs/backlog/api/1/oauth2"
  1460. }
  1461. }
  1462.  
  1463. module.exports = backlogConfig;
  1464.  
  1465. // STATUS CODES
  1466. const chalk = require('chalk');
  1467. const outputFormat = process.argv[2].toLowerCase();
  1468. const inputPathArgument = process.argv[3];
  1469. const outputPathArgument = process.argv[4];
  1470.  
  1471. let STATUS = {
  1472. BEGIN_MARKDOWN_CONVERT: "Converting to Markdown...",
  1473. BEGIN_MARKDOWN_INTERIM_CONVERT: "Converting to Markdown first...",
  1474. BEGIN_JSON_CONVERT: "Converting to JSON...",
  1475.  
  1476. STARTING_HUGO: `Beginning conversion to ${outputFormat.toUpperCase()}...\n`,
  1477. BEGIN_HUGO_BUILD: "Adding Hugo Front Matter & saving to disk...",
  1478.  
  1479. FINISH_CONVERT: "Success!\n",
  1480.  
  1481. ERROR_PARSE: "Error: couldn't parse input. Please check syntax and try again. \n",
  1482. WRITING_TO_FILE: `SAVED: "${outputPathArgument}".\n`,
  1483.  
  1484. // For generate-translation-map
  1485. GENERATING_TRANSLATION_MAP: "Generating headings list for use in Japanese translations...\n\n",
  1486. GENERATING_TRANSLATION_MAP_DONE: "Done. \nCheck api-data/ for headings-list.json and subheadings-list.json files. \nIf you want to generate Japanese Markdown content, run `node backlog-syntax-converter-jp.js hugo /path/to/output/folder`"
  1487. }
  1488.  
  1489. // Change status messages for Hugo
  1490. STATUS.WRITING_TO_FILE = outputFormat == "hugo" ? "Files saved in Hugo directories." : STATUS.WRITING_TO_FILE;
  1491.  
  1492. // Helper function function reportStatus(message) {
  1493. STATUS.reportStatus = function(message) {
  1494. console.log(chalk.bold(message));
  1495. }
  1496.  
  1497. module.exports = STATUS;
  1498.  
  1499. // topics-config
  1500.  
  1501. let topicsConfig = {
  1502. blacklist: [
  1503. "200-2014-07-07",
  1504. "git",
  1505. "group",
  1506. "issue",
  1507. "notification",
  1508. "oauth-2.0",
  1509. "priority",
  1510. "project",
  1511. "pull-request",
  1512. "resolution",
  1513. "space",
  1514. "star",
  1515. "status",
  1516. "users",
  1517. "watching",
  1518. "wiki",
  1519.  
  1520. "oauth-20",
  1521. "スペース",
  1522. "ユーザー",
  1523. "グループ",
  1524. "状態",
  1525. "完了理由",
  1526. "優先度",
  1527. "プロジェクト",
  1528. "課題",
  1529. "Wiki",
  1530. "スター",
  1531. "お知らせ",
  1532. "Git",
  1533. "プルリクエスト",
  1534. "ウォッチ",
  1535. ]
  1536. };
  1537.  
  1538. module.exports = topicsConfig;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement