Gruntfile.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /*eslint-env node*/
  2. 'use strict';
  3. process.on('unhandledRejection', up => {
  4. throw up;
  5. });
  6. const fs = require('fs');
  7. const path = require('path');
  8. const semver = require('semver');
  9. const liveEditor = require('@gfxfundamentals/live-editor');
  10. const liveEditorPath = path.dirname(require.resolve('@gfxfundamentals/live-editor'));
  11. const jsdom = require('jsdom');
  12. const {JSDOM} = jsdom;
  13. // make a fake window because jquery sucks
  14. const dom = new JSDOM('');
  15. global.window = dom.window;
  16. global.document = global.window.document;
  17. const jquery = require('jquery');
  18. module.exports = function(grunt) {
  19. require('load-grunt-tasks')(grunt);
  20. const s_ignoreRE = /\.(md|py|sh|enc)$/i;
  21. function noMds(filename) {
  22. return !s_ignoreRE.test(filename);
  23. }
  24. const s_isMdRE = /\.md$/i;
  25. function mdsOnly(filename) {
  26. return s_isMdRE.test(filename);
  27. }
  28. function notFolder(filename) {
  29. return !fs.statSync(filename).isDirectory();
  30. }
  31. function noMdsNoFolders(filename) {
  32. return noMds(filename) && notFolder(filename);
  33. }
  34. grunt.initConfig({
  35. eslint: {
  36. lib: {
  37. src: [
  38. 'threejs/resources/*.js',
  39. ],
  40. },
  41. support: {
  42. src: [
  43. 'Gruntfile.js',
  44. 'build/js/build.js',
  45. ],
  46. },
  47. examples: {
  48. src: [
  49. 'threejs/*.html',
  50. 'threejs/lessons/resources/*.js',
  51. '!threejs/lessons/resources/prettify.js',
  52. 'threejs/lessons/resources/*.html',
  53. ],
  54. },
  55. },
  56. copy: {
  57. main: {
  58. files: [
  59. { expand: false, src: '*', dest: 'out/', filter: noMdsNoFolders, },
  60. { expand: true, cwd: `${liveEditor.monacoEditor}/`, src: 'min/**', dest: 'out/monaco-editor/', nonull: true, },
  61. { expand: true, cwd: `${liveEditorPath}/src/`, src: '**', dest: 'out/threejs/resources/', nonull: true, },
  62. { expand: true, src: 'threejs/**', dest: 'out/', filter: noMds, },
  63. { expand: true, src: '3rdparty/**', dest: 'out/', },
  64. ],
  65. },
  66. },
  67. clean: [
  68. 'out/**/*',
  69. ],
  70. buildlesson: {
  71. main: {
  72. files: [],
  73. },
  74. },
  75. watch: {
  76. main: {
  77. files: [
  78. 'threejs/**',
  79. '3rdparty/**',
  80. 'node_modules/@gfxfundamentals/live-editor/src/**',
  81. ],
  82. tasks: ['copy'],
  83. options: {
  84. spawn: false,
  85. },
  86. },
  87. lessons: {
  88. files: [
  89. 'threejs/lessons/**/threejs*.md',
  90. ],
  91. tasks: ['buildlesson'],
  92. options: {
  93. spawn: false,
  94. },
  95. },
  96. },
  97. });
  98. let changedFiles = {};
  99. const onChange = grunt.util._.debounce(function() {
  100. grunt.config('copy.main.files', Object.keys(changedFiles).filter(noMds).map((file) => {
  101. const copy = {
  102. src: file,
  103. dest: 'out/',
  104. };
  105. if (file.indexOf('live-editor') >= 0) {
  106. copy.cwd = `${path.dirname(file)}/`;
  107. copy.src = path.basename(file);
  108. copy.expand = true;
  109. copy.dest = 'out/threejs/resources/';
  110. }
  111. return copy;
  112. }));
  113. grunt.config('buildlesson.main.files', Object.keys(changedFiles).filter(mdsOnly).map((file) => {
  114. return {
  115. src: file,
  116. };
  117. }));
  118. changedFiles = {};
  119. }, 200);
  120. grunt.event.on('watch', function(action, filepath) {
  121. changedFiles[filepath] = action;
  122. onChange();
  123. });
  124. function fixThreeJSLinks(html) {
  125. const supportedLangs = {
  126. 'en': true,
  127. 'zh': true,
  128. 'ko': true,
  129. };
  130. global.document.open('text/html', 'replace');
  131. global.document.write(html);
  132. global.document.close();
  133. const $ = jquery;
  134. function insertLang(codeKeywordLinks) {
  135. const lang = document.documentElement.lang.substr(0, 2).toLowerCase();
  136. const langPart = `#api/${supportedLangs[lang] ? lang : 'en'}/`;
  137. const langAddedLinks = {};
  138. for (const [keyword, url] of Object.entries(codeKeywordLinks)) {
  139. langAddedLinks[keyword] = url.replace('#api/', langPart);
  140. }
  141. return langAddedLinks;
  142. }
  143. const codeKeywordLinks = insertLang({
  144. AnimationAction: 'https://threejs.org/docs/#api/animation/AnimationAction',
  145. AnimationClip: 'https://threejs.org/docs/#api/animation/AnimationClip',
  146. AnimationMixer: 'https://threejs.org/docs/#api/animation/AnimationMixer',
  147. AnimationObjectGroup: 'https://threejs.org/docs/#api/animation/AnimationObjectGroup',
  148. AnimationUtils: 'https://threejs.org/docs/#api/animation/AnimationUtils',
  149. KeyframeTrack: 'https://threejs.org/docs/#api/animation/KeyframeTrack',
  150. PropertyBinding: 'https://threejs.org/docs/#api/animation/PropertyBinding',
  151. PropertyMixer: 'https://threejs.org/docs/#api/animation/PropertyMixer',
  152. BooleanKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/BooleanKeyframeTrack',
  153. ColorKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/ColorKeyframeTrack',
  154. NumberKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/NumberKeyframeTrack',
  155. QuaternionKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/QuaternionKeyframeTrack',
  156. StringKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/StringKeyframeTrack',
  157. VectorKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/VectorKeyframeTrack',
  158. Audio: 'https://threejs.org/docs/#api/audio/Audio',
  159. AudioAnalyser: 'https://threejs.org/docs/#api/audio/AudioAnalyser',
  160. AudioContext: 'https://threejs.org/docs/#api/audio/AudioContext',
  161. AudioListener: 'https://threejs.org/docs/#api/audio/AudioListener',
  162. PositionalAudio: 'https://threejs.org/docs/#api/audio/PositionalAudio',
  163. ArrayCamera: 'https://threejs.org/docs/#api/cameras/ArrayCamera',
  164. Camera: 'https://threejs.org/docs/#api/cameras/Camera',
  165. CubeCamera: 'https://threejs.org/docs/#api/cameras/CubeCamera',
  166. OrthographicCamera: 'https://threejs.org/docs/#api/cameras/OrthographicCamera',
  167. PerspectiveCamera: 'https://threejs.org/docs/#api/cameras/PerspectiveCamera',
  168. StereoCamera: 'https://threejs.org/docs/#api/cameras/StereoCamera',
  169. Animation: 'https://threejs.org/docs/#api/constants/Animation',
  170. Core: 'https://threejs.org/docs/#api/constants/Core',
  171. CustomBlendingEquation: 'https://threejs.org/docs/#api/constants/CustomBlendingEquations',
  172. DrawModes: 'https://threejs.org/docs/#api/constants/DrawModes',
  173. Materials: 'https://threejs.org/docs/#api/constants/Materials',
  174. Renderer: 'https://threejs.org/docs/#api/constants/Renderer',
  175. Textures: 'https://threejs.org/docs/#api/constants/Textures',
  176. BufferAttribute: 'https://threejs.org/docs/#api/core/BufferAttribute',
  177. BufferGeometry: 'https://threejs.org/docs/#api/core/BufferGeometry',
  178. Clock: 'https://threejs.org/docs/#api/core/Clock',
  179. DirectGeometry: 'https://threejs.org/docs/#api/core/DirectGeometry',
  180. EventDispatcher: 'https://threejs.org/docs/#api/core/EventDispatcher',
  181. Face3: 'https://threejs.org/docs/#api/core/Face3',
  182. InstancedBufferAttribute: 'https://threejs.org/docs/#api/core/InstancedBufferAttribute',
  183. InstancedBufferGeometry: 'https://threejs.org/docs/#api/core/InstancedBufferGeometry',
  184. InstancedInterleavedBuffer: 'https://threejs.org/docs/#api/core/InstancedInterleavedBuffer',
  185. InterleavedBuffer: 'https://threejs.org/docs/#api/core/InterleavedBuffer',
  186. InterleavedBufferAttribute: 'https://threejs.org/docs/#api/core/InterleavedBufferAttribute',
  187. Layers: 'https://threejs.org/docs/#api/core/Layers',
  188. Object3D: 'https://threejs.org/docs/#api/core/Object3D',
  189. Raycaster: 'https://threejs.org/docs/#api/core/Raycaster',
  190. Uniform: 'https://threejs.org/docs/#api/core/Uniform',
  191. BufferAttributeTypes: 'https://threejs.org/docs/#api/core/bufferAttributeTypes/BufferAttributeTypes',
  192. Earcut: 'https://threejs.org/docs/#api/extras/Earcut',
  193. ShapeUtils: 'https://threejs.org/docs/#api/extras/ShapeUtils',
  194. Curve: 'https://threejs.org/docs/#api/extras/core/Curve',
  195. CurvePath: 'https://threejs.org/docs/#api/extras/core/CurvePath',
  196. Font: 'https://threejs.org/docs/#api/extras/core/Font',
  197. Interpolations: 'https://threejs.org/docs/#api/extras/core/Interpolations',
  198. Path: 'https://threejs.org/docs/#api/extras/core/Path',
  199. Shape: 'https://threejs.org/docs/#api/extras/core/Shape',
  200. ShapePath: 'https://threejs.org/docs/#api/extras/core/ShapePath',
  201. ArcCurve: 'https://threejs.org/docs/#api/extras/curves/ArcCurve',
  202. CatmullRomCurve3: 'https://threejs.org/docs/#api/extras/curves/CatmullRomCurve3',
  203. CubicBezierCurve: 'https://threejs.org/docs/#api/extras/curves/CubicBezierCurve',
  204. CubicBezierCurve3: 'https://threejs.org/docs/#api/extras/curves/CubicBezierCurve3',
  205. EllipseCurve: 'https://threejs.org/docs/#api/extras/curves/EllipseCurve',
  206. LineCurve: 'https://threejs.org/docs/#api/extras/curves/LineCurve',
  207. LineCurve3: 'https://threejs.org/docs/#api/extras/curves/LineCurve3',
  208. QuadraticBezierCurve: 'https://threejs.org/docs/#api/extras/curves/QuadraticBezierCurve',
  209. QuadraticBezierCurve3: 'https://threejs.org/docs/#api/extras/curves/QuadraticBezierCurve3',
  210. SplineCurve: 'https://threejs.org/docs/#api/extras/curves/SplineCurve',
  211. ImmediateRenderObject: 'https://threejs.org/docs/#api/extras/objects/ImmediateRenderObject',
  212. BoxGeometry: 'https://threejs.org/docs/#api/geometries/BoxGeometry',
  213. CircleGeometry: 'https://threejs.org/docs/#api/geometries/CircleGeometry',
  214. ConeGeometry: 'https://threejs.org/docs/#api/geometries/ConeGeometry',
  215. CylinderGeometry: 'https://threejs.org/docs/#api/geometries/CylinderGeometry',
  216. DodecahedronGeometry: 'https://threejs.org/docs/#api/geometries/DodecahedronGeometry',
  217. EdgesGeometry: 'https://threejs.org/docs/#api/geometries/EdgesGeometry',
  218. ExtrudeGeometry: 'https://threejs.org/docs/#api/geometries/ExtrudeGeometry',
  219. IcosahedronGeometry: 'https://threejs.org/docs/#api/geometries/IcosahedronGeometry',
  220. LatheGeometry: 'https://threejs.org/docs/#api/geometries/LatheGeometry',
  221. OctahedronGeometry: 'https://threejs.org/docs/#api/geometries/OctahedronGeometry',
  222. ParametricGeometry: 'https://threejs.org/docs/#api/geometries/ParametricGeometry',
  223. PlaneGeometry: 'https://threejs.org/docs/#api/geometries/PlaneGeometry',
  224. PolyhedronGeometry: 'https://threejs.org/docs/#api/geometries/PolyhedronGeometry',
  225. RingGeometry: 'https://threejs.org/docs/#api/geometries/RingGeometry',
  226. ShapeGeometry: 'https://threejs.org/docs/#api/geometries/ShapeGeometry',
  227. SphereGeometry: 'https://threejs.org/docs/#api/geometries/SphereGeometry',
  228. TetrahedronGeometry: 'https://threejs.org/docs/#api/geometries/TetrahedronGeometry',
  229. TextGeometry: 'https://threejs.org/docs/#api/geometries/TextGeometry',
  230. TorusGeometry: 'https://threejs.org/docs/#api/geometries/TorusGeometry',
  231. TorusKnotGeometry: 'https://threejs.org/docs/#api/geometries/TorusKnotGeometry',
  232. TubeGeometry: 'https://threejs.org/docs/#api/geometries/TubeGeometry',
  233. WireframeGeometry: 'https://threejs.org/docs/#api/geometries/WireframeGeometry',
  234. ArrowHelper: 'https://threejs.org/docs/#api/helpers/ArrowHelper',
  235. AxesHelper: 'https://threejs.org/docs/#api/helpers/AxesHelper',
  236. BoxHelper: 'https://threejs.org/docs/#api/helpers/BoxHelper',
  237. Box3Helper: 'https://threejs.org/docs/#api/helpers/Box3Helper',
  238. CameraHelper: 'https://threejs.org/docs/#api/helpers/CameraHelper',
  239. DirectionalLightHelper: 'https://threejs.org/docs/#api/helpers/DirectionalLightHelper',
  240. FaceNormalsHelper: 'https://threejs.org/docs/#api/helpers/FaceNormalsHelper',
  241. GridHelper: 'https://threejs.org/docs/#api/helpers/GridHelper',
  242. PolarGridHelper: 'https://threejs.org/docs/#api/helpers/PolarGridHelper',
  243. HemisphereLightHelper: 'https://threejs.org/docs/#api/helpers/HemisphereLightHelper',
  244. PlaneHelper: 'https://threejs.org/docs/#api/helpers/PlaneHelper',
  245. PointLightHelper: 'https://threejs.org/docs/#api/helpers/PointLightHelper',
  246. RectAreaLightHelper: 'https://threejs.org/docs/#api/helpers/RectAreaLightHelper',
  247. SkeletonHelper: 'https://threejs.org/docs/#api/helpers/SkeletonHelper',
  248. SpotLightHelper: 'https://threejs.org/docs/#api/helpers/SpotLightHelper',
  249. VertexNormalsHelper: 'https://threejs.org/docs/#api/helpers/VertexNormalsHelper',
  250. AmbientLight: 'https://threejs.org/docs/#api/lights/AmbientLight',
  251. DirectionalLight: 'https://threejs.org/docs/#api/lights/DirectionalLight',
  252. HemisphereLight: 'https://threejs.org/docs/#api/lights/HemisphereLight',
  253. Light: 'https://threejs.org/docs/#api/lights/Light',
  254. PointLight: 'https://threejs.org/docs/#api/lights/PointLight',
  255. RectAreaLight: 'https://threejs.org/docs/#api/lights/RectAreaLight',
  256. SpotLight: 'https://threejs.org/docs/#api/lights/SpotLight',
  257. DirectionalLightShadow: 'https://threejs.org/docs/#api/lights/shadows/DirectionalLightShadow',
  258. LightShadow: 'https://threejs.org/docs/#api/lights/shadows/LightShadow',
  259. SpotLightShadow: 'https://threejs.org/docs/#api/lights/shadows/SpotLightShadow',
  260. AnimationLoader: 'https://threejs.org/docs/#api/loaders/AnimationLoader',
  261. AudioLoader: 'https://threejs.org/docs/#api/loaders/AudioLoader',
  262. BufferGeometryLoader: 'https://threejs.org/docs/#api/loaders/BufferGeometryLoader',
  263. Cache: 'https://threejs.org/docs/#api/loaders/Cache',
  264. CompressedTextureLoader: 'https://threejs.org/docs/#api/loaders/CompressedTextureLoader',
  265. CubeTextureLoader: 'https://threejs.org/docs/#api/loaders/CubeTextureLoader',
  266. DataTextureLoader: 'https://threejs.org/docs/#api/loaders/DataTextureLoader',
  267. FileLoader: 'https://threejs.org/docs/#api/loaders/FileLoader',
  268. FontLoader: 'https://threejs.org/docs/#api/loaders/FontLoader',
  269. ImageBitmapLoader: 'https://threejs.org/docs/#api/loaders/ImageBitmapLoader',
  270. ImageLoader: 'https://threejs.org/docs/#api/loaders/ImageLoader',
  271. JSONLoader: 'https://threejs.org/docs/#api/loaders/JSONLoader',
  272. Loader: 'https://threejs.org/docs/#api/loaders/Loader',
  273. LoaderUtils: 'https://threejs.org/docs/#api/loaders/LoaderUtils',
  274. MaterialLoader: 'https://threejs.org/docs/#api/loaders/MaterialLoader',
  275. ObjectLoader: 'https://threejs.org/docs/#api/loaders/ObjectLoader',
  276. TextureLoader: 'https://threejs.org/docs/#api/loaders/TextureLoader',
  277. DefaultLoadingManager: 'https://threejs.org/docs/#api/loaders/managers/DefaultLoadingManager',
  278. LoadingManager: 'https://threejs.org/docs/#api/loaders/managers/LoadingManager',
  279. LineBasicMaterial: 'https://threejs.org/docs/#api/materials/LineBasicMaterial',
  280. LineDashedMaterial: 'https://threejs.org/docs/#api/materials/LineDashedMaterial',
  281. Material: 'https://threejs.org/docs/#api/materials/Material',
  282. MeshBasicMaterial: 'https://threejs.org/docs/#api/materials/MeshBasicMaterial',
  283. MeshDepthMaterial: 'https://threejs.org/docs/#api/materials/MeshDepthMaterial',
  284. MeshLambertMaterial: 'https://threejs.org/docs/#api/materials/MeshLambertMaterial',
  285. MeshNormalMaterial: 'https://threejs.org/docs/#api/materials/MeshNormalMaterial',
  286. MeshPhongMaterial: 'https://threejs.org/docs/#api/materials/MeshPhongMaterial',
  287. MeshPhysicalMaterial: 'https://threejs.org/docs/#api/materials/MeshPhysicalMaterial',
  288. MeshStandardMaterial: 'https://threejs.org/docs/#api/materials/MeshStandardMaterial',
  289. MeshToonMaterial: 'https://threejs.org/docs/#api/materials/MeshToonMaterial',
  290. PointsMaterial: 'https://threejs.org/docs/#api/materials/PointsMaterial',
  291. RawShaderMaterial: 'https://threejs.org/docs/#api/materials/RawShaderMaterial',
  292. ShaderMaterial: 'https://threejs.org/docs/#api/materials/ShaderMaterial',
  293. ShadowMaterial: 'https://threejs.org/docs/#api/materials/ShadowMaterial',
  294. SpriteMaterial: 'https://threejs.org/docs/#api/materials/SpriteMaterial',
  295. Box2: 'https://threejs.org/docs/#api/math/Box2',
  296. Box3: 'https://threejs.org/docs/#api/math/Box3',
  297. Color: 'https://threejs.org/docs/#api/math/Color',
  298. Cylindrical: 'https://threejs.org/docs/#api/math/Cylindrical',
  299. Euler: 'https://threejs.org/docs/#api/math/Euler',
  300. Frustum: 'https://threejs.org/docs/#api/math/Frustum',
  301. Interpolant: 'https://threejs.org/docs/#api/math/Interpolant',
  302. Line3: 'https://threejs.org/docs/#api/math/Line3',
  303. Math: 'https://threejs.org/docs/#api/math/Math',
  304. Matrix3: 'https://threejs.org/docs/#api/math/Matrix3',
  305. Matrix4: 'https://threejs.org/docs/#api/math/Matrix4',
  306. Plane: 'https://threejs.org/docs/#api/math/Plane',
  307. Quaternion: 'https://threejs.org/docs/#api/math/Quaternion',
  308. Ray: 'https://threejs.org/docs/#api/math/Ray',
  309. Sphere: 'https://threejs.org/docs/#api/math/Sphere',
  310. Spherical: 'https://threejs.org/docs/#api/math/Spherical',
  311. Triangle: 'https://threejs.org/docs/#api/math/Triangle',
  312. Vector2: 'https://threejs.org/docs/#api/math/Vector2',
  313. Vector3: 'https://threejs.org/docs/#api/math/Vector3',
  314. Vector4: 'https://threejs.org/docs/#api/math/Vector4',
  315. CubicInterpolant: 'https://threejs.org/docs/#api/math/interpolants/CubicInterpolant',
  316. DiscreteInterpolant: 'https://threejs.org/docs/#api/math/interpolants/DiscreteInterpolant',
  317. LinearInterpolant: 'https://threejs.org/docs/#api/math/interpolants/LinearInterpolant',
  318. QuaternionLinearInterpolant: 'https://threejs.org/docs/#api/math/interpolants/QuaternionLinearInterpolant',
  319. Bone: 'https://threejs.org/docs/#api/objects/Bone',
  320. Group: 'https://threejs.org/docs/#api/objects/Group',
  321. Line: 'https://threejs.org/docs/#api/objects/Line',
  322. LineLoop: 'https://threejs.org/docs/#api/objects/LineLoop',
  323. LineSegments: 'https://threejs.org/docs/#api/objects/LineSegments',
  324. LOD: 'https://threejs.org/docs/#api/objects/LOD',
  325. Mesh: 'https://threejs.org/docs/#api/objects/Mesh',
  326. Points: 'https://threejs.org/docs/#api/objects/Points',
  327. Skeleton: 'https://threejs.org/docs/#api/objects/Skeleton',
  328. SkinnedMesh: 'https://threejs.org/docs/#api/objects/SkinnedMesh',
  329. Sprite: 'https://threejs.org/docs/#api/objects/Sprite',
  330. WebGLRenderer: 'https://threejs.org/docs/#api/renderers/WebGLRenderer',
  331. WebGLRenderTarget: 'https://threejs.org/docs/#api/renderers/WebGLRenderTarget',
  332. WebGLCubeRenderTarget: 'https://threejs.org/docs/#api/renderers/WebGLCubeRenderTarget',
  333. ShaderChunk: 'https://threejs.org/docs/#api/renderers/shaders/ShaderChunk',
  334. ShaderLib: 'https://threejs.org/docs/#api/renderers/shaders/ShaderLib',
  335. UniformsLib: 'https://threejs.org/docs/#api/renderers/shaders/UniformsLib',
  336. UniformsUtils: 'https://threejs.org/docs/#api/renderers/shaders/UniformsUtils',
  337. Fog: 'https://threejs.org/docs/#api/scenes/Fog',
  338. FogExp2: 'https://threejs.org/docs/#api/scenes/FogExp2',
  339. Scene: 'https://threejs.org/docs/#api/scenes/Scene',
  340. CanvasTexture: 'https://threejs.org/docs/#api/textures/CanvasTexture',
  341. CompressedTexture: 'https://threejs.org/docs/#api/textures/CompressedTexture',
  342. CubeTexture: 'https://threejs.org/docs/#api/textures/CubeTexture',
  343. DataTexture: 'https://threejs.org/docs/#api/textures/DataTexture',
  344. DepthTexture: 'https://threejs.org/docs/#api/textures/DepthTexture',
  345. Texture: 'https://threejs.org/docs/#api/textures/Texture',
  346. VideoTexture: 'https://threejs.org/docs/#api/textures/VideoTexture',
  347. CCDIKSolver: 'https://threejs.org/docs/#examples/animations/CCDIKSolver',
  348. MMDAnimationHelper: 'https://threejs.org/docs/#examples/animations/MMDAnimationHelper',
  349. MMDPhysics: 'https://threejs.org/docs/#examples/animations/MMDPhysics',
  350. OrbitControls: 'https://threejs.org/docs/#examples/controls/OrbitControls',
  351. ConvexGeometry: 'https://threejs.org/docs/#examples/geometries/ConvexGeometry',
  352. DecalGeometry: 'https://threejs.org/docs/#examples/geometries/DecalGeometry',
  353. BabylonLoader: 'https://threejs.org/docs/#examples/loaders/BabylonLoader',
  354. GLTFLoader: 'https://threejs.org/docs/#examples/loaders/GLTFLoader',
  355. MMDLoader: 'https://threejs.org/docs/#examples/loaders/MMDLoader',
  356. MTLLoader: 'https://threejs.org/docs/#examples/loaders/MTLLoader',
  357. OBJLoader: 'https://threejs.org/docs/#examples/loaders/OBJLoader',
  358. OBJLoader2: 'https://threejs.org/docs/#examples/loaders/OBJLoader2',
  359. LoaderSupport: 'https://threejs.org/docs/#examples/loaders/LoaderSupport',
  360. PCDLoader: 'https://threejs.org/docs/#examples/loaders/PCDLoader',
  361. PDBLoader: 'https://threejs.org/docs/#examples/loaders/PDBLoader',
  362. SVGLoader: 'https://threejs.org/docs/#examples/loaders/SVGLoader',
  363. TGALoader: 'https://threejs.org/docs/#examples/loaders/TGALoader',
  364. PRWMLoader: 'https://threejs.org/docs/#examples/loaders/PRWMLoader',
  365. Lensflare: 'https://threejs.org/docs/#examples/objects/Lensflare',
  366. GLTFExporter: 'https://threejs.org/docs/#examples/exporters/GLTFExporter',
  367. });
  368. function getKeywordLink(keyword) {
  369. const dotNdx = keyword.indexOf('.');
  370. if (dotNdx) {
  371. const before = keyword.substring(0, dotNdx);
  372. const link = codeKeywordLinks[before];
  373. if (link) {
  374. return `${link}.${keyword.substr(dotNdx + 1)}`;
  375. }
  376. }
  377. return keyword.startsWith('THREE.')
  378. ? codeKeywordLinks[keyword.substring(6)]
  379. : codeKeywordLinks[keyword];
  380. }
  381. $('code').filter(function() {
  382. return getKeywordLink(this.textContent) &&
  383. this.parentElement.nodeName !== 'A';
  384. }).wrap(function() {
  385. const a = document.createElement('a');
  386. a.href = getKeywordLink(this.textContent);
  387. return a;
  388. });
  389. const methodPropertyRE = /^(\w+)\.(\w+)$/;
  390. const classRE = /^(\w+)$/;
  391. $('a').each(function() {
  392. const href = this.getAttribute('href');
  393. if (!href) {
  394. return;
  395. }
  396. const m = methodPropertyRE.exec(href);
  397. if (m) {
  398. const codeKeywordLink = getKeywordLink(m[1]);
  399. if (codeKeywordLink) {
  400. this.setAttribute('href', `${codeKeywordLink}#${m[2]}`);
  401. }
  402. } else if (classRE.test(href)) {
  403. const codeKeywordLink = getKeywordLink(href);
  404. if (codeKeywordLink) {
  405. this.setAttribute('href', codeKeywordLink);
  406. }
  407. }
  408. });
  409. $('pre>code')
  410. .unwrap()
  411. .replaceWith(function() {
  412. return $(`<pre class="prettyprint showlinemods notranslate ${this.className || ''}" translate="no">${this.innerHTML}</pre>`);
  413. });
  414. return dom.serialize();
  415. }
  416. const buildSettings = {
  417. outDir: 'out',
  418. baseUrl: 'https://threejsfundamentals.org',
  419. rootFolder: 'threejs',
  420. lessonGrep: 'threejs*.md',
  421. siteName: 'ThreeJSFundamentals',
  422. siteThumbnail: 'threejsfundamentals.jpg', // in rootFolder/lessons/resources
  423. templatePath: 'build/templates',
  424. owner: 'gfxfundamentals',
  425. repo: 'threejsfundamentals',
  426. thumbnailOptions: {
  427. thumbnailBackground: 'threejsfundamentals-background.jpg',
  428. text: [
  429. {
  430. font: 'bold 100px lesson-font',
  431. verticalSpacing: 100,
  432. offset: [100, 120],
  433. textAlign: 'left',
  434. shadowOffset: [15, 15],
  435. strokeWidth: 15,
  436. textWrapWidth: 1000,
  437. },
  438. {
  439. font: 'bold 60px lesson-font',
  440. text: 'threejsfundamentals.org',
  441. verticalSpacing: 100,
  442. offset: [-100, -90],
  443. textAlign: 'right',
  444. shadowOffset: [8, 8],
  445. strokeWidth: 15,
  446. textWrapWidth: 1000,
  447. color: 'hsl(340, 100%, 70%)',
  448. },
  449. ],
  450. },
  451. postHTMLFn: fixThreeJSLinks,
  452. };
  453. // just the hackiest way to get this working.
  454. grunt.registerMultiTask('buildlesson', 'build a lesson', function() {
  455. const filenames = new Set();
  456. this.files.forEach((files) => {
  457. files.src.forEach((filename) => {
  458. filenames.add(filename);
  459. });
  460. });
  461. const buildStuff = require('@gfxfundamentals/lesson-builder');
  462. const settings = {...buildSettings, filenames};
  463. const finish = this.async();
  464. buildStuff(settings).finally(finish);
  465. });
  466. grunt.registerTask('buildlessons', function() {
  467. const buildStuff = require('@gfxfundamentals/lesson-builder');
  468. const finish = this.async();
  469. buildStuff(buildSettings).finally(finish);
  470. });
  471. grunt.task.registerMultiTask('fixthreepaths', 'fix three paths', function() {
  472. const options = this.options({});
  473. const oldVersionRE = new RegExp(`/${options.oldVersionStr}/`, 'g');
  474. const newVersionReplacement = `/${options.newVersionStr}/`;
  475. this.files.forEach((files) => {
  476. files.src.forEach((filename) => {
  477. const oldContent = fs.readFileSync(filename, {encoding: 'utf8'});
  478. const newContent = oldContent.replace(oldVersionRE, newVersionReplacement);
  479. if (oldContent !== newContent) {
  480. grunt.log.writeln(`updating ${filename} to ${options.newVersionStr}`);
  481. fs.writeFileSync(filename, newContent);
  482. }
  483. });
  484. });
  485. });
  486. grunt.registerTask('bumpthree', function() {
  487. const lessonInfo = JSON.parse(fs.readFileSync('package.json', {encoding: 'utf8'}));
  488. const oldVersion = lessonInfo.threejsfundamentals.threeVersion;
  489. const oldVersionStr = `r${oldVersion}`;
  490. const threePath = path.dirname(path.dirname(require.resolve('three')));
  491. const threeInfo = JSON.parse(fs.readFileSync(path.join(threePath, 'package.json'), {encoding: 'utf8'}));
  492. const newVersion = semver.minor(threeInfo.version);
  493. const newVersionStr = `r${newVersion}`;
  494. const basePath = path.join('threejs', 'resources', 'threejs', newVersionStr);
  495. grunt.config.merge({
  496. copy: {
  497. threejs: {
  498. files: [
  499. { expand: true, cwd: `${threePath}/build/`, src: 'three.js', dest: `${basePath}/build/`, },
  500. { expand: true, cwd: `${threePath}/build/`, src: 'three.min.js', dest: `${basePath}/build/`, },
  501. { expand: true, cwd: `${threePath}/build/`, src: 'three.module.js', dest: `${basePath}/build/`, },
  502. { expand: true, cwd: `${threePath}/examples/js/`, src: '**', dest: `${basePath}/examples/js/`, },
  503. { expand: true, cwd: `${threePath}/examples/jsm/`, src: '**', dest: `${basePath}/examples/jsm/`, },
  504. ],
  505. },
  506. },
  507. fixthreepaths: {
  508. options: {
  509. oldVersionStr,
  510. newVersionStr,
  511. },
  512. src: [
  513. 'threejs/**/*.html',
  514. 'threejs/**/*.md',
  515. 'threejs/**/*.js',
  516. '!threejs/resources/threejs/**',
  517. ],
  518. },
  519. });
  520. lessonInfo.threejsfundamentals.threeVersion = newVersion;
  521. fs.writeFileSync('package.json', JSON.stringify(lessonInfo, null, 2));
  522. grunt.task.run(['copy:threejs', 'fixthreepaths']);
  523. });
  524. grunt.registerTask('build', ['clean', 'copy:main', 'buildlessons']);
  525. grunt.registerTask('buildwatch', ['build', 'watch']);
  526. grunt.registerTask('default', ['eslint', 'build']);
  527. };