Gruntfile.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  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. };
  129. global.document.open('text/html', 'replace');
  130. global.document.write(html);
  131. global.document.close();
  132. const $ = jquery;
  133. function insertLang(codeKeywordLinks) {
  134. const lang = document.documentElement.lang.substr(0, 2).toLowerCase();
  135. const langPart = `#api/${supportedLangs[lang] ? lang : 'en'}/`;
  136. const langAddedLinks = {};
  137. for (const [keyword, url] of Object.entries(codeKeywordLinks)) {
  138. langAddedLinks[keyword] = url.replace('#api/', langPart);
  139. }
  140. return langAddedLinks;
  141. }
  142. const codeKeywordLinks = insertLang({
  143. AnimationAction: 'https://threejs.org/docs/#api/animation/AnimationAction',
  144. AnimationClip: 'https://threejs.org/docs/#api/animation/AnimationClip',
  145. AnimationMixer: 'https://threejs.org/docs/#api/animation/AnimationMixer',
  146. AnimationObjectGroup: 'https://threejs.org/docs/#api/animation/AnimationObjectGroup',
  147. AnimationUtils: 'https://threejs.org/docs/#api/animation/AnimationUtils',
  148. KeyframeTrack: 'https://threejs.org/docs/#api/animation/KeyframeTrack',
  149. PropertyBinding: 'https://threejs.org/docs/#api/animation/PropertyBinding',
  150. PropertyMixer: 'https://threejs.org/docs/#api/animation/PropertyMixer',
  151. BooleanKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/BooleanKeyframeTrack',
  152. ColorKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/ColorKeyframeTrack',
  153. NumberKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/NumberKeyframeTrack',
  154. QuaternionKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/QuaternionKeyframeTrack',
  155. StringKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/StringKeyframeTrack',
  156. VectorKeyframeTrack: 'https://threejs.org/docs/#api/animation/tracks/VectorKeyframeTrack',
  157. Audio: 'https://threejs.org/docs/#api/audio/Audio',
  158. AudioAnalyser: 'https://threejs.org/docs/#api/audio/AudioAnalyser',
  159. AudioContext: 'https://threejs.org/docs/#api/audio/AudioContext',
  160. AudioListener: 'https://threejs.org/docs/#api/audio/AudioListener',
  161. PositionalAudio: 'https://threejs.org/docs/#api/audio/PositionalAudio',
  162. ArrayCamera: 'https://threejs.org/docs/#api/cameras/ArrayCamera',
  163. Camera: 'https://threejs.org/docs/#api/cameras/Camera',
  164. CubeCamera: 'https://threejs.org/docs/#api/cameras/CubeCamera',
  165. OrthographicCamera: 'https://threejs.org/docs/#api/cameras/OrthographicCamera',
  166. PerspectiveCamera: 'https://threejs.org/docs/#api/cameras/PerspectiveCamera',
  167. StereoCamera: 'https://threejs.org/docs/#api/cameras/StereoCamera',
  168. Animation: 'https://threejs.org/docs/#api/constants/Animation',
  169. Core: 'https://threejs.org/docs/#api/constants/Core',
  170. CustomBlendingEquation: 'https://threejs.org/docs/#api/constants/CustomBlendingEquations',
  171. DrawModes: 'https://threejs.org/docs/#api/constants/DrawModes',
  172. Materials: 'https://threejs.org/docs/#api/constants/Materials',
  173. Renderer: 'https://threejs.org/docs/#api/constants/Renderer',
  174. Textures: 'https://threejs.org/docs/#api/constants/Textures',
  175. BufferAttribute: 'https://threejs.org/docs/#api/core/BufferAttribute',
  176. BufferGeometry: 'https://threejs.org/docs/#api/core/BufferGeometry',
  177. Clock: 'https://threejs.org/docs/#api/core/Clock',
  178. DirectGeometry: 'https://threejs.org/docs/#api/core/DirectGeometry',
  179. EventDispatcher: 'https://threejs.org/docs/#api/core/EventDispatcher',
  180. Face3: 'https://threejs.org/docs/#api/core/Face3',
  181. Geometry: 'https://threejs.org/docs/#api/core/Geometry',
  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. BoxBufferGeometry: 'https://threejs.org/docs/#api/geometries/BoxBufferGeometry',
  213. BoxGeometry: 'https://threejs.org/docs/#api/geometries/BoxGeometry',
  214. CircleBufferGeometry: 'https://threejs.org/docs/#api/geometries/CircleBufferGeometry',
  215. CircleGeometry: 'https://threejs.org/docs/#api/geometries/CircleGeometry',
  216. ConeBufferGeometry: 'https://threejs.org/docs/#api/geometries/ConeBufferGeometry',
  217. ConeGeometry: 'https://threejs.org/docs/#api/geometries/ConeGeometry',
  218. CylinderBufferGeometry: 'https://threejs.org/docs/#api/geometries/CylinderBufferGeometry',
  219. CylinderGeometry: 'https://threejs.org/docs/#api/geometries/CylinderGeometry',
  220. DodecahedronBufferGeometry: 'https://threejs.org/docs/#api/geometries/DodecahedronBufferGeometry',
  221. DodecahedronGeometry: 'https://threejs.org/docs/#api/geometries/DodecahedronGeometry',
  222. EdgesGeometry: 'https://threejs.org/docs/#api/geometries/EdgesGeometry',
  223. ExtrudeBufferGeometry: 'https://threejs.org/docs/#api/geometries/ExtrudeBufferGeometry',
  224. ExtrudeGeometry: 'https://threejs.org/docs/#api/geometries/ExtrudeGeometry',
  225. IcosahedronBufferGeometry: 'https://threejs.org/docs/#api/geometries/IcosahedronBufferGeometry',
  226. IcosahedronGeometry: 'https://threejs.org/docs/#api/geometries/IcosahedronGeometry',
  227. LatheBufferGeometry: 'https://threejs.org/docs/#api/geometries/LatheBufferGeometry',
  228. LatheGeometry: 'https://threejs.org/docs/#api/geometries/LatheGeometry',
  229. OctahedronBufferGeometry: 'https://threejs.org/docs/#api/geometries/OctahedronBufferGeometry',
  230. OctahedronGeometry: 'https://threejs.org/docs/#api/geometries/OctahedronGeometry',
  231. ParametricBufferGeometry: 'https://threejs.org/docs/#api/geometries/ParametricBufferGeometry',
  232. ParametricGeometry: 'https://threejs.org/docs/#api/geometries/ParametricGeometry',
  233. PlaneBufferGeometry: 'https://threejs.org/docs/#api/geometries/PlaneBufferGeometry',
  234. PlaneGeometry: 'https://threejs.org/docs/#api/geometries/PlaneGeometry',
  235. PolyhedronBufferGeometry: 'https://threejs.org/docs/#api/geometries/PolyhedronBufferGeometry',
  236. PolyhedronGeometry: 'https://threejs.org/docs/#api/geometries/PolyhedronGeometry',
  237. RingBufferGeometry: 'https://threejs.org/docs/#api/geometries/RingBufferGeometry',
  238. RingGeometry: 'https://threejs.org/docs/#api/geometries/RingGeometry',
  239. ShapeBufferGeometry: 'https://threejs.org/docs/#api/geometries/ShapeBufferGeometry',
  240. ShapeGeometry: 'https://threejs.org/docs/#api/geometries/ShapeGeometry',
  241. SphereBufferGeometry: 'https://threejs.org/docs/#api/geometries/SphereBufferGeometry',
  242. SphereGeometry: 'https://threejs.org/docs/#api/geometries/SphereGeometry',
  243. TetrahedronBufferGeometry: 'https://threejs.org/docs/#api/geometries/TetrahedronBufferGeometry',
  244. TetrahedronGeometry: 'https://threejs.org/docs/#api/geometries/TetrahedronGeometry',
  245. TextBufferGeometry: 'https://threejs.org/docs/#api/geometries/TextBufferGeometry',
  246. TextGeometry: 'https://threejs.org/docs/#api/geometries/TextGeometry',
  247. TorusBufferGeometry: 'https://threejs.org/docs/#api/geometries/TorusBufferGeometry',
  248. TorusGeometry: 'https://threejs.org/docs/#api/geometries/TorusGeometry',
  249. TorusKnotBufferGeometry: 'https://threejs.org/docs/#api/geometries/TorusKnotBufferGeometry',
  250. TorusKnotGeometry: 'https://threejs.org/docs/#api/geometries/TorusKnotGeometry',
  251. TubeBufferGeometry: 'https://threejs.org/docs/#api/geometries/TubeBufferGeometry',
  252. TubeGeometry: 'https://threejs.org/docs/#api/geometries/TubeGeometry',
  253. WireframeGeometry: 'https://threejs.org/docs/#api/geometries/WireframeGeometry',
  254. ArrowHelper: 'https://threejs.org/docs/#api/helpers/ArrowHelper',
  255. AxesHelper: 'https://threejs.org/docs/#api/helpers/AxesHelper',
  256. BoxHelper: 'https://threejs.org/docs/#api/helpers/BoxHelper',
  257. Box3Helper: 'https://threejs.org/docs/#api/helpers/Box3Helper',
  258. CameraHelper: 'https://threejs.org/docs/#api/helpers/CameraHelper',
  259. DirectionalLightHelper: 'https://threejs.org/docs/#api/helpers/DirectionalLightHelper',
  260. FaceNormalsHelper: 'https://threejs.org/docs/#api/helpers/FaceNormalsHelper',
  261. GridHelper: 'https://threejs.org/docs/#api/helpers/GridHelper',
  262. PolarGridHelper: 'https://threejs.org/docs/#api/helpers/PolarGridHelper',
  263. HemisphereLightHelper: 'https://threejs.org/docs/#api/helpers/HemisphereLightHelper',
  264. PlaneHelper: 'https://threejs.org/docs/#api/helpers/PlaneHelper',
  265. PointLightHelper: 'https://threejs.org/docs/#api/helpers/PointLightHelper',
  266. RectAreaLightHelper: 'https://threejs.org/docs/#api/helpers/RectAreaLightHelper',
  267. SkeletonHelper: 'https://threejs.org/docs/#api/helpers/SkeletonHelper',
  268. SpotLightHelper: 'https://threejs.org/docs/#api/helpers/SpotLightHelper',
  269. VertexNormalsHelper: 'https://threejs.org/docs/#api/helpers/VertexNormalsHelper',
  270. AmbientLight: 'https://threejs.org/docs/#api/lights/AmbientLight',
  271. DirectionalLight: 'https://threejs.org/docs/#api/lights/DirectionalLight',
  272. HemisphereLight: 'https://threejs.org/docs/#api/lights/HemisphereLight',
  273. Light: 'https://threejs.org/docs/#api/lights/Light',
  274. PointLight: 'https://threejs.org/docs/#api/lights/PointLight',
  275. RectAreaLight: 'https://threejs.org/docs/#api/lights/RectAreaLight',
  276. SpotLight: 'https://threejs.org/docs/#api/lights/SpotLight',
  277. DirectionalLightShadow: 'https://threejs.org/docs/#api/lights/shadows/DirectionalLightShadow',
  278. LightShadow: 'https://threejs.org/docs/#api/lights/shadows/LightShadow',
  279. SpotLightShadow: 'https://threejs.org/docs/#api/lights/shadows/SpotLightShadow',
  280. AnimationLoader: 'https://threejs.org/docs/#api/loaders/AnimationLoader',
  281. AudioLoader: 'https://threejs.org/docs/#api/loaders/AudioLoader',
  282. BufferGeometryLoader: 'https://threejs.org/docs/#api/loaders/BufferGeometryLoader',
  283. Cache: 'https://threejs.org/docs/#api/loaders/Cache',
  284. CompressedTextureLoader: 'https://threejs.org/docs/#api/loaders/CompressedTextureLoader',
  285. CubeTextureLoader: 'https://threejs.org/docs/#api/loaders/CubeTextureLoader',
  286. DataTextureLoader: 'https://threejs.org/docs/#api/loaders/DataTextureLoader',
  287. FileLoader: 'https://threejs.org/docs/#api/loaders/FileLoader',
  288. FontLoader: 'https://threejs.org/docs/#api/loaders/FontLoader',
  289. ImageBitmapLoader: 'https://threejs.org/docs/#api/loaders/ImageBitmapLoader',
  290. ImageLoader: 'https://threejs.org/docs/#api/loaders/ImageLoader',
  291. JSONLoader: 'https://threejs.org/docs/#api/loaders/JSONLoader',
  292. Loader: 'https://threejs.org/docs/#api/loaders/Loader',
  293. LoaderUtils: 'https://threejs.org/docs/#api/loaders/LoaderUtils',
  294. MaterialLoader: 'https://threejs.org/docs/#api/loaders/MaterialLoader',
  295. ObjectLoader: 'https://threejs.org/docs/#api/loaders/ObjectLoader',
  296. TextureLoader: 'https://threejs.org/docs/#api/loaders/TextureLoader',
  297. DefaultLoadingManager: 'https://threejs.org/docs/#api/loaders/managers/DefaultLoadingManager',
  298. LoadingManager: 'https://threejs.org/docs/#api/loaders/managers/LoadingManager',
  299. LineBasicMaterial: 'https://threejs.org/docs/#api/materials/LineBasicMaterial',
  300. LineDashedMaterial: 'https://threejs.org/docs/#api/materials/LineDashedMaterial',
  301. Material: 'https://threejs.org/docs/#api/materials/Material',
  302. MeshBasicMaterial: 'https://threejs.org/docs/#api/materials/MeshBasicMaterial',
  303. MeshDepthMaterial: 'https://threejs.org/docs/#api/materials/MeshDepthMaterial',
  304. MeshLambertMaterial: 'https://threejs.org/docs/#api/materials/MeshLambertMaterial',
  305. MeshNormalMaterial: 'https://threejs.org/docs/#api/materials/MeshNormalMaterial',
  306. MeshPhongMaterial: 'https://threejs.org/docs/#api/materials/MeshPhongMaterial',
  307. MeshPhysicalMaterial: 'https://threejs.org/docs/#api/materials/MeshPhysicalMaterial',
  308. MeshStandardMaterial: 'https://threejs.org/docs/#api/materials/MeshStandardMaterial',
  309. MeshToonMaterial: 'https://threejs.org/docs/#api/materials/MeshToonMaterial',
  310. PointsMaterial: 'https://threejs.org/docs/#api/materials/PointsMaterial',
  311. RawShaderMaterial: 'https://threejs.org/docs/#api/materials/RawShaderMaterial',
  312. ShaderMaterial: 'https://threejs.org/docs/#api/materials/ShaderMaterial',
  313. ShadowMaterial: 'https://threejs.org/docs/#api/materials/ShadowMaterial',
  314. SpriteMaterial: 'https://threejs.org/docs/#api/materials/SpriteMaterial',
  315. Box2: 'https://threejs.org/docs/#api/math/Box2',
  316. Box3: 'https://threejs.org/docs/#api/math/Box3',
  317. Color: 'https://threejs.org/docs/#api/math/Color',
  318. Cylindrical: 'https://threejs.org/docs/#api/math/Cylindrical',
  319. Euler: 'https://threejs.org/docs/#api/math/Euler',
  320. Frustum: 'https://threejs.org/docs/#api/math/Frustum',
  321. Interpolant: 'https://threejs.org/docs/#api/math/Interpolant',
  322. Line3: 'https://threejs.org/docs/#api/math/Line3',
  323. Math: 'https://threejs.org/docs/#api/math/Math',
  324. Matrix3: 'https://threejs.org/docs/#api/math/Matrix3',
  325. Matrix4: 'https://threejs.org/docs/#api/math/Matrix4',
  326. Plane: 'https://threejs.org/docs/#api/math/Plane',
  327. Quaternion: 'https://threejs.org/docs/#api/math/Quaternion',
  328. Ray: 'https://threejs.org/docs/#api/math/Ray',
  329. Sphere: 'https://threejs.org/docs/#api/math/Sphere',
  330. Spherical: 'https://threejs.org/docs/#api/math/Spherical',
  331. Triangle: 'https://threejs.org/docs/#api/math/Triangle',
  332. Vector2: 'https://threejs.org/docs/#api/math/Vector2',
  333. Vector3: 'https://threejs.org/docs/#api/math/Vector3',
  334. Vector4: 'https://threejs.org/docs/#api/math/Vector4',
  335. CubicInterpolant: 'https://threejs.org/docs/#api/math/interpolants/CubicInterpolant',
  336. DiscreteInterpolant: 'https://threejs.org/docs/#api/math/interpolants/DiscreteInterpolant',
  337. LinearInterpolant: 'https://threejs.org/docs/#api/math/interpolants/LinearInterpolant',
  338. QuaternionLinearInterpolant: 'https://threejs.org/docs/#api/math/interpolants/QuaternionLinearInterpolant',
  339. Bone: 'https://threejs.org/docs/#api/objects/Bone',
  340. Group: 'https://threejs.org/docs/#api/objects/Group',
  341. Line: 'https://threejs.org/docs/#api/objects/Line',
  342. LineLoop: 'https://threejs.org/docs/#api/objects/LineLoop',
  343. LineSegments: 'https://threejs.org/docs/#api/objects/LineSegments',
  344. LOD: 'https://threejs.org/docs/#api/objects/LOD',
  345. Mesh: 'https://threejs.org/docs/#api/objects/Mesh',
  346. Points: 'https://threejs.org/docs/#api/objects/Points',
  347. Skeleton: 'https://threejs.org/docs/#api/objects/Skeleton',
  348. SkinnedMesh: 'https://threejs.org/docs/#api/objects/SkinnedMesh',
  349. Sprite: 'https://threejs.org/docs/#api/objects/Sprite',
  350. WebGLRenderer: 'https://threejs.org/docs/#api/renderers/WebGLRenderer',
  351. WebGLRenderTarget: 'https://threejs.org/docs/#api/renderers/WebGLRenderTarget',
  352. WebGLCubeRenderTarget: 'https://threejs.org/docs/#api/renderers/WebGLCubeRenderTarget',
  353. ShaderChunk: 'https://threejs.org/docs/#api/renderers/shaders/ShaderChunk',
  354. ShaderLib: 'https://threejs.org/docs/#api/renderers/shaders/ShaderLib',
  355. UniformsLib: 'https://threejs.org/docs/#api/renderers/shaders/UniformsLib',
  356. UniformsUtils: 'https://threejs.org/docs/#api/renderers/shaders/UniformsUtils',
  357. Fog: 'https://threejs.org/docs/#api/scenes/Fog',
  358. FogExp2: 'https://threejs.org/docs/#api/scenes/FogExp2',
  359. Scene: 'https://threejs.org/docs/#api/scenes/Scene',
  360. CanvasTexture: 'https://threejs.org/docs/#api/textures/CanvasTexture',
  361. CompressedTexture: 'https://threejs.org/docs/#api/textures/CompressedTexture',
  362. CubeTexture: 'https://threejs.org/docs/#api/textures/CubeTexture',
  363. DataTexture: 'https://threejs.org/docs/#api/textures/DataTexture',
  364. DepthTexture: 'https://threejs.org/docs/#api/textures/DepthTexture',
  365. Texture: 'https://threejs.org/docs/#api/textures/Texture',
  366. VideoTexture: 'https://threejs.org/docs/#api/textures/VideoTexture',
  367. CCDIKSolver: 'https://threejs.org/docs/#examples/animations/CCDIKSolver',
  368. MMDAnimationHelper: 'https://threejs.org/docs/#examples/animations/MMDAnimationHelper',
  369. MMDPhysics: 'https://threejs.org/docs/#examples/animations/MMDPhysics',
  370. OrbitControls: 'https://threejs.org/docs/#examples/controls/OrbitControls',
  371. ConvexBufferGeometry: 'https://threejs.org/docs/#examples/geometries/ConvexBufferGeometry',
  372. ConvexGeometry: 'https://threejs.org/docs/#examples/geometries/ConvexGeometry',
  373. DecalGeometry: 'https://threejs.org/docs/#examples/geometries/DecalGeometry',
  374. BabylonLoader: 'https://threejs.org/docs/#examples/loaders/BabylonLoader',
  375. GLTFLoader: 'https://threejs.org/docs/#examples/loaders/GLTFLoader',
  376. MMDLoader: 'https://threejs.org/docs/#examples/loaders/MMDLoader',
  377. MTLLoader: 'https://threejs.org/docs/#examples/loaders/MTLLoader',
  378. OBJLoader: 'https://threejs.org/docs/#examples/loaders/OBJLoader',
  379. OBJLoader2: 'https://threejs.org/docs/#examples/loaders/OBJLoader2',
  380. LoaderSupport: 'https://threejs.org/docs/#examples/loaders/LoaderSupport',
  381. PCDLoader: 'https://threejs.org/docs/#examples/loaders/PCDLoader',
  382. PDBLoader: 'https://threejs.org/docs/#examples/loaders/PDBLoader',
  383. SVGLoader: 'https://threejs.org/docs/#examples/loaders/SVGLoader',
  384. TGALoader: 'https://threejs.org/docs/#examples/loaders/TGALoader',
  385. PRWMLoader: 'https://threejs.org/docs/#examples/loaders/PRWMLoader',
  386. Lensflare: 'https://threejs.org/docs/#examples/objects/Lensflare',
  387. GLTFExporter: 'https://threejs.org/docs/#examples/exporters/GLTFExporter',
  388. });
  389. function getKeywordLink(keyword) {
  390. const dotNdx = keyword.indexOf('.');
  391. if (dotNdx) {
  392. const before = keyword.substring(0, dotNdx);
  393. const link = codeKeywordLinks[before];
  394. if (link) {
  395. return `${link}.${keyword.substr(dotNdx + 1)}`;
  396. }
  397. }
  398. return keyword.startsWith('THREE.')
  399. ? codeKeywordLinks[keyword.substring(6)]
  400. : codeKeywordLinks[keyword];
  401. }
  402. $('code').filter(function() {
  403. return getKeywordLink(this.textContent) &&
  404. this.parentElement.nodeName !== 'A';
  405. }).wrap(function() {
  406. const a = document.createElement('a');
  407. a.href = getKeywordLink(this.textContent);
  408. return a;
  409. });
  410. const methodPropertyRE = /^(\w+)\.(\w+)$/;
  411. const classRE = /^(\w+)$/;
  412. $('a').each(function() {
  413. const href = this.getAttribute('href');
  414. if (!href) {
  415. return;
  416. }
  417. const m = methodPropertyRE.exec(href);
  418. if (m) {
  419. const codeKeywordLink = getKeywordLink(m[1]);
  420. if (codeKeywordLink) {
  421. this.setAttribute('href', `${codeKeywordLink}#${m[2]}`);
  422. }
  423. } else if (classRE.test(href)) {
  424. const codeKeywordLink = getKeywordLink(href);
  425. if (codeKeywordLink) {
  426. this.setAttribute('href', codeKeywordLink);
  427. }
  428. }
  429. });
  430. $('pre>code')
  431. .unwrap()
  432. .replaceWith(function() {
  433. return $(`<pre class="prettyprint showlinemods notranslate ${this.className || ''}" translate="no">${this.innerHTML}</pre>`);
  434. });
  435. return dom.serialize();
  436. }
  437. const buildSettings = {
  438. outDir: 'out',
  439. baseUrl: 'https://threejsfundamentals.org',
  440. rootFolder: 'threejs',
  441. lessonGrep: 'threejs*.md',
  442. siteName: 'ThreeJSFundamentals',
  443. siteThumbnail: 'threejsfundamentals.jpg', // in rootFolder/lessons/resources
  444. templatePath: 'build/templates',
  445. owner: 'gfxfundamentals',
  446. repo: 'threejsfundamentals',
  447. thumbnailOptions: {
  448. thumbnailBackground: 'threejsfundamentals-background.jpg',
  449. text: [
  450. {
  451. font: 'bold 100px lesson-font',
  452. verticalSpacing: 100,
  453. offset: [100, 120],
  454. textAlign: 'left',
  455. shadowOffset: [15, 15],
  456. strokeWidth: 15,
  457. textWrapWidth: 1000,
  458. },
  459. {
  460. font: 'bold 60px lesson-font',
  461. text: 'threejsfundamentals.org',
  462. verticalSpacing: 100,
  463. offset: [-100, -90],
  464. textAlign: 'right',
  465. shadowOffset: [8, 8],
  466. strokeWidth: 15,
  467. textWrapWidth: 1000,
  468. color: 'hsl(340, 100%, 70%)',
  469. },
  470. ],
  471. },
  472. postHTMLFn: fixThreeJSLinks,
  473. };
  474. // just the hackiest way to get this working.
  475. grunt.registerMultiTask('buildlesson', 'build a lesson', function() {
  476. const filenames = new Set();
  477. this.files.forEach((files) => {
  478. files.src.forEach((filename) => {
  479. filenames.add(filename);
  480. });
  481. });
  482. const buildStuff = require('@gfxfundamentals/lesson-builder');
  483. const settings = {...buildSettings, filenames};
  484. const finish = this.async();
  485. buildStuff(settings).finally(finish);
  486. });
  487. grunt.registerTask('buildlessons', function() {
  488. const buildStuff = require('@gfxfundamentals/lesson-builder');
  489. const finish = this.async();
  490. buildStuff(buildSettings).finally(finish);
  491. });
  492. grunt.task.registerMultiTask('fixthreepaths', 'fix three paths', function() {
  493. const options = this.options({});
  494. const oldVersionRE = new RegExp(`/${options.oldVersionStr}/`, 'g');
  495. const newVersionReplacement = `/${options.newVersionStr}/`;
  496. this.files.forEach((files) => {
  497. files.src.forEach((filename) => {
  498. const oldContent = fs.readFileSync(filename, {encoding: 'utf8'});
  499. const newContent = oldContent.replace(oldVersionRE, newVersionReplacement);
  500. if (oldContent !== newContent) {
  501. grunt.log.writeln(`updating ${filename} to ${options.newVersionStr}`);
  502. fs.writeFileSync(filename, newContent);
  503. }
  504. });
  505. });
  506. });
  507. grunt.registerTask('bumpthree', function() {
  508. const lessonInfo = JSON.parse(fs.readFileSync('package.json', {encoding: 'utf8'}));
  509. const oldVersion = lessonInfo.threejsfundamentals.threeVersion;
  510. const oldVersionStr = `r${oldVersion}`;
  511. const threePath = path.dirname(path.dirname(require.resolve('three')));
  512. const threeInfo = JSON.parse(fs.readFileSync(path.join(threePath, 'package.json'), {encoding: 'utf8'}));
  513. const newVersion = semver.minor(threeInfo.version);
  514. const newVersionStr = `r${newVersion}`;
  515. const basePath = path.join('threejs', 'resources', 'threejs', newVersionStr);
  516. grunt.config.merge({
  517. copy: {
  518. threejs: {
  519. files: [
  520. { expand: true, cwd: `${threePath}/build/`, src: 'three.js', dest: `${basePath}/build/`, },
  521. { expand: true, cwd: `${threePath}/build/`, src: 'three.min.js', dest: `${basePath}/build/`, },
  522. { expand: true, cwd: `${threePath}/build/`, src: 'three.module.js', dest: `${basePath}/build/`, },
  523. { expand: true, cwd: `${threePath}/examples/js/`, src: '**', dest: `${basePath}/examples/js/`, },
  524. { expand: true, cwd: `${threePath}/examples/jsm/`, src: '**', dest: `${basePath}/examples/jsm/`, },
  525. ],
  526. },
  527. },
  528. fixthreepaths: {
  529. options: {
  530. oldVersionStr,
  531. newVersionStr,
  532. },
  533. src: [
  534. 'threejs/**/*.html',
  535. 'threejs/**/*.md',
  536. 'threejs/**/*.js',
  537. '!threejs/resources/threejs/**',
  538. ],
  539. },
  540. });
  541. lessonInfo.threejsfundamentals.threeVersion = newVersion;
  542. fs.writeFileSync('package.json', JSON.stringify(lessonInfo, null, 2));
  543. grunt.task.run(['copy:threejs', 'fixthreepaths']);
  544. });
  545. grunt.registerTask('build', ['clean', 'copy:main', 'buildlessons']);
  546. grunt.registerTask('buildwatch', ['build', 'watch']);
  547. grunt.registerTask('default', ['eslint', 'build']);
  548. };