From 15b24a1f840725c5c4651665351668feeeb2c4b2 Mon Sep 17 00:00:00 2001 From: Tofandel Date: Tue, 8 Feb 2022 00:39:06 +0100 Subject: [PATCH] Add webpack plugin update deps and compile with gulp-typescript (no need for babel) --- .gitignore | 3 +- Resources/doc/installation.rst | 6 + Resources/doc/usage.rst | 16 +- Resources/gulpfile.js | 16 +- Resources/js/router.template.js | 2 +- Resources/package.json | 33 +- Resources/public/js/router.js | 587 +++++++++++++----------------- Resources/public/js/router.min.js | 2 +- Resources/webpack/FosRouting.js | 96 +++++ 9 files changed, 397 insertions(+), 364 deletions(-) create mode 100644 Resources/webpack/FosRouting.js diff --git a/.gitignore b/.gitignore index b6fb3940..90cea6e3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ /vendor/ /node_modules/ /.phpunit/ -/.phpunit.result.cache \ No newline at end of file +/.phpunit.result.cache +.idea diff --git a/Resources/doc/installation.rst b/Resources/doc/installation.rst index c130243e..c829ef37 100644 --- a/Resources/doc/installation.rst +++ b/Resources/doc/installation.rst @@ -55,3 +55,9 @@ Execute the following command to publish the assets required by the bundle: $ php bin/console assets:install --symlink public .. _`installation chapter`: https://getcomposer.org/doc/00-intro.md + +Step 5: If you are using webpack, install the npm package locally +----------------------------------------------------------------- +.. code-block:: bash + + $ yarn add -D ./vendor/friendsofsymfony/jsrouting-bundle/Resources/ diff --git a/Resources/doc/usage.rst b/Resources/doc/usage.rst index 6d644e52..7c6688f3 100644 --- a/Resources/doc/usage.rst +++ b/Resources/doc/usage.rst @@ -23,12 +23,24 @@ In applications not using webpack add these two lines in your layout: the two JavaScript files above loaded at some point in your web page. -If you are using webpack and Encore to package your assets you will need to use the dump command +If you are using webpack and Encore to package your assets you can use the webpack plugin included in this package + +.. code-block:: js + + const FosRouting = require('fos-router/webpack/FosRouting'); + //... + Encore + .addPlugin(new FosRouting()) + +Then use it simply by importing ``import Routing from 'fos-router';`` in your js or ts code + + +Alternatively you can use the dump command and export your routes to json, this command will create a json file into the ``web/js`` folder: .. code-block:: bash - bin/console fos:js-routing:dump --format=json + bin/console fos:js-routing:dump --format=json --target=assets/js/routes.json If you are using Flex, probably you want to dump your routes into the ``public`` folder instead of ``web``, to achieve this you can set the ``target`` parameter: diff --git a/Resources/gulpfile.js b/Resources/gulpfile.js index 2157266b..7abc1b79 100755 --- a/Resources/gulpfile.js +++ b/Resources/gulpfile.js @@ -1,15 +1,19 @@ const gulp = require('gulp'); -const babel = require('gulp-babel'); const rename = require('gulp-rename'); const uglify = require('gulp-uglify'); const wrap = require('gulp-wrap'); +const ts = require('gulp-typescript') -gulp.task('js', function() { +gulp.task('ts', function() { return gulp.src('js/router.ts') - .pipe(babel({ - presets: ["@babel/preset-env", "@babel/preset-typescript"], - plugins: ["@babel/plugin-transform-object-assign"] + .pipe(ts({ + noImplicitAny: true, })) + .pipe(gulp.dest('public/js')); +}); + +gulp.task('min', function() { + return gulp.src('public/js/!(*.min).js') .pipe(wrap({ src: 'js/router.template.js' })) .pipe(gulp.dest('public/js')) .pipe(rename({ extname: '.min.js' })) @@ -17,4 +21,4 @@ gulp.task('js', function() { .pipe(gulp.dest('public/js')); }); -gulp.task('default', gulp.series('js')); +gulp.task('default', gulp.series('ts', 'min')); diff --git a/Resources/js/router.template.js b/Resources/js/router.template.js index 9759f792..3cf6c2a4 100644 --- a/Resources/js/router.template.js +++ b/Resources/js/router.template.js @@ -19,5 +19,5 @@ var exports = {}; <%= contents %> - return { Router: Router, Routing: Routing }; + return { Router: exports.Router, Routing: exports.Routing }; })); diff --git a/Resources/package.json b/Resources/package.json index 73a84b9a..3a719647 100755 --- a/Resources/package.json +++ b/Resources/package.json @@ -1,6 +1,6 @@ { "name": "fos-router", - "version": "2.2.0", + "version": "2.4.3", "description": "A pretty nice way to use the routes generated by the FOSJsRoutingBundle in your JavaScript.", "keywords": [ "router", @@ -23,33 +23,32 @@ ], "main": "public/js/router.js", "files": [ + "webpack/FosRouting.js", "public/js/router.js", "public/js/router.min.js", "ts/router.d.ts" ], "types": "ts/router.d.ts", "devDependencies": { - "@babel/core": "^7.14.0", - "@babel/plugin-transform-object-assign": "^7.12.13", - "@babel/polyfill": "^7.12.1", - "@babel/preset-env": "^7.14.1", - "@babel/preset-typescript": "^7.13.0", - "@types/node": "^14.14.44", - "google-closure-library": "^20171203.0.0", + "@types/node": "^14.18.10", + "google-closure-library": "^20220104.0.0", "gulp": "^4.0.2", - "gulp-babel": "^8.0.0", - "gulp-rename": "^1.2.2", - "gulp-uglify": "^1.5.4", - "gulp-wrap": "^0.13.0", - "jasmine": "^2.4.1", - "tsd": "^0.14.0", - "typescript": "^4.2.4" + "gulp-rename": "^2.0.0", + "gulp-uglify": "^3.0.2", + "gulp-typescript": "^6.0.0-alpha.1", + "gulp-wrap": "^0.15.0", + "jasmine": "^4.0.2", + "tsd": "^0.19.1", + "typescript": "^4.5.5" }, "scripts": { "build": "gulp && npm run build:types", "build:types": "tsc --declaration --emitDeclarationOnly", "test": "npm run build && npm run test:types && phantomjs js/run_jsunit.js js/router_test.html", - "test:types": "tsd" + "test:types": "tsd", + "prepublish": "npm run build" }, - "dependencies": {} + "dependencies": { + "webpack-inject-plugin": "^1.5.5" + } } diff --git a/Resources/public/js/router.js b/Resources/public/js/router.js index 311dec5d..0d1c9112 100644 --- a/Resources/public/js/router.js +++ b/Resources/public/js/router.js @@ -1,368 +1,283 @@ -(function (root, factory) { - var routing = factory(); - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define([], routing.Routing); - } else if (typeof module === 'object' && module.exports) { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = routing.Routing; - } else { - // Browser globals (root is window) - root.Routing = routing.Routing; - root.fos = { - Router: routing.Router - }; - } -}(this, function () { - var exports = {}; +(function (root, factory) { + var routing = factory(); + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], routing.Routing); + } else if (typeof module === 'object' && module.exports) { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = routing.Routing; + } else { + // Browser globals (root is window) + root.Routing = routing.Routing; + root.fos = { + Router: routing.Router + }; + } +}(this, function () { + var exports = {}; "use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports["default"] = exports.Routing = exports.Router = void 0; - -function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } - -function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } - -function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } - -var Router = /*#__PURE__*/function () { - function Router(context, routes) { - _classCallCheck(this, Router); - - this.context_ = context || { - base_url: '', - prefix: '', - host: '', - port: '', - scheme: '', - locale: '' - }; - this.setRoutes(routes || {}); - } - - _createClass(Router, [{ - key: "setRoutingData", - value: function setRoutingData(data) { - this.setBaseUrl(data['base_url']); - this.setRoutes(data['routes']); - - if (typeof data.prefix !== 'undefined') { - this.setPrefix(data['prefix']); - } - - if (typeof data.port !== 'undefined') { - this.setPort(data['port']); - } - - if (typeof data.locale !== 'undefined') { - this.setLocale(data['locale']); - } - - this.setHost(data['host']); - - if (typeof data.scheme !== 'undefined') { - this.setScheme(data['scheme']); - } - } - }, { - key: "setRoutes", - value: function setRoutes(routes) { - this.routes_ = Object.freeze(routes); - } - }, { - key: "getRoutes", - value: function getRoutes() { - return this.routes_; - } - }, { - key: "setBaseUrl", - value: function setBaseUrl(baseUrl) { - this.context_.base_url = baseUrl; - } - }, { - key: "getBaseUrl", - value: function getBaseUrl() { - return this.context_.base_url; - } - }, { - key: "setPrefix", - value: function setPrefix(prefix) { - this.context_.prefix = prefix; - } - }, { - key: "setScheme", - value: function setScheme(scheme) { - this.context_.scheme = scheme; - } - }, { - key: "getScheme", - value: function getScheme() { - return this.context_.scheme; - } - }, { - key: "setHost", - value: function setHost(host) { - this.context_.host = host; - } - }, { - key: "getHost", - value: function getHost() { - return this.context_.host; - } - }, { - key: "setPort", - value: function setPort(port) { - this.context_.port = port; - } - }, { - key: "getPort", - value: function getPort() { - return this.context_.port; - } - }, { - key: "setLocale", - value: function setLocale(locale) { - this.context_.locale = locale; - } - }, { - key: "getLocale", - value: function getLocale() { - return this.context_.locale; +exports.__esModule = true; +exports.Routing = exports.Router = void 0; +var Router = /** @class */ (function () { + function Router(context, routes) { + this.context_ = context || { base_url: '', prefix: '', host: '', port: '', scheme: '', locale: '' }; + this.setRoutes(routes || {}); } - }, { - key: "buildQueryParams", - value: + Router.getInstance = function () { + return exports.Routing; + }; + Router.setData = function (data) { + var router = Router.getInstance(); + router.setRoutingData(data); + }; + Router.prototype.setRoutingData = function (data) { + this.setBaseUrl(data['base_url']); + this.setRoutes(data['routes']); + if (typeof data.prefix !== 'undefined') { + this.setPrefix(data['prefix']); + } + if (typeof data.port !== 'undefined') { + this.setPort(data['port']); + } + if (typeof data.locale !== 'undefined') { + this.setLocale(data['locale']); + } + this.setHost(data['host']); + if (typeof data.scheme !== 'undefined') { + this.setScheme(data['scheme']); + } + }; + Router.prototype.setRoutes = function (routes) { + this.routes_ = Object.freeze(routes); + }; + Router.prototype.getRoutes = function () { + return this.routes_; + }; + Router.prototype.setBaseUrl = function (baseUrl) { + this.context_.base_url = baseUrl; + }; + Router.prototype.getBaseUrl = function () { + return this.context_.base_url; + }; + Router.prototype.setPrefix = function (prefix) { + this.context_.prefix = prefix; + }; + Router.prototype.setScheme = function (scheme) { + this.context_.scheme = scheme; + }; + Router.prototype.getScheme = function () { + return this.context_.scheme; + }; + Router.prototype.setHost = function (host) { + this.context_.host = host; + }; + Router.prototype.getHost = function () { + return this.context_.host; + }; + Router.prototype.setPort = function (port) { + this.context_.port = port; + }; + Router.prototype.getPort = function () { + return this.context_.port; + }; + ; + Router.prototype.setLocale = function (locale) { + this.context_.locale = locale; + }; + Router.prototype.getLocale = function () { + return this.context_.locale; + }; + ; /** * Builds query string params added to a URL. * Port of jQuery's $.param() function, so credit is due there. */ - function buildQueryParams(prefix, params, add) { - var _this = this; - - var name; - var rbracket = new RegExp(/\[\]$/); - - if (params instanceof Array) { - params.forEach(function (val, i) { - if (rbracket.test(prefix)) { - add(prefix, val); - } else { - _this.buildQueryParams(prefix + '[' + (_typeof(val) === 'object' ? i : '') + ']', val, add); - } - }); - } else if (_typeof(params) === 'object') { - for (name in params) { - this.buildQueryParams(prefix + '[' + name + ']', params[name], add); + Router.prototype.buildQueryParams = function (prefix, params, add) { + var _this = this; + var name; + var rbracket = new RegExp(/\[\]$/); + if (params instanceof Array) { + params.forEach(function (val, i) { + if (rbracket.test(prefix)) { + add(prefix, val); + } + else { + _this.buildQueryParams(prefix + '[' + (typeof val === 'object' ? i : '') + ']', val, add); + } + }); } - } else { - add(prefix, params); - } - } + else if (typeof params === 'object') { + for (name in params) { + this.buildQueryParams(prefix + '[' + name + ']', params[name], add); + } + } + else { + add(prefix, params); + } + }; /** * Returns a raw route object. */ - - }, { - key: "getRoute", - value: function getRoute(name) { - var prefixedName = this.context_.prefix + name; - var sf41i18nName = name + '.' + this.context_.locale; - var prefixedSf41i18nName = this.context_.prefix + name + '.' + this.context_.locale; - var variants = [prefixedName, sf41i18nName, prefixedSf41i18nName, name]; - - for (var i in variants) { - if (variants[i] in this.routes_) { - return this.routes_[variants[i]]; + Router.prototype.getRoute = function (name) { + var prefixedName = this.context_.prefix + name; + var sf41i18nName = name + '.' + this.context_.locale; + var prefixedSf41i18nName = this.context_.prefix + name + '.' + this.context_.locale; + var variants = [prefixedName, sf41i18nName, prefixedSf41i18nName, name]; + for (var i in variants) { + if (variants[i] in this.routes_) { + return this.routes_[variants[i]]; + } } - } - - throw new Error('The route "' + name + '" does not exist.'); - } + throw new Error('The route "' + name + '" does not exist.'); + }; /** * Generates the URL for a route. */ - - }, { - key: "generate", - value: function generate(name, opt_params, absolute) { - var route = this.getRoute(name); - var params = opt_params || {}; - - var unusedParams = _extends({}, params); - - var url = ''; - var optional = true; - var host = ''; - var port = typeof this.getPort() == 'undefined' || this.getPort() === null ? '' : this.getPort(); - route.tokens.forEach(function (token) { - if ('text' === token[0] && typeof token[1] === 'string') { - url = Router.encodePathComponent(token[1]) + url; - optional = false; - return; + Router.prototype.generate = function (name, opt_params, absolute) { + var route = (this.getRoute(name)); + var params = opt_params || {}; + var unusedParams = Object.assign({}, params); + var url = ''; + var optional = true; + var host = ''; + var port = (typeof this.getPort() == 'undefined' || this.getPort() === null) ? '' : this.getPort(); + route.tokens.forEach(function (token) { + if ('text' === token[0] && typeof token[1] === 'string') { + url = Router.encodePathComponent(token[1]) + url; + optional = false; + return; + } + if ('variable' === token[0]) { + if (token.length === 6 && token[5] === true) { // Sixth part of the token array indicates if it should be included in case of defaults + optional = false; + } + var hasDefault = route.defaults && !Array.isArray(route.defaults) && typeof token[3] === 'string' && (token[3] in route.defaults); + if (false === optional || !hasDefault || ((typeof token[3] === 'string' && token[3] in params) && !Array.isArray(route.defaults) && params[token[3]] != route.defaults[token[3]])) { + var value = void 0; + if (typeof token[3] === 'string' && token[3] in params) { + value = params[token[3]]; + delete unusedParams[token[3]]; + } + else if (typeof token[3] === 'string' && hasDefault && !Array.isArray(route.defaults)) { + value = route.defaults[token[3]]; + } + else if (optional) { + return; + } + else { + throw new Error('The route "' + name + '" requires the parameter "' + token[3] + '".'); + } + var empty = true === value || false === value || '' === value; + if (!empty || !optional) { + var encodedValue = Router.encodePathComponent(value); + if ('null' === encodedValue && null === value) { + encodedValue = ''; + } + url = token[1] + encodedValue + url; + } + optional = false; + } + else if (hasDefault && (typeof token[3] === 'string' && token[3] in unusedParams)) { + delete unusedParams[token[3]]; + } + return; + } + throw new Error('The token type "' + token[0] + '" is not supported.'); + }); + if (url === '') { + url = '/'; } - - if ('variable' === token[0]) { - if (token.length === 6 && token[5] === true) { - // Sixth part of the token array indicates if it should be included in case of defaults - optional = false; - } - - var hasDefault = route.defaults && !Array.isArray(route.defaults) && typeof token[3] === 'string' && token[3] in route.defaults; - - if (false === optional || !hasDefault || typeof token[3] === 'string' && token[3] in params && !Array.isArray(route.defaults) && params[token[3]] != route.defaults[token[3]]) { + route.hosttokens.forEach(function (token) { var value; - - if (typeof token[3] === 'string' && token[3] in params) { - value = params[token[3]]; - delete unusedParams[token[3]]; - } else if (typeof token[3] === 'string' && hasDefault && !Array.isArray(route.defaults)) { - value = route.defaults[token[3]]; - } else if (optional) { - return; - } else { - throw new Error('The route "' + name + '" requires the parameter "' + token[3] + '".'); + if ('text' === token[0]) { + host = token[1] + host; + return; } - - var empty = true === value || false === value || '' === value; - - if (!empty || !optional) { - var encodedValue = Router.encodePathComponent(value); - - if ('null' === encodedValue && null === value) { - encodedValue = ''; - } - - url = token[1] + encodedValue + url; + if ('variable' === token[0]) { + if (token[3] in params) { + value = params[token[3]]; + delete unusedParams[token[3]]; + } + else if (route.defaults && !Array.isArray(route.defaults) && (token[3] in route.defaults)) { + value = route.defaults[token[3]]; + } + host = token[1] + value + host; } - - optional = false; - } else if (hasDefault && typeof token[3] === 'string' && token[3] in unusedParams) { - delete unusedParams[token[3]]; - } - - return; + }); + url = this.context_.base_url + url; + if (route.requirements && ('_scheme' in route.requirements) && this.getScheme() != route.requirements['_scheme']) { + var currentHost = host || this.getHost(); + url = route.requirements['_scheme'] + '://' + currentHost + (currentHost.indexOf(':' + port) > -1 || '' === port ? '' : ':' + port) + url; } - - throw new Error('The token type "' + token[0] + '" is not supported.'); - }); - - if (url === '') { - url = '/'; - } - - route.hosttokens.forEach(function (token) { - var value; - - if ('text' === token[0]) { - host = token[1] + host; - return; + else if ('undefined' !== typeof route.schemes && 'undefined' !== typeof route.schemes[0] && this.getScheme() !== route.schemes[0]) { + var currentHost = host || this.getHost(); + url = route.schemes[0] + '://' + currentHost + (currentHost.indexOf(':' + port) > -1 || '' === port ? '' : ':' + port) + url; } - - if ('variable' === token[0]) { - if (token[3] in params) { - value = params[token[3]]; - delete unusedParams[token[3]]; - } else if (route.defaults && !Array.isArray(route.defaults) && token[3] in route.defaults) { - value = route.defaults[token[3]]; - } - - host = token[1] + value + host; + else if (host && this.getHost() !== host + (host.indexOf(':' + port) > -1 || '' === port ? '' : ':' + port)) { + url = this.getScheme() + '://' + host + (host.indexOf(':' + port) > -1 || '' === port ? '' : ':' + port) + url; } - }); - url = this.context_.base_url + url; - - if (route.requirements && '_scheme' in route.requirements && this.getScheme() != route.requirements['_scheme']) { - var currentHost = host || this.getHost(); - url = route.requirements['_scheme'] + '://' + currentHost + (currentHost.indexOf(':' + port) > -1 || '' === port ? '' : ':' + port) + url; - } else if ('undefined' !== typeof route.schemes && 'undefined' !== typeof route.schemes[0] && this.getScheme() !== route.schemes[0]) { - var _currentHost = host || this.getHost(); - - url = route.schemes[0] + '://' + _currentHost + (_currentHost.indexOf(':' + port) > -1 || '' === port ? '' : ':' + port) + url; - } else if (host && this.getHost() !== host + (host.indexOf(':' + port) > -1 || '' === port ? '' : ':' + port)) { - url = this.getScheme() + '://' + host + (host.indexOf(':' + port) > -1 || '' === port ? '' : ':' + port) + url; - } else if (absolute === true) { - url = this.getScheme() + '://' + this.getHost() + (this.getHost().indexOf(':' + port) > -1 || '' === port ? '' : ':' + port) + url; - } - - if (Object.keys(unusedParams).length > 0) { - var queryParams = []; - - var add = function add(key, value) { - // if value is a function then call it and assign it's return value as value - value = typeof value === 'function' ? value() : value; // change null to empty string - - value = value === null ? '' : value; - queryParams.push(Router.encodeQueryComponent(key) + '=' + Router.encodeQueryComponent(value)); - }; - - for (var _prefix in unusedParams) { - if (unusedParams.hasOwnProperty(_prefix)) { - this.buildQueryParams(_prefix, unusedParams[_prefix], add); - } + else if (absolute === true) { + url = this.getScheme() + '://' + this.getHost() + (this.getHost().indexOf(':' + port) > -1 || '' === port ? '' : ':' + port) + url; } - - url = url + '?' + queryParams.join('&'); - } - - return url; - } + if (Object.keys(unusedParams).length > 0) { + var queryParams_1 = []; + var add = function (key, value) { + // if value is a function then call it and assign it's return value as value + value = (typeof value === 'function') ? value() : value; + // change null to empty string + value = (value === null) ? '' : value; + queryParams_1.push(Router.encodeQueryComponent(key) + '=' + Router.encodeQueryComponent(value)); + }; + for (var prefix in unusedParams) { + if (unusedParams.hasOwnProperty(prefix)) { + this.buildQueryParams(prefix, unusedParams[prefix], add); + } + } + url = url + '?' + queryParams_1.join('&'); + } + return url; + }; /** * Returns the given string encoded to mimic Symfony URL generator. */ - - }], [{ - key: "getInstance", - value: function getInstance() { - return Routing; - } - }, { - key: "setData", - value: function setData(data) { - var router = Router.getInstance(); - router.setRoutingData(data); - } - }, { - key: "customEncodeURIComponent", - value: function customEncodeURIComponent(value) { - return encodeURIComponent(value).replace(/%2F/g, '/').replace(/%40/g, '@').replace(/%3A/g, ':').replace(/%21/g, '!').replace(/%3B/g, ';').replace(/%2C/g, ',').replace(/%2A/g, '*').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/'/g, '%27'); - } + Router.customEncodeURIComponent = function (value) { + return encodeURIComponent(value) + .replace(/%2F/g, '/') + .replace(/%40/g, '@') + .replace(/%3A/g, ':') + .replace(/%21/g, '!') + .replace(/%3B/g, ';') + .replace(/%2C/g, ',') + .replace(/%2A/g, '*') + .replace(/\(/g, '%28') + .replace(/\)/g, '%29') + .replace(/'/g, '%27'); + }; /** * Returns the given path properly encoded to mimic Symfony URL generator. */ - - }, { - key: "encodePathComponent", - value: function encodePathComponent(value) { - return Router.customEncodeURIComponent(value).replace(/%3D/g, '=').replace(/%2B/g, '+').replace(/%21/g, '!').replace(/%7C/g, '|'); - } + Router.encodePathComponent = function (value) { + return Router.customEncodeURIComponent(value) + .replace(/%3D/g, '=') + .replace(/%2B/g, '+') + .replace(/%21/g, '!') + .replace(/%7C/g, '|'); + }; /** * Returns the given query parameter or value properly encoded to mimic Symfony URL generator. */ - - }, { - key: "encodeQueryComponent", - value: function encodeQueryComponent(value) { - return Router.customEncodeURIComponent(value).replace(/%3F/g, '?'); - } - }]); - - return Router; -}(); - + Router.encodeQueryComponent = function (value) { + return Router.customEncodeURIComponent(value) + .replace(/%3F/g, '?'); + }; + return Router; +}()); exports.Router = Router; -var Routing = new Router(); -exports.Routing = Routing; -var _default = Routing; -exports["default"] = _default; - - return { Router: Router, Routing: Routing }; -})); \ No newline at end of file +exports.Routing = new Router(); +exports["default"] = exports.Routing; + + + return { Router: exports.Router, Routing: exports.Routing }; +})); \ No newline at end of file diff --git a/Resources/public/js/router.min.js b/Resources/public/js/router.min.js index e423c550..50f24420 100644 --- a/Resources/public/js/router.min.js +++ b/Resources/public/js/router.min.js @@ -1 +1 @@ -!function(e,t){var n=t();"function"==typeof define&&define.amd?define([],n.Routing):"object"==typeof module&&module.exports?module.exports=n.Routing:(e.Routing=n.Routing,e.fos={Router:n.Router})}(this,function(){function e(){return e=Object.assign||function(e){for(var t=1;t-1||""===l?"":":"+l)+a}else if("undefined"!=typeof i.schemes&&"undefined"!=typeof i.schemes[0]&&this.getScheme()!==i.schemes[0]){var p=f||this.getHost();a=i.schemes[0]+"://"+p+(p.indexOf(":"+l)>-1||""===l?"":":"+l)+a}else f&&this.getHost()!==f+(f.indexOf(":"+l)>-1||""===l?"":":"+l)?a=this.getScheme()+"://"+f+(f.indexOf(":"+l)>-1||""===l?"":":"+l)+a:r===!0&&(a=this.getScheme()+"://"+this.getHost()+(this.getHost().indexOf(":"+l)>-1||""===l?"":":"+l)+a);if(Object.keys(u).length>0){var y=[],d=function(e,t){t="function"==typeof t?t():t,t=null===t?"":t,y.push(o.encodeQueryComponent(e)+"="+o.encodeQueryComponent(t))};for(var g in u)u.hasOwnProperty(g)&&this.buildQueryParams(g,u[g],d);a=a+"?"+y.join("&")}return a}}],[{key:"getInstance",value:function(){return u}},{key:"setData",value:function(e){var t=o.getInstance();t.setRoutingData(e)}},{key:"customEncodeURIComponent",value:function(e){return encodeURIComponent(e).replace(/%2F/g,"/").replace(/%40/g,"@").replace(/%3A/g,":").replace(/%21/g,"!").replace(/%3B/g,";").replace(/%2C/g,",").replace(/%2A/g,"*").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/'/g,"%27")}},{key:"encodePathComponent",value:function(e){return o.customEncodeURIComponent(e).replace(/%3D/g,"=").replace(/%2B/g,"+").replace(/%21/g,"!").replace(/%7C/g,"|")}},{key:"encodeQueryComponent",value:function(e){return o.customEncodeURIComponent(e).replace(/%3F/g,"?")}}]),o}();i.Router=s;var u=new s;i.Routing=u;var a=u;return i["default"]=a,{Router:s,Routing:u}}); \ No newline at end of file +!function(e){(t={}).__esModule=!0,t.Routing=t.Router=void 0,o=function(){function l(e,t){this.context_=e||{base_url:"",prefix:"",host:"",port:"",scheme:"",locale:""},this.setRoutes(t||{})}return l.getInstance=function(){return t.Routing},l.setData=function(e){l.getInstance().setRoutingData(e)},l.prototype.setRoutingData=function(e){this.setBaseUrl(e.base_url),this.setRoutes(e.routes),void 0!==e.prefix&&this.setPrefix(e.prefix),void 0!==e.port&&this.setPort(e.port),void 0!==e.locale&&this.setLocale(e.locale),this.setHost(e.host),void 0!==e.scheme&&this.setScheme(e.scheme)},l.prototype.setRoutes=function(e){this.routes_=Object.freeze(e)},l.prototype.getRoutes=function(){return this.routes_},l.prototype.setBaseUrl=function(e){this.context_.base_url=e},l.prototype.getBaseUrl=function(){return this.context_.base_url},l.prototype.setPrefix=function(e){this.context_.prefix=e},l.prototype.setScheme=function(e){this.context_.scheme=e},l.prototype.getScheme=function(){return this.context_.scheme},l.prototype.setHost=function(e){this.context_.host=e},l.prototype.getHost=function(){return this.context_.host},l.prototype.setPort=function(e){this.context_.port=e},l.prototype.getPort=function(){return this.context_.port},l.prototype.setLocale=function(e){this.context_.locale=e},l.prototype.getLocale=function(){return this.context_.locale},l.prototype.buildQueryParams=function(o,e,n){var t,r=this,s=new RegExp(/\[\]$/);if(e instanceof Array)e.forEach(function(e,t){s.test(o)?n(o,e):r.buildQueryParams(o+"["+("object"==typeof e?t:"")+"]",e,n)});else if("object"==typeof e)for(t in e)this.buildQueryParams(o+"["+t+"]",e[t],n);else n(o,e)},l.prototype.getRoute=function(e){var t,o=[this.context_.prefix+e,e+"."+this.context_.locale,this.context_.prefix+e+"."+this.context_.locale,e];for(t in o)if(o[t]in this.routes_)return this.routes_[o[t]];throw new Error('The route "'+e+'" does not exist.')},l.prototype.generate=function(r,e,p){var t,s=this.getRoute(r),i=e||{},u=Object.assign({},i),c="",a=!0,o="",e=void 0===this.getPort()||null===this.getPort()?"":this.getPort();if(s.tokens.forEach(function(e){if("text"===e[0]&&"string"==typeof e[1])return c=l.encodePathComponent(e[1])+c,void(a=!1);if("variable"!==e[0])throw new Error('The token type "'+e[0]+'" is not supported.');6===e.length&&!0===e[5]&&(a=!1);var t=s.defaults&&!Array.isArray(s.defaults)&&"string"==typeof e[3]&&e[3]in s.defaults;if(!1===a||!t||"string"==typeof e[3]&&e[3]in i&&!Array.isArray(s.defaults)&&i[e[3]]!=s.defaults[e[3]]){var o,n=void 0;if("string"==typeof e[3]&&e[3]in i)n=i[e[3]],delete u[e[3]];else{if("string"!=typeof e[3]||!t||Array.isArray(s.defaults)){if(a)return;throw new Error('The route "'+r+'" requires the parameter "'+e[3]+'".')}n=s.defaults[e[3]]}(!0===n||!1===n||""===n)&&a||(o=l.encodePathComponent(n),c=e[1]+(o="null"===o&&null===n?"":o)+c),a=!1}else t&&"string"==typeof e[3]&&e[3]in u&&delete u[e[3]]}),""===c&&(c="/"),s.hosttokens.forEach(function(e){var t;"text"!==e[0]?"variable"===e[0]&&(e[3]in i?(t=i[e[3]],delete u[e[3]]):s.defaults&&!Array.isArray(s.defaults)&&e[3]in s.defaults&&(t=s.defaults[e[3]]),o=e[1]+t+o):o=e[1]+o}),c=this.context_.base_url+c,s.requirements&&"_scheme"in s.requirements&&this.getScheme()!=s.requirements._scheme?(t=o||this.getHost(),c=s.requirements._scheme+"://"+t+(-1 + */ +const fs = require('fs'); +const path = require('path'); +const util = require('util'); + +const InjectPlugin = require('webpack-inject-plugin').default; + +const execFile = util.promisify(require('child_process').execFile); +const readFile = util.promisify(fs.readFile); +const rmFile = util.promisify(fs.rm); +const writeFile = util.promisify(fs.writeFile); +const makeDir = util.promisify(fs.mkdir) + +class FosRouting { + default = { + locale: '', + prettyPrint: false, + domain: [], + }; + + constructor(options = {}) { + this.options = Object.assign({target: 'var/cache/fosRoutes.json'}, this.default, options, {format: 'json'}); + this.finalTarget = path.resolve(process.cwd(), this.options.target); + this.options.target = path.resolve(process.cwd(), this.options.target.replace(/\.json$/, '.tmp.json')); + + if (this.options.target === this.finalTarget) { + this.options.target += '.tmp'; + } + } + + // Values don't need to be escaped because node already does that + shellArg(key, value) { + key = this.kebabize(key); + return typeof value === 'boolean' ? (value ? '--' + key : '') : '--' + key + '=' + value; + } + + kebabize(str) { + return str.split('').map((letter, idx) => { + return letter.toUpperCase() === letter + ? `${idx !== 0 ? '-' : ''}${letter.toLowerCase()}` + : letter; + }).join(''); + } + + apply(compiler) { + let prevContent = null; + try { + fs.readFileSync(this.finalTarget); + } catch (e) { + } + const compile = async (comp, callback) => { + const args = Object.keys(this.options).reduce((pass, key) => { + const val = this.options[key]; + if (val !== this.default[key]) { + if (Array.isArray(val)) { + pass.push(...val.map((v) => this.shellArg(key, v))); + } else { + pass.push(this.shellArg(key, val)); + } + } + return pass; + }, []); + await execFile('bin/console', ['fos:js-routing:dump', ...args]); + const content = await readFile(this.options.target); + await rmFile(this.options.target); + if (!prevContent || content.compare(prevContent) !== 0) { + await makeDir(path.basename(this.finalTarget), {recursive: true}) + await writeFile(this.finalTarget, content); + prevContent = content; + if (comp.modifiedFiles && !comp.modifiedFiles.has(this.finalTarget)) { + comp.modifiedFiles.add(this.finalTarget); + } + } + callback(); + }; + compiler.hooks.beforeRun.tapAsync('RouteDump', compile); + compiler.hooks.watchRun.tapAsync('RouteDump_Watch', (comp, callback) => { + if (!comp.modifiedFiles || !comp.modifiedFiles.has(this.finalTarget)) { + compile(comp, callback); + } else { + callback(); + } + }); + + new InjectPlugin(() => { + return 'import Routing from "fos-router";' + + 'import routes from "' + this.finalTarget + '";' + + 'Routing.setRoutingData(routes);'; + }).apply(compiler); + } +} + +module.exports = FosRouting; +module.exports.default = FosRouting;