diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 662851b..b7da880 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -12,27 +12,33 @@ on: jobs: macos-browser-test: + strategy: + matrix: + node-version: ["17.x", "18.x"] runs-on: macos-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: - node-version: 14.x + node-version: ${{ matrix.node-version }} - uses: browser-actions/setup-chromium@latest - uses: browser-actions/setup-firefox@latest - run: npm install - run: npm run test windows-browser-test: + strategy: + matrix: + node-version: ["17.x", "18.x"] runs-on: windows-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: - node-version: 14.x + node-version: ${{ matrix.node-version }} - uses: browser-actions/setup-chromium@latest - uses: browser-actions/setup-firefox@latest with: - firefox-version: "84.0" + firefox-version: "90.0" - run: npm install - - run: npm run test \ No newline at end of file + - run: npm run test diff --git a/jest.config.js b/jest.config.js index 1a89874..5873275 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,3 +1,6 @@ module.exports = { - "setupFilesAfterEnv": ["./jest.setup.js"] -}; \ No newline at end of file + "setupFilesAfterEnv": ["./jest.setup.js"], + "moduleNameMapper": { + "^\\@/(.+)": "/src/$1" + } +}; diff --git a/jsdoc.conf.js b/jsdoc.conf.js index 9950383..3222f06 100644 --- a/jsdoc.conf.js +++ b/jsdoc.conf.js @@ -1,8 +1,5 @@ "use strict"; -// init => npm install -g jsdoc -// command => jsdoc -c ./jsdoc.conf.js -r ./src DOCS.md - module.exports = { "plugins": [ "plugins/markdown" diff --git a/package.json b/package.json index f4956d3..a51fbe9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@next2d/framework", - "description": "Next2D Framework", - "version": "1.3.0", + "description": "It is a framework dedicated to Next2D that enables scene management by URL (SPA), which has been difficult with conventional Canvas/WebGL applications, and simplifies readability and shareability by fixing the development pattern (MVVM).", + "version": "1.4.0", "homepage": "https://next2d.app", "bugs": "https://github.com/Next2D/Framework/issues/new", "author": "Toshiyuki Ienaga ", @@ -15,20 +15,22 @@ "start": "webpack serve", "lint": "eslint src/**/*.js", "build": "webpack --mode production", - "test": "npx jest" + "test": "npx jest", + "jsdoc": "jsdoc -c jsdoc.conf.js -r src DOCS.md" }, "repository": { "type": "git", "url": "git+https://github.com/Next2D/Framework.git" }, "devDependencies": { - "@babel/core": "^7.18.13", - "@babel/preset-env": "^7.18.10", - "@next2d/jsdoc-template": "^1.0.3", - "eslint": "^8.22.0", + "@babel/core": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@next2d/jsdoc-template": "^1.0.7", + "eslint": "^8.36.0", "eslint-webpack-plugin": "^3.2.0", - "webpack": "^5.74.0", + "jsdoc": "^4.0.2", + "webpack": "^5.76.1", "webpack-cli": "^4.10.0", - "webpack-dev-server": "^4.10.0" + "webpack-dev-server": "^4.12.0" } } diff --git a/src/Application.js b/src/Application.js index 4943756..2a4887f 100644 --- a/src/Application.js +++ b/src/Application.js @@ -86,6 +86,7 @@ export class Application extends Model * constructorが起動した後にコールされます。(初回起動時のみコールされます。) * Called after the constructor is invoked. (Called only the first time it is invoked.) * @return {void} + * @method * @abstract */ // eslint-disable-next-line no-empty-function @@ -103,88 +104,95 @@ export class Application extends Model */ gotoView (name = null) { + const promises = []; if (this.config.loading) { - this._$createSnapshot(); + promises.push(this._$createSnapshot()); this._$startLoading(); } - if (this.query.length) { - this.query.clear(); - } - - let query = ""; - if (!name && location.search) { - query = location.search; - const parameters = query.slice(1).split("&"); - for (let idx = 0; idx < parameters.length; ++idx) { - const pair = parameters[idx].split("="); - this.query.set(pair[0], pair[1]); - } - } + Promise + .all(promises) + .then(() => + { + if (this.query.length) { + this.query.clear(); + } - if (!name) { - name = location.pathname.slice(1); - if (name) { - const routing = this.config.routing[name]; - if (routing && routing.private) { - name = routing.redirect || "top"; + let query = ""; + if (!name && location.search) { + query = location.search; + const parameters = query.slice(1).split("&"); + for (let idx = 0; idx < parameters.length; ++idx) { + const pair = parameters[idx].split("="); + this.query.set(pair[0], pair[1]); + } } - } - if (!name) { - name = "top"; - } - } + if (!name) { + name = location.pathname.slice(1); + if (name) { + const routing = this.config.routing[name]; + if (routing && routing.private) { + name = routing.redirect || "top"; + } + } - if (name.indexOf("?") > -1) { + if (!name) { + name = "top"; + } + } - const names = name.split("?"); + if (name.indexOf("?") > -1) { - name = names[0]; - query = `?${names[1]}`; + const names = name.split("?"); - const parameters = names[1].split("&"); - for (let idx = 0; idx < parameters.length; ++idx) { - const pair = parameters[idx].split("="); - this.query.set(pair[0], pair[1]); - } - } + name = names[0]; + query = `?${names[1]}`; - if (name.slice(0, 1) === ".") { - name = name.split("/").slice(1).join("/") || "top"; - } + const parameters = names[1].split("&"); + for (let idx = 0; idx < parameters.length; ++idx) { + const pair = parameters[idx].split("="); + this.query.set(pair[0], pair[1]); + } + } - if (this.config.spa && !this._$popstate) { - const url = name === "top" - ? `${location.origin}${location.search}` - : `${location.origin}/${name}${query}`; + if (name.slice(0, 1) === ".") { + name = name.split("/").slice(1).join("/") || "top"; + } - history.pushState("", "", url); - } + if (this.config.spa && !this._$popstate) { + const url = name === "top" + ? `${location.origin}${location.search}` + : `${location.origin}/${name}${query}`; - // update - this._$popstate = false; + history.pushState("", "", url); + } - if (name.indexOf("@") > -1) { - name = name.replace("@", ""); - } + // update + this._$popstate = false; - Promise - .all(this._$requests(name)) - .then((responses) => - { - return Promise.resolve(this.context.addChild(name, responses)); - }) - .then((view) => - { - if ("gotoView" in this.config) { - this._$callback(this.config.gotoView.callback, view); + if (name.indexOf("@") > -1) { + name = name.replace("@", ""); } + + Promise + .all(this._$requests(name)) + .then((responses) => + { + return Promise.resolve(this.context.addChild(name, responses)); + }) + .then((view) => + { + if ("gotoView" in this.config) { + this._$callback(this.config.gotoView.callback, view); + } + }); }); } /** - * @return {void} + * @return {Promise} + * @method * @private */ _$createSnapshot () @@ -204,60 +212,73 @@ export class Application extends Model const player = root.stage._$player; const matrix = player._$matrix; - const drawMatrix = new Matrix( matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5] ); - bitmapData.draw(root, drawMatrix); + return new Promise((resolve) => + { + bitmapData.draw(root, drawMatrix, null, null, (canvas) => + { + // remove all + while (root.numChildren) { + root.removeChild(root.getChildAt(0)); + } + + if (root._$created) { + root._$created = false; + root._$createWorkerInstance(); + } - // remove all - while (root.numChildren) { - root.removeChild(root.getChildAt(0)); - } + bitmapData.canvas = canvas; + + const sprite = root.addChild(new Sprite()); + sprite.x = -matrix[4] / matrix[0]; + sprite.y = -matrix[5] / matrix[3]; + sprite.scaleX = 1 / matrix[0]; + sprite.scaleY = 1 / matrix[3]; + + sprite + .addChild(new Shape()) + .graphics + .beginBitmapFill(bitmapData) + .drawRect(0, 0, bitmapData.width, bitmapData.height) + .endFill(); + + const width = this.config.stage.width; + const height = this.config.stage.height; + + const mask = root.addChild(new Shape()); + mask + .graphics + .beginFill(0, 0.8) + .drawRect(0, 0, width, height) + .endFill(); + + const tx = matrix[4]; + if (tx) { + const scaleX = matrix[0]; + mask.scaleX = (width + tx * 2 / scaleX) / width; + mask.x = -tx / scaleX; + } - const sprite = root.addChild(new Sprite()); - sprite.x = -matrix[4] / matrix[0]; - sprite.y = -matrix[5] / matrix[3]; - sprite.scaleX = 1 / matrix[0]; - sprite.scaleY = 1 / matrix[3]; - - const snapshot = sprite.addChild(new Shape()); - snapshot - .graphics - .beginBitmapFill(bitmapData) - .drawRect(0, 0, bitmapData.width, bitmapData.height) - .endFill(); - - const width = this.config.stage.width; - const height = this.config.stage.height; - - const mask = root.addChild(new Shape()); - mask - .graphics - .beginFill(0, 0.8) - .drawRect(0, 0, width, height) - .endFill(); - - const tx = matrix[4]; - if (tx) { - const scaleX = matrix[0]; - mask.scaleX = (width + tx * 2 / scaleX) / width; - mask.x = -tx / scaleX; - } + const ty = matrix[5]; + if (ty) { + const scaleY = matrix[3]; + mask.scaleY = (height + ty * 2 / scaleY) / height; + mask.y = -ty / scaleY; + } - const ty = matrix[5]; - if (ty) { - const scaleY = matrix[3]; - mask.scaleY = (height + ty * 2 / scaleY) / height; - mask.y = -ty / scaleY; - } + return resolve(); + }); + }); } /** * @return {void} + * @method * @private */ _$startLoading () @@ -509,6 +530,7 @@ export class Application extends Model * @param {string|array} [callback=null] * @param {*} [value=null] * @return {void} + * @method * @private */ _$callback (callback = null, value = null) @@ -536,6 +558,7 @@ export class Application extends Model /** * @param {string} [value=null] * @return {string} + * @method * @private */ _$parseConfig (value) diff --git a/src/Context.js b/src/Context.js index 905a589..6530c58 100644 --- a/src/Context.js +++ b/src/Context.js @@ -168,7 +168,8 @@ export class Context * * @param {string} name * @param {array} responses - * @return {ViewModel|null} + * @return {Promise} + * @method * @public */ addChild (name, responses) @@ -190,7 +191,7 @@ export class Context if (!next2d.fw.packages.has(viewName) || !next2d.fw.packages.has(viewModelName) ) { - return null; + return Promise.resolve(); } if (next2d.fw.response.size) { @@ -216,18 +217,19 @@ export class Context this._$viewModel = new ViewModelClass(); return Promise - .resolve(this._$viewModel.bind(this._$view)) + .all([this._$viewModel.bind(this._$view)]) .then(() => { if (next2d.fw.config.loading) { this._$endLoading(); } - while (this._$root.numChildren) { - this._$root.removeChild(this._$root.getChildAt(0)); + const root = this._$root; + while (root.numChildren) { + root.removeChild(root.getChildAt(0)); } - return this._$root.addChild(this._$view); + return root.addChild(this._$view); }) .catch((error) => { diff --git a/src/Util.js b/src/Util.js index 1cc2406..592dfe2 100644 --- a/src/Util.js +++ b/src/Util.js @@ -1,19 +1,20 @@ /** * @type {object} */ -export const Util = { - /** - * @description ユニークな値を返却します。 - * Returns a unique value. - * - * @return {string} - * @static - * @method - */ - "uniqid": () => - { - const sec = Date.now() * 1000 + Math.random() * 1000; - const id = sec.toString(16).replace(/\./g, "").padEnd(14, "0"); - return `${id}-${Math.trunc(Math.random() * 10000)}-${Math.trunc(Math.random() * 10000)}`; - } -}; \ No newline at end of file +export const Util = {}; + +/** + * @description ユニークな値を返却します。 + * Returns a unique value. + * + * @return {string} + * @static + * @method + */ +Util.uniqid = () => +{ + const sec = Date.now() * 1000 + Math.random() * 1000; + const id = sec.toString(16).replace(/\./g, "").padEnd(14, "0"); + return `${id}-${Math.trunc(Math.random() * 10000)}-${Math.trunc(Math.random() * 10000)}`; +}; + diff --git a/src/content/Content.js b/src/content/Content.js index 1b00087..b306d8e 100644 --- a/src/content/Content.js +++ b/src/content/Content.js @@ -40,8 +40,9 @@ export class Content extends MovieClip * Called after the constructor is invoked. * * @return {void} + * @method * @abstract */ // eslint-disable-next-line no-empty-function initialize () {} -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js index 8544b79..2cf49f0 100644 --- a/src/index.js +++ b/src/index.js @@ -37,4 +37,4 @@ if (!("fw" in window.next2d)) { "color: #fff; background: #4bc729", ""); -} \ No newline at end of file +} diff --git a/src/model/callback/Loading.js b/src/model/callback/Loading.js index da619b7..9844f01 100644 --- a/src/model/callback/Loading.js +++ b/src/model/callback/Loading.js @@ -8,6 +8,7 @@ export class Loading extends Model { /** * @return {void} + * @method * @public */ start () @@ -88,6 +89,7 @@ export class Loading extends Model /** * @return {void} + * @method * @public */ end () @@ -99,4 +101,4 @@ export class Loading extends Model element.style.display = "none"; } } -} \ No newline at end of file +} diff --git a/src/model/common/Model.js b/src/model/common/Model.js index 7ee18f6..c9bdc83 100644 --- a/src/model/common/Model.js +++ b/src/model/common/Model.js @@ -25,6 +25,7 @@ export class Model /** * @param {object} schema * @return {string} + * @method * @public */ toJSON (schema) diff --git a/src/screen/ScreenSheet.js b/src/screen/ScreenSheet.js new file mode 100644 index 0000000..795ac77 --- /dev/null +++ b/src/screen/ScreenSheet.js @@ -0,0 +1,23 @@ +import { Model } from "../model/common/Model"; + +/** + * スクリーンのサイズ変化に合わせて表示をコントロール + * Controls display as screen size changes. + * + * @class + * @extends {Model} + */ +export class ScreenSheet extends Model +{ + /** + * @description ページに適用するJSONのパスをセットする + * + * @param {string} path + * @return {void} + * @public + */ + static use (path) + { + console.log(path); + } +} diff --git a/src/view/View.js b/src/view/View.js index 5575c8b..58a7906 100644 --- a/src/view/View.js +++ b/src/view/View.js @@ -24,8 +24,9 @@ export class View extends MovieClip * Called after the constructor is invoked. * * @return {void} + * @method * @abstract */ // eslint-disable-next-line no-empty-function initialize () {} -} \ No newline at end of file +} diff --git a/src/view/ViewModel.js b/src/view/ViewModel.js index 599bfa4..9fc1138 100644 --- a/src/view/ViewModel.js +++ b/src/view/ViewModel.js @@ -45,7 +45,7 @@ export class ViewModel extends Model { return new Promise((resolve) => { - requestAnimationFrame(() => { resolve() }); + requestAnimationFrame(resolve); }); } } diff --git a/webpack.config.js b/webpack.config.js index b0ca655..055389c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -6,7 +6,7 @@ module.exports = { "entry": "./src/index.js", "output": { "filename": "next2d-framework.js", - "path": path.join(__dirname, "/") + "path": path.resolve(__dirname, "/") }, "plugins": [ new ESLintPlugin({ @@ -15,9 +15,9 @@ module.exports = { ], "devServer": { "static": { - "directory": path.join(__dirname, "dist") + "directory": path.resolve(__dirname, "dist") }, "compress": false, "open": true } -}; \ No newline at end of file +};