index.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /**
  2. * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
  3. * SPDX-License-Identifier: MIT
  4. */
  5. const fs = require("fs");
  6. const path = require("path");
  7. const ig = require("ignore")();
  8. const ignoreFile = fs.readFileSync(path.join(__dirname, "../../../.gitignore"), {
  9. encoding: "utf-8",
  10. });
  11. ig.add(ignoreFile);
  12. // ignore cli install demos
  13. ig.add(['.next', 'doc_build']);
  14. const src = path.resolve(__dirname, '../../../');
  15. const header = ` Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
  16. SPDX-License-Identifier: MIT`;
  17. const bashHeader = `#!/usr/bin/env`;
  18. const rushPreHeader = `// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.`;
  19. /**
  20. * Add License Header to all files in the folder
  21. * @param {string} targetDir - target folder path (absolute path)
  22. * @param {string} licenseContent - License content to be added (plain text)
  23. * @param {object} options - configuration items
  24. * @param {string[]} [options.includeExts] - file extensions to be processed (such as ['.js', '.ts']), all text files are processed by default
  25. * @param {string[]} [options.excludeDirs] - directories to be excluded (such as ['node_modules', 'dist'])
  26. * @param {string} [options.commentLinePrefix] - comment prefix (such as '// ' or '/* '), comment format is not added by default
  27. * @param {boolean} [options.force] - whether to force overwrite (re-add even if there is already a license), default false
  28. */
  29. function addLicenseHeader(targetDir, licenseContent, options = {}) {
  30. const {
  31. includeExts = [".js", ".ts", ".mjs", ".cjs", ".html", ".css", ".scss"],
  32. commentLinePrefix = "// ", // default by js
  33. commentPrefix,
  34. commentSuffix,
  35. force = false,
  36. } = options;
  37. const licensedText =
  38. (commentPrefix ? commentPrefix + "\n" : "") +
  39. licenseContent
  40. .split("\n")
  41. .map((line) => commentLinePrefix + line)
  42. .join("\n") +
  43. (commentSuffix ? "\n" + commentSuffix : "") +
  44. "\n\n";
  45. function traverseDir(currentDir) {
  46. const entries = fs.readdirSync(currentDir, { withFileTypes: true });
  47. for (const entry of entries) {
  48. const fullPath = path.join(currentDir, entry.name);
  49. if (
  50. entry.isDirectory() &&
  51. ig.ignores(path.relative(targetDir, fullPath))
  52. ) {
  53. continue;
  54. }
  55. if (entry.isDirectory()) {
  56. traverseDir(fullPath);
  57. } else {
  58. processFile(fullPath);
  59. }
  60. }
  61. }
  62. function processFile(filePath) {
  63. const ext = path.extname(filePath).toLowerCase();
  64. if (includeExts.length > 0 && !includeExts.includes(ext)) {
  65. return;
  66. }
  67. try {
  68. const originalContent = fs.readFileSync(filePath, "utf8");
  69. // Check if the license already exists (simple match at the beginning)
  70. if (!force && (originalContent.startsWith(licensedText.trim()) || originalContent.startsWith(bashHeader.trim()) || originalContent.startsWith(rushPreHeader.trim()))) {
  71. return;
  72. }
  73. let newContent = originalContent;
  74. const shebangMatch = originalContent.match(/^#!.*\n/);
  75. if (shebangMatch) {
  76. newContent =
  77. shebangMatch[0] +
  78. licensedText +
  79. originalContent.replace(shebangMatch[0], "");
  80. } else {
  81. newContent = licensedText + originalContent;
  82. }
  83. fs.writeFileSync(filePath, newContent, "utf8");
  84. console.log(`[Success] License added: ${filePath}, please manually upload the locally modified file`);
  85. } catch (err) {
  86. console.error(`[ERROR] Failed to process file ${filePath}:`, err.message);
  87. }
  88. }
  89. if (fs.existsSync(targetDir) && fs.statSync(targetDir).isDirectory()) {
  90. traverseDir(targetDir);
  91. console.log("License Header add successfully");
  92. } else {
  93. console.error("Error: The destination path is not a valid folder");
  94. }
  95. }
  96. addLicenseHeader(
  97. src,
  98. header,
  99. {
  100. includeExts: ['.js', '.ts', '.tsx', '.jsx', '.mjs', '.cjs', '.scss', '.less', '.prisma', '.styl', '.css'],
  101. commentPrefix: '/**',
  102. commentLinePrefix: ' *',
  103. commentSuffix: ' */',
  104. force: false
  105. }
  106. );
  107. addLicenseHeader(
  108. src,
  109. header,
  110. {
  111. includeExts: ['.sh'],
  112. commentLinePrefix: '# ',
  113. force: false
  114. }
  115. );