{"version":3,"file":"generateRule.cjs","names":["fs","camelCase","existsSync","resolve","open"],"sources":["../src/bin/generateRule.js"],"sourcesContent":["/* eslint-disable no-console -- CLI */\n/**\n * @example\n * ```shell\n * pnpm run create-rule my-new-rule -- --recommended\n * ```\n */\n\nimport camelCase from 'camelcase';\nimport {\n  existsSync,\n} from 'node:fs';\nimport fs from 'node:fs/promises';\nimport {\n  resolve,\n} from 'node:path';\nimport open from 'open-editor';\n\n// Todo: Would ideally have prompts, e.g., to ask for whether\n//   type was problem/layout, etc.\n\nconst [\n  , , ruleName,\n  ...options\n] = process.argv;\n\nconst recommended = options.includes('--recommended');\n\n(async () => {\n  if (!ruleName) {\n    console.error('Please supply a rule name');\n\n    return;\n  }\n\n  if ((/[A-Z]/v).test(ruleName)) {\n    console.error('Please ensure the rule has no capital letters');\n\n    return;\n  }\n\n  const ruleNamesPath = './test/rules/ruleNames.json';\n  const ruleNames = JSON.parse(await fs.readFile(\n    // eslint-disable-next-line unicorn/prefer-json-parse-buffer -- TypeScript\n    ruleNamesPath, 'utf8',\n  ));\n  if (!ruleNames.includes(ruleName)) {\n    ruleNames.push(ruleName);\n    ruleNames.sort();\n  }\n\n  await fs.writeFile(ruleNamesPath, JSON.stringify(ruleNames, null, 2) + '\\n');\n  console.log('ruleNames', ruleNames);\n\n  const ruleTemplate = `import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n  context,\n  utils,\n}) => {\n  // Rule here\n}, {\n  iterateAllJsdocs: true,\n  meta: {\n    docs: {\n      description: '',\n      url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/${ruleName}.md#repos-sticky-header',\n    },\n    schema: [\n      {\n        additionalProperties: false,\n        properties: {\n          // Option properties here (or remove the object)\n        },\n        type: 'object',\n      },\n    ],\n    type: 'suggestion',\n  },\n});\n`;\n\n  const camelCasedRuleName = camelCase(ruleName);\n\n  const rulePath = `./src/rules/${camelCasedRuleName}.js`;\n\n  if (!existsSync(rulePath)) {\n    await fs.writeFile(rulePath, ruleTemplate);\n  }\n\n  const ruleTestTemplate = `export default {\n  invalid: [\n    {\n      code: \\`\n      \\`,\n      errors: [\n        {\n          line: 2,\n          message: '',\n        },\n      ],\n    },\n  ],\n  valid: [\n    {\n      code: \\`\n      \\`,\n    },\n  ],\n};\n`;\n\n  const ruleTestPath = `./test/rules/assertions/${camelCasedRuleName}.js`;\n  if (!existsSync(ruleTestPath)) {\n    await fs.writeFile(ruleTestPath, ruleTestTemplate);\n  }\n\n  const ruleReadmeTemplate = `# \\`${ruleName}\\`\n\n## Options\n\n{\"gitdown\": \"options\"}\n\n|||\n|---|---|\n|Context|everywhere|\n|Tags|\\`\\`|\n|Recommended|${recommended ? 'true' : 'false'}|\n|Settings||\n|Options||\n\n## Failing examples\n\n<!-- assertions-failing ${camelCasedRuleName} -->\n\n## Passing examples\n\n<!-- assertions-passing ${camelCasedRuleName} -->\n`;\n\n  const ruleReadmePath = `./.README/rules/${ruleName}.md`;\n  if (!existsSync(ruleReadmePath)) {\n    await fs.writeFile(ruleReadmePath, ruleReadmeTemplate);\n  }\n\n  /**\n   * @param {object} cfg\n   * @param {string} cfg.path\n   * @param {RegExp} cfg.oldRegex\n   * @param {string} cfg.checkName\n   * @param {string} cfg.newLine\n   * @param {boolean} [cfg.oldIsCamel]\n   * @returns {Promise<void>}\n   */\n  const replaceInOrder = async ({\n    checkName,\n    newLine,\n    oldIsCamel,\n    oldRegex,\n    path,\n  }) => {\n    /**\n     * @typedef {number} Integer\n     */\n    /**\n     * @typedef {{\n     *   matchedLine: string,\n     *   offset: Integer,\n     *   oldRule: string,\n     * }} OffsetInfo\n     */\n    /**\n     * @type {OffsetInfo[]}\n     */\n    const offsets = [];\n\n    let readme = await fs.readFile(path, 'utf8');\n    readme.replace(\n      oldRegex,\n      /**\n       * @param {string} matchedLine\n       * @param {string} n1\n       * @param {Integer} offset\n       * @param {string} str\n       * @param {object} groups\n       * @param {string} groups.oldRule\n       * @returns {string}\n       */\n      (matchedLine, n1, offset, str, {\n        oldRule,\n      }) => {\n        offsets.push({\n          matchedLine,\n          offset,\n          oldRule,\n        });\n\n        return matchedLine;\n      },\n    );\n\n    offsets.sort(({\n      oldRule,\n    }, {\n      oldRule: oldRuleB,\n    }) => {\n      return oldRule < oldRuleB ? -1 : (oldRule > oldRuleB ? 1 : 0);\n    });\n\n    let alreadyIncluded = false;\n    const itemIndex = offsets.findIndex(({\n      oldRule,\n    }) => {\n      alreadyIncluded ||= oldIsCamel ? camelCasedRuleName === oldRule : ruleName === oldRule;\n\n      return oldIsCamel ? camelCasedRuleName < oldRule : ruleName < oldRule;\n    });\n    let item = itemIndex !== undefined && offsets[itemIndex];\n    if (item && itemIndex === 0 &&\n\n      // This property would not always be sufficient but in this case it is.\n      oldIsCamel\n    ) {\n      item.offset = 0;\n    }\n\n    if (!item) {\n      item = /** @type {OffsetInfo} */ (offsets.pop());\n      item.offset += item.matchedLine.length;\n    }\n\n    if (alreadyIncluded) {\n      console.log(`Rule name is already present in ${checkName}.`);\n    } else {\n      readme = readme.slice(0, item.offset) +\n                (item.offset ? '\\n' : '') +\n                newLine +\n                (item.offset ? '' : '\\n') +\n                readme.slice(item.offset);\n\n      await fs.writeFile(path, readme);\n    }\n  };\n\n  // await replaceInOrder({\n  //   checkName: 'README',\n  //   newLine: `{\"gitdown\": \"include\", \"file\": \"./rules/${ruleName}.md\"}`,\n  //   oldRegex: /\\n\\{\"gitdown\": \"include\", \"file\": \".\\/rules\\/(?<oldRule>[^.]*).md\"\\}/gv,\n  //   path: './.README/README.md',\n  // });\n\n  await replaceInOrder({\n    checkName: 'index import',\n    newLine: `import ${camelCasedRuleName} from './rules/${camelCasedRuleName}.js';`,\n    oldIsCamel: true,\n    oldRegex: /\\nimport (?<oldRule>[^ ]*) from '.\\/rules\\/\\1\\.js';/gv,\n    path: './src/index-cjs.js',\n  });\n\n  await replaceInOrder({\n    checkName: 'index recommended',\n    newLine: `${' '.repeat(6)}'jsdoc/${ruleName}': ${recommended ? 'warnOrError' : '\\'off\\''},`,\n    oldRegex: /\\n\\s{6}'jsdoc\\/(?<oldRule>[^']*)': .*?,/gv,\n    path: './src/index-cjs.js',\n  });\n\n  await replaceInOrder({\n    checkName: 'index rules',\n    newLine: `${' '.repeat(2)}'${ruleName}': ${camelCasedRuleName},`,\n    oldRegex: /\\n\\s{2}'(?<oldRule>[^']*)': [^,]*,/gv,\n    path: './src/index-cjs.js',\n  });\n\n  await import('./buildEntryFileForTS.js');\n\n  await import('./generateDocs.js');\n\n  /*\n  console.log('Paths to open for further editing\\n');\n  console.log(`open ${ruleReadmePath}`);\n  console.log(`open ${rulePath}`);\n  console.log(`open ${ruleTestPath}\\n`);\n  */\n\n  // Set chdir as somehow still in operation from other test\n  process.chdir(resolve(import.meta.dirname, '../../'));\n  await open([\n    // Could even add editor line column numbers like `${rulePath}:1:1`\n    ruleReadmePath,\n    ruleTestPath,\n    rulePath,\n  ]);\n})();\n"],"mappings":"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","ignoreList":[]}