index.js 4.3 KB

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