build.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. import fs from 'fs';
  2. import path from 'path';
  3. import TurndownService from 'turndown';
  4. // Read package.json to get current version
  5. const packageJson = JSON.parse( fs.readFileSync( 'package.json', 'utf8' ) );
  6. const version = packageJson.version;
  7. // Read TSL specification
  8. const tslSpec = fs.readFileSync( 'docs/TSL.md', 'utf8' );
  9. // Setup Turndown for HTML to Markdown conversion
  10. const turndown = new TurndownService( {
  11. headingStyle: 'atx',
  12. codeBlockStyle: 'fenced'
  13. } );
  14. // Code blocks - assume JavaScript
  15. turndown.addRule( 'codeBlocks', {
  16. filter: [ 'pre' ],
  17. replacement: function ( content ) {
  18. return '\n```js\n' + content.trim() + '\n```\n';
  19. }
  20. } );
  21. // Simplify member/method headings: ".[name](#name)" -> ".name"
  22. turndown.addRule( 'memberHeadings', {
  23. filter: function ( node ) {
  24. return node.tagName === 'H3' && node.classList.contains( 'name' );
  25. },
  26. replacement: function ( content, node ) {
  27. // Extract the clean signature without anchor links
  28. let text = node.textContent.trim();
  29. // Clean up extra whitespace
  30. text = text.replace( /\s+/g, ' ' );
  31. return '\n### ' + text + '\n';
  32. }
  33. } );
  34. // Simplify type signatures in spans
  35. turndown.addRule( 'typeSignatures', {
  36. filter: function ( node ) {
  37. return node.tagName === 'SPAN' && node.classList.contains( 'type-signature' );
  38. },
  39. replacement: function ( content, node ) {
  40. // Just return the text content without links
  41. return ' : ' + node.textContent.trim();
  42. }
  43. } );
  44. // Clean up inheritance chain (p.inheritance)
  45. turndown.addRule( 'inheritance', {
  46. filter: function ( node ) {
  47. return node.tagName === 'P' && node.classList.contains( 'inheritance' );
  48. },
  49. replacement: function ( content, node ) {
  50. // Convert to simple text chain
  51. const text = node.textContent.trim();
  52. if ( ! text ) return '';
  53. return '*Inheritance: ' + text + '*\n\n';
  54. }
  55. } );
  56. // Root llms.txt - simple pointer file
  57. const rootLlms = `# Three.js
  58. > Three.js is a cross-browser JavaScript library for creating 3D graphics using WebGL and WebGPU.
  59. See the full documentation for LLMs at: https://threejs.org/docs/llms.txt
  60. For complete inline documentation including TSL: https://threejs.org/docs/llms-full.txt
  61. `;
  62. // Docs llms.txt - main documentation index with instructions
  63. const docsLlms = `# Three.js
  64. > Three.js is a cross-browser JavaScript library for creating 3D graphics using WebGL and WebGPU.
  65. ## Instructions for Large Language Models
  66. When generating Three.js code, follow these guidelines:
  67. ### 1. Use Import Maps (Not Old CDN Patterns)
  68. WRONG - outdated pattern:
  69. \`\`\`html
  70. <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  71. \`\`\`
  72. CORRECT - modern pattern (always use latest version):
  73. \`\`\`html
  74. <script type="importmap">
  75. {
  76. "imports": {
  77. "three": "https://cdn.jsdelivr.net/npm/three@${version}/build/three.module.js",
  78. "three/addons/": "https://cdn.jsdelivr.net/npm/three@${version}/examples/jsm/"
  79. }
  80. }
  81. </script>
  82. <script type="module">
  83. import * as THREE from 'three';
  84. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  85. </script>
  86. \`\`\`
  87. ### 2. Choosing Between WebGLRenderer and WebGPURenderer
  88. Three.js maintains both renderers:
  89. **Use WebGLRenderer** (default, mature):
  90. - Maximum browser compatibility
  91. - Well-established, many years of development
  92. - Most examples and tutorials use this
  93. \`\`\`js
  94. import * as THREE from 'three';
  95. const renderer = new THREE.WebGLRenderer();
  96. \`\`\`
  97. **Use WebGPURenderer** when you need:
  98. - Custom shaders/materials using TSL (Three.js Shading Language)
  99. - Compute shaders
  100. - Advanced node-based materials
  101. \`\`\`js
  102. import * as THREE from 'three/webgpu';
  103. const renderer = new THREE.WebGPURenderer();
  104. await renderer.init();
  105. \`\`\`
  106. ### 3. TSL (Three.js Shading Language)
  107. When using WebGPURenderer, use TSL instead of raw GLSL for custom materials:
  108. \`\`\`js
  109. import { texture, uv, color } from 'three/tsl';
  110. const material = new THREE.MeshStandardNodeMaterial();
  111. material.colorNode = texture( myTexture ).mul( color( 0xff0000 ) );
  112. \`\`\`
  113. TSL benefits:
  114. - Works with both WebGL and WebGPU backends
  115. - No string manipulation or onBeforeCompile hacks
  116. - Type-safe, composable shader nodes
  117. - Automatic optimization
  118. ### 4. NodeMaterial Classes (for WebGPU/TSL)
  119. When using TSL, use node-based materials:
  120. - MeshBasicNodeMaterial
  121. - MeshStandardNodeMaterial
  122. - MeshPhysicalNodeMaterial
  123. - LineBasicNodeMaterial
  124. - SpriteNodeMaterial
  125. ## Getting Started
  126. - [Installation](https://threejs.org/manual/#en/installation)
  127. - [Creating a Scene](https://threejs.org/manual/#en/creating-a-scene)
  128. - [Fundamentals](https://threejs.org/manual/#en/fundamentals)
  129. - [Responsive Design](https://threejs.org/manual/#en/responsive)
  130. ## Renderer Guides
  131. - [WebGPURenderer](https://threejs.org/manual/#en/webgpurenderer)
  132. ## Core Concepts
  133. - [TSL Specification](https://threejs.org/docs/#api/en/nodes/TSL): Complete shader language reference
  134. - [Animation System](https://threejs.org/manual/#en/animation-system)
  135. - [Loading 3D Models](https://threejs.org/manual/#en/loading-3d-models)
  136. - [Scene Graph](https://threejs.org/manual/#en/scenegraph)
  137. - [Materials](https://threejs.org/manual/#en/materials)
  138. - [Textures](https://threejs.org/manual/#en/textures)
  139. - [Lights](https://threejs.org/manual/#en/lights)
  140. - [Cameras](https://threejs.org/manual/#en/cameras)
  141. - [Shadows](https://threejs.org/manual/#en/shadows)
  142. ## Essential API
  143. ### Core
  144. - [Object3D](https://threejs.org/docs/#api/en/core/Object3D)
  145. - [BufferGeometry](https://threejs.org/docs/#api/en/core/BufferGeometry)
  146. - [BufferAttribute](https://threejs.org/docs/#api/en/core/BufferAttribute)
  147. ### Scenes
  148. - [Scene](https://threejs.org/docs/#api/en/scenes/Scene)
  149. ### Cameras
  150. - [PerspectiveCamera](https://threejs.org/docs/#api/en/cameras/PerspectiveCamera)
  151. - [OrthographicCamera](https://threejs.org/docs/#api/en/cameras/OrthographicCamera)
  152. ### Renderers
  153. - [WebGLRenderer](https://threejs.org/docs/#api/en/renderers/WebGLRenderer)
  154. - [WebGPURenderer](https://threejs.org/docs/#api/en/renderers/webgpu/WebGPURenderer)
  155. ### Objects
  156. - [Mesh](https://threejs.org/docs/#api/en/objects/Mesh)
  157. - [InstancedMesh](https://threejs.org/docs/#api/en/objects/InstancedMesh)
  158. - [Group](https://threejs.org/docs/#api/en/objects/Group)
  159. ### Materials
  160. - [MeshBasicMaterial](https://threejs.org/docs/#api/en/materials/MeshBasicMaterial)
  161. - [MeshStandardMaterial](https://threejs.org/docs/#api/en/materials/MeshStandardMaterial)
  162. - [MeshPhysicalMaterial](https://threejs.org/docs/#api/en/materials/MeshPhysicalMaterial)
  163. ### Geometries
  164. - [BoxGeometry](https://threejs.org/docs/#api/en/geometries/BoxGeometry)
  165. - [SphereGeometry](https://threejs.org/docs/#api/en/geometries/SphereGeometry)
  166. - [PlaneGeometry](https://threejs.org/docs/#api/en/geometries/PlaneGeometry)
  167. ### Lights
  168. - [AmbientLight](https://threejs.org/docs/#api/en/lights/AmbientLight)
  169. - [DirectionalLight](https://threejs.org/docs/#api/en/lights/DirectionalLight)
  170. - [PointLight](https://threejs.org/docs/#api/en/lights/PointLight)
  171. - [SpotLight](https://threejs.org/docs/#api/en/lights/SpotLight)
  172. ### Loaders
  173. - [TextureLoader](https://threejs.org/docs/#api/en/loaders/TextureLoader)
  174. - [GLTFLoader](https://threejs.org/docs/#examples/en/loaders/GLTFLoader)
  175. ### Controls
  176. - [OrbitControls](https://threejs.org/docs/#examples/en/controls/OrbitControls)
  177. - [TransformControls](https://threejs.org/docs/#examples/en/controls/TransformControls)
  178. ### Math
  179. - [Vector2](https://threejs.org/docs/#api/en/math/Vector2)
  180. - [Vector3](https://threejs.org/docs/#api/en/math/Vector3)
  181. - [Matrix4](https://threejs.org/docs/#api/en/math/Matrix4)
  182. - [Quaternion](https://threejs.org/docs/#api/en/math/Quaternion)
  183. - [Color](https://threejs.org/docs/#api/en/math/Color)
  184. `;
  185. // Docs llms-full.txt - complete inline documentation
  186. const docsLlmsFull = `# Three.js
  187. > Three.js is a cross-browser JavaScript library for creating 3D graphics using WebGL and WebGPU.
  188. ## Instructions for Large Language Models
  189. When generating Three.js code, follow these guidelines:
  190. ### 1. Use Import Maps (Not Old CDN Patterns)
  191. WRONG - outdated pattern:
  192. \`\`\`html
  193. <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  194. \`\`\`
  195. CORRECT - modern pattern (always use latest version):
  196. \`\`\`html
  197. <script type="importmap">
  198. {
  199. "imports": {
  200. "three": "https://cdn.jsdelivr.net/npm/three@${version}/build/three.module.js",
  201. "three/addons/": "https://cdn.jsdelivr.net/npm/three@${version}/examples/jsm/"
  202. }
  203. }
  204. </script>
  205. <script type="module">
  206. import * as THREE from 'three';
  207. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  208. </script>
  209. \`\`\`
  210. ### 2. Choosing Between WebGLRenderer and WebGPURenderer
  211. Three.js maintains both renderers:
  212. **Use WebGLRenderer** (default, mature):
  213. - Maximum browser compatibility
  214. - Well-established, many years of development
  215. - Most examples and tutorials use this
  216. \`\`\`js
  217. import * as THREE from 'three';
  218. const renderer = new THREE.WebGLRenderer();
  219. \`\`\`
  220. **Use WebGPURenderer** when you need:
  221. - Custom shaders/materials using TSL (Three.js Shading Language)
  222. - Compute shaders
  223. - Advanced node-based materials
  224. \`\`\`js
  225. import * as THREE from 'three/webgpu';
  226. const renderer = new THREE.WebGPURenderer();
  227. await renderer.init();
  228. \`\`\`
  229. ### 3. TSL (Three.js Shading Language)
  230. When using WebGPURenderer, use TSL instead of raw GLSL for custom materials:
  231. \`\`\`js
  232. import { texture, uv, color } from 'three/tsl';
  233. const material = new THREE.MeshStandardNodeMaterial();
  234. material.colorNode = texture( myTexture ).mul( color( 0xff0000 ) );
  235. \`\`\`
  236. TSL benefits:
  237. - Works with both WebGL and WebGPU backends
  238. - No string manipulation or onBeforeCompile hacks
  239. - Type-safe, composable shader nodes
  240. - Automatic optimization
  241. ### 4. NodeMaterial Classes (for WebGPU/TSL)
  242. When using TSL, use node-based materials:
  243. - MeshBasicNodeMaterial
  244. - MeshStandardNodeMaterial
  245. - MeshPhysicalNodeMaterial
  246. - LineBasicNodeMaterial
  247. - SpriteNodeMaterial
  248. ---
  249. ## Complete Code Examples
  250. ### Basic Scene with WebGLRenderer
  251. \`\`\`html
  252. <!DOCTYPE html>
  253. <html>
  254. <head>
  255. <meta charset="utf-8">
  256. <title>Three.js Basic Scene</title>
  257. <style>
  258. body { margin: 0; }
  259. </style>
  260. </head>
  261. <body>
  262. <script type="importmap">
  263. {
  264. "imports": {
  265. "three": "https://cdn.jsdelivr.net/npm/three@${version}/build/three.module.js",
  266. "three/addons/": "https://cdn.jsdelivr.net/npm/three@${version}/examples/jsm/"
  267. }
  268. }
  269. </script>
  270. <script type="module">
  271. import * as THREE from 'three';
  272. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  273. // Scene
  274. const scene = new THREE.Scene();
  275. // Camera
  276. const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  277. camera.position.z = 5;
  278. // Renderer
  279. const renderer = new THREE.WebGLRenderer( { antialias: true } );
  280. renderer.setSize( window.innerWidth, window.innerHeight );
  281. renderer.setPixelRatio( window.devicePixelRatio );
  282. document.body.appendChild( renderer.domElement );
  283. // Controls
  284. const controls = new OrbitControls( camera, renderer.domElement );
  285. // Lighting
  286. const ambientLight = new THREE.AmbientLight( 0x404040 );
  287. scene.add( ambientLight );
  288. const directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
  289. directionalLight.position.set( 5, 5, 5 );
  290. scene.add( directionalLight );
  291. // Mesh
  292. const geometry = new THREE.BoxGeometry( 1, 1, 1 );
  293. const material = new THREE.MeshStandardMaterial( { color: 0x00ff00 } );
  294. const cube = new THREE.Mesh( geometry, material );
  295. scene.add( cube );
  296. // Handle resize
  297. window.addEventListener( 'resize', () => {
  298. camera.aspect = window.innerWidth / window.innerHeight;
  299. camera.updateProjectionMatrix();
  300. renderer.setSize( window.innerWidth, window.innerHeight );
  301. } );
  302. // Animation loop
  303. function animate() {
  304. cube.rotation.x += 0.01;
  305. cube.rotation.y += 0.01;
  306. controls.update();
  307. renderer.render( scene, camera );
  308. }
  309. renderer.setAnimationLoop( animate );
  310. </script>
  311. </body>
  312. </html>
  313. \`\`\`
  314. ### Basic Scene with WebGPURenderer and TSL
  315. \`\`\`html
  316. <!DOCTYPE html>
  317. <html>
  318. <head>
  319. <meta charset="utf-8">
  320. <title>Three.js WebGPU Scene</title>
  321. <style>
  322. body { margin: 0; }
  323. </style>
  324. </head>
  325. <body>
  326. <script type="importmap">
  327. {
  328. "imports": {
  329. "three": "https://cdn.jsdelivr.net/npm/three@${version}/build/three.webgpu.js",
  330. "three/tsl": "https://cdn.jsdelivr.net/npm/three@${version}/build/three.tsl.js",
  331. "three/addons/": "https://cdn.jsdelivr.net/npm/three@${version}/examples/jsm/"
  332. }
  333. }
  334. </script>
  335. <script type="module">
  336. import * as THREE from 'three';
  337. import { color, positionLocal, sin, time } from 'three/tsl';
  338. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  339. // Scene
  340. const scene = new THREE.Scene();
  341. // Camera
  342. const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  343. camera.position.z = 5;
  344. // Renderer
  345. const renderer = new THREE.WebGPURenderer( { antialias: true } );
  346. renderer.setSize( window.innerWidth, window.innerHeight );
  347. renderer.setPixelRatio( window.devicePixelRatio );
  348. document.body.appendChild( renderer.domElement );
  349. await renderer.init();
  350. // Controls
  351. const controls = new OrbitControls( camera, renderer.domElement );
  352. // Lighting
  353. const ambientLight = new THREE.AmbientLight( 0x404040 );
  354. scene.add( ambientLight );
  355. const directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
  356. directionalLight.position.set( 5, 5, 5 );
  357. scene.add( directionalLight );
  358. // Custom TSL material
  359. const material = new THREE.MeshStandardNodeMaterial();
  360. material.colorNode = color( 0x00ff00 ).mul( sin( time ).mul( 0.5 ).add( 0.5 ) );
  361. material.positionNode = positionLocal.add( sin( time.add( positionLocal.y ) ).mul( 0.1 ) );
  362. // Mesh
  363. const geometry = new THREE.BoxGeometry( 1, 1, 1 );
  364. const cube = new THREE.Mesh( geometry, material );
  365. scene.add( cube );
  366. // Handle resize
  367. window.addEventListener( 'resize', () => {
  368. camera.aspect = window.innerWidth / window.innerHeight;
  369. camera.updateProjectionMatrix();
  370. renderer.setSize( window.innerWidth, window.innerHeight );
  371. } );
  372. // Animation loop
  373. function animate() {
  374. cube.rotation.x += 0.01;
  375. cube.rotation.y += 0.01;
  376. controls.update();
  377. renderer.render( scene, camera );
  378. }
  379. renderer.setAnimationLoop( animate );
  380. </script>
  381. </body>
  382. </html>
  383. \`\`\`
  384. ### Loading a GLTF Model
  385. \`\`\`js
  386. import * as THREE from 'three';
  387. import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
  388. const loader = new GLTFLoader();
  389. loader.load(
  390. 'model.glb',
  391. ( gltf ) => {
  392. scene.add( gltf.scene );
  393. },
  394. ( progress ) => {
  395. console.log( ( progress.loaded / progress.total * 100 ) + '% loaded' );
  396. },
  397. ( error ) => {
  398. console.error( 'Error loading model:', error );
  399. }
  400. );
  401. \`\`\`
  402. ---
  403. # TSL (Three.js Shading Language) - Complete Reference
  404. ${tslSpec}
  405. `;
  406. // Generate .md versions of all HTML doc pages
  407. const docsDir = 'docs/pages';
  408. // Remove stale .md files from previous builds
  409. const existingMdFiles = fs.readdirSync( docsDir ).filter( f => f.endsWith( '.html.md' ) );
  410. for ( const file of existingMdFiles ) {
  411. fs.unlinkSync( path.join( docsDir, file ) );
  412. }
  413. const htmlFiles = fs.readdirSync( docsDir ).filter( f => f.endsWith( '.html' ) );
  414. const mdFiles = [];
  415. for ( const file of htmlFiles ) {
  416. const htmlPath = path.join( docsDir, file );
  417. const html = fs.readFileSync( htmlPath, 'utf8' );
  418. // Extract just the body content
  419. const bodyMatch = html.match( /<body[^>]*>([\s\S]*)<\/body>/i );
  420. if ( ! bodyMatch ) continue;
  421. const bodyHtml = bodyMatch[ 1 ];
  422. const markdown = turndown.turndown( bodyHtml );
  423. // Write .md file alongside HTML
  424. const mdPath = htmlPath + '.md';
  425. fs.writeFileSync( mdPath, markdown );
  426. // Track for listing
  427. const name = file.replace( '.html', '' );
  428. mdFiles.push( name );
  429. }
  430. // Categorize files by naming patterns
  431. function categorize( name ) {
  432. // Skip internal/index files
  433. if ( name === 'index' || name === 'global' ) return null;
  434. // Specific patterns (order matters - more specific first)
  435. if ( /Loader$/.test( name ) ) return 'Loaders';
  436. if ( /Geometry$/.test( name ) ) return 'Geometries';
  437. if ( /Material$/.test( name ) ) return 'Materials';
  438. if ( /NodeMaterial$/.test( name ) ) return 'Materials';
  439. if ( /Light$/.test( name ) ) return 'Lights';
  440. if ( /Camera$/.test( name ) ) return 'Cameras';
  441. if ( /Controls$/.test( name ) ) return 'Controls';
  442. if ( /Helper$/.test( name ) ) return 'Helpers';
  443. if ( /Curve/.test( name ) ) return 'Curves';
  444. if ( /Pass$/.test( name ) || /PassNode$/.test( name ) ) return 'Post-Processing';
  445. if ( /Node$/.test( name ) ) return 'Nodes (TSL)';
  446. if ( /Texture$/.test( name ) ) return 'Textures';
  447. if ( /Animation/.test( name ) ) return 'Animation';
  448. if ( /Audio/.test( name ) ) return 'Audio';
  449. if ( /XR/.test( name ) ) return 'WebXR';
  450. if ( /Effect$/.test( name ) ) return 'Effects';
  451. if ( /^Vector|^Matrix|^Quaternion|^Euler|^Color$|^Box|^Sphere|^Ray|^Plane|^Frustum|^Triangle/.test( name ) ) return 'Math';
  452. if ( /^module-/.test( name ) ) return 'Shader Modules';
  453. return 'Core';
  454. }
  455. const categories = {};
  456. for ( const name of mdFiles ) {
  457. const category = categorize( name );
  458. if ( ! category ) continue;
  459. if ( ! categories[ category ] ) categories[ category ] = [];
  460. categories[ category ].push( name );
  461. }
  462. // Sort categories and items within each
  463. const categoryOrder = [
  464. 'Core', 'Cameras', 'Lights', 'Materials', 'Geometries', 'Textures',
  465. 'Loaders', 'Controls', 'Helpers', 'Animation', 'Audio', 'Math',
  466. 'Curves', 'Effects', 'Post-Processing', 'Nodes (TSL)', 'WebXR', 'Shader Modules'
  467. ];
  468. let categorizedList = '';
  469. for ( const category of categoryOrder ) {
  470. if ( ! categories[ category ] ) continue;
  471. categories[ category ].sort();
  472. categorizedList += `\n### ${category}\n\n`;
  473. categorizedList += categories[ category ]
  474. .map( name => `- [${name}](https://threejs.org/docs/pages/${name}.html.md)` )
  475. .join( '\n' );
  476. categorizedList += '\n';
  477. }
  478. // Build documentation list for llms-full.txt
  479. const docsList = `
  480. ---
  481. ## Available Documentation
  482. The following documentation pages are available in markdown format at \`https://threejs.org/docs/pages/{Name}.html.md\`:
  483. ${categorizedList}`;
  484. // Write files
  485. fs.writeFileSync( 'llms.txt', rootLlms );
  486. fs.writeFileSync( 'docs/llms.txt', docsLlms );
  487. fs.writeFileSync( 'docs/llms-full.txt', docsLlmsFull + docsList );
  488. console.log( `Generated llms.txt files for Three.js v${version}` );
  489. console.log( ' - llms.txt (root)' );
  490. console.log( ' - docs/llms.txt' );
  491. console.log( ' - docs/llms-full.txt' );
  492. console.log( ` - ${mdFiles.length} doc pages converted to .md` );
粤ICP备19079148号