├── .gitignore ├── .gitattributes ├── src ├── LaravelJsRoutesServiceProvider.php ├── Generators │ ├── templates │ │ └── Router.js │ └── RoutesJavascriptGenerator.php └── Commands │ └── RoutesJavascriptCommand.php ├── LICENSE.txt ├── composer.json ├── README.md └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /node_modules/ 3 | /.grunt/ 4 | /build/ 5 | composer.phar 6 | _SpecRunner.html 7 | .DS_Store 8 | .php_cs.cache 9 | composer.lock -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | .php_cs export-ignore 2 | .travis.yml export-ignore 3 | Gruntfile.js export-ignore 4 | package.json export-ignore 5 | phpcs.xml export-ignore 6 | phpmd.xml export-ignore 7 | phpunit.xml.dist export-ignore 8 | /tests export-ignore 9 | _SpecRunner.html export-ignore -------------------------------------------------------------------------------- /src/LaravelJsRoutesServiceProvider.php: -------------------------------------------------------------------------------- 1 | commands([ 23 | Commands\RoutesJavascriptCommand::class, 24 | ]); 25 | } 26 | 27 | /** 28 | * Get the services provided by the provider. 29 | * 30 | * @return array 31 | */ 32 | public function provides() 33 | { 34 | return []; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Federico Isas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravelba/laravel-js-routes", 3 | "description": "Access Laravel routes from your javascript files.", 4 | "license": "MIT", 5 | "keywords": ["laravel", "generators", "javascript", "routes"], 6 | "authors": [ 7 | { 8 | "name": "Fede Isas", 9 | "email": "fedeisas@hotmail.com" 10 | }, 11 | { 12 | "name": "Guido Contreras Woda", 13 | "email": "guiwoda@gmail.com" 14 | } 15 | ], 16 | "require": { 17 | "php": ">=5.6.0", 18 | "illuminate/support": "^5.0", 19 | "illuminate/console": "^5.0", 20 | "illuminate/filesystem": "^5.0", 21 | "illuminate/routing": "^5.0" 22 | }, 23 | "require-dev": { 24 | "illuminate/events": "^5.0", 25 | "phpunit/phpunit": "^5.3", 26 | "mockery/mockery": "^1.0.0@dev", 27 | "squizlabs/php_codesniffer": "^2.6", 28 | "jakub-onderka/php-parallel-lint": "^0.9", 29 | "jakub-onderka/php-console-highlighter": "^0.3", 30 | "phpmd/phpmd": "^2.4", 31 | "fabpot/php-cs-fixer": "^1.11" 32 | }, 33 | "autoload": { 34 | "psr-4": { 35 | "LaravelBA\\LaravelJsRoutes\\": "src/" 36 | } 37 | }, 38 | "minimum-stability": "stable" 39 | } 40 | -------------------------------------------------------------------------------- /src/Generators/templates/Router.js: -------------------------------------------------------------------------------- 1 | (function(name, definition) { 2 | if (typeof module != 'undefined') { 3 | module.exports = definition(); 4 | } else if (typeof define == 'function' && typeof define.amd == 'object') { 5 | define(definition); 6 | } else { 7 | this[name] = definition(); 8 | } 9 | }('Router', function() { 10 | return { 11 | routes: null, 12 | route: function(name, params) { 13 | var route = this.searchRoute(name), 14 | rootUrl = this.getRootUrl(), 15 | result = "", 16 | compiled = ""; 17 | 18 | if (route) { 19 | compiled = this.buildParams(route, params); 20 | result = this.cleanupDoubleSlashes(rootUrl + '/' + compiled); 21 | result = this.stripTrailingSlash(result); 22 | return result; 23 | } 24 | 25 | }, 26 | searchRoute: function(name) { 27 | for (var i = this.routes.length - 1; i >= 0; i--) { 28 | if (this.routes[i].name == name) { 29 | return this.routes[i]; 30 | } 31 | } 32 | }, 33 | buildParams: function(route, params) { 34 | var compiled = route.uri, 35 | queryParams = {}; 36 | 37 | for (var key in params) { 38 | if (compiled.indexOf('{' + key + '?}') != -1) { 39 | if (key in params) { 40 | compiled = compiled.replace('{' + key + '?}', params[key]); 41 | } 42 | } else if (compiled.indexOf('{' + key + '}') != -1) { 43 | compiled = compiled.replace('{' + key + '}', params[key]); 44 | } else { 45 | queryParams[key] = params[key]; 46 | } 47 | } 48 | 49 | compiled = compiled.replace(/\{([^\/]*)\?}/g, ""); 50 | 51 | if (!this.isEmptyObject(queryParams)) { 52 | return compiled + this.buildQueryString(queryParams); 53 | } 54 | 55 | return compiled; 56 | }, 57 | getRootUrl: function() { 58 | return window.location.protocol + '//' + window.location.host; 59 | }, 60 | buildQueryString: function(params) { 61 | var ret = []; 62 | for (var key in params) { 63 | ret.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key])); 64 | } 65 | return '?' + ret.join("&"); 66 | }, 67 | isEmptyObject: function(obj) { 68 | var name; 69 | for (name in obj) { 70 | return false; 71 | } 72 | return true; 73 | }, 74 | cleanupDoubleSlashes: function(url) { 75 | return url.replace(/([^:]\/)\/+/g, "$1"); 76 | }, 77 | stripTrailingSlash: function(url) { 78 | if(url.substr(-1) == '/') { 79 | return url.substr(0, url.length - 1); 80 | } 81 | return url; 82 | } 83 | }; 84 | })); -------------------------------------------------------------------------------- /src/Commands/RoutesJavascriptCommand.php: -------------------------------------------------------------------------------- 1 | getPath() . '/' . $this->argument('name'); 34 | $middleware = $this->option('middleware'); 35 | 36 | if ($this->option('filter')) { 37 | $this->warn("Filter option is deprecated, as Laravel 5 doesn't use filters anymore." . PHP_EOL . 38 | "Please change your code to use --middleware (or -m) instead."); 39 | 40 | $middleware = $this->option('filter'); 41 | } 42 | 43 | $options = [ 44 | 'middleware' => $middleware, 45 | 'object' => $this->option('object'), 46 | 'prefix' => $this->option('prefix'), 47 | ]; 48 | 49 | if ($generator->make($this->getPath(), $this->argument('name'), $options)) { 50 | $this->info("Created {$path}"); 51 | 52 | return 0; 53 | } 54 | 55 | $this->error("Could not create {$path}"); 56 | 57 | return 1; 58 | } 59 | 60 | /** 61 | * Get the path to the file that should be generated. 62 | * 63 | * @return string 64 | */ 65 | protected function getPath() 66 | { 67 | return base_path($this->option('path')); 68 | } 69 | 70 | /** 71 | * Get the console command arguments. 72 | * 73 | * @return array 74 | */ 75 | protected function getArguments() 76 | { 77 | return [ 78 | ['name', InputArgument::OPTIONAL, 'Filename', 'routes.js'], 79 | ]; 80 | } 81 | 82 | /** 83 | * Get the console command options. 84 | * 85 | * @return array 86 | */ 87 | protected function getOptions() 88 | { 89 | return [ 90 | ['path', 'p', InputOption::VALUE_OPTIONAL, 'Path to assets directory.', 'resources/assets/js'], 91 | ['filter', 'f', InputOption::VALUE_OPTIONAL, 'DEPRECATED: Kept here for compatibility only. Use middleware flag instead.', null], 92 | ['middleware', 'm', InputOption::VALUE_OPTIONAL, 'Custom route middleware.', null], 93 | ['object', 'o', InputOption::VALUE_OPTIONAL, 'Custom JS object.', 'Router'], 94 | ['prefix', 'prefix', InputOption::VALUE_OPTIONAL, 'Custom route prefix.', null], 95 | ]; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/Generators/RoutesJavascriptGenerator.php: -------------------------------------------------------------------------------- 1 | file = $file; 28 | $this->router = $router; 29 | } 30 | 31 | /** 32 | * Compile routes template and generate 33 | * 34 | * @param string $path 35 | * @param string $name 36 | * @param array $options 37 | * 38 | * @return bool 39 | */ 40 | public function make($path, $name, array $options = []) 41 | { 42 | $options += ['middleware' => null, 'prefix' => null]; 43 | 44 | $parsedRoutes = $this->getParsedRoutes($options['middleware'], $options['prefix']); 45 | 46 | $template = $this->file->get(__DIR__ . '/templates/Router.js'); 47 | 48 | $template = str_replace("routes: null,", 'routes: ' . json_encode($parsedRoutes) . ',', $template); 49 | $template = str_replace("'Router'", "'" . $options['object'] . "'", $template); 50 | 51 | if ($this->file->isWritable($path)) { 52 | $filename = $path . '/' . $name; 53 | 54 | return $this->file->put($filename, $template) !== false; 55 | } 56 | 57 | return false; 58 | } 59 | 60 | /** 61 | * Get parsed routes 62 | * 63 | * @param string $middleware 64 | * @param string $prefix 65 | * 66 | * @return array 67 | */ 68 | protected function getParsedRoutes($middleware = null, $prefix = null) 69 | { 70 | /** @var Collection $parsedRoutes */ 71 | $parsedRoutes = Collection::make($this->router->getRoutes()->getRoutes()) 72 | ->map(function ($route) { 73 | return $this->getRouteInformation($route); 74 | }) 75 | ->filter(); 76 | 77 | if ($middleware) { 78 | $parsedRoutes = $parsedRoutes->filter(function($routeInfo) use ($middleware) { 79 | return in_array($middleware, $routeInfo['middleware']); 80 | }); 81 | } 82 | 83 | $parsedRoutes = $parsedRoutes->map(function($routeInfo){ 84 | unset($routeInfo['middleware']); 85 | 86 | return $routeInfo; 87 | }); 88 | 89 | if ($prefix) { 90 | $parsedRoutes = $parsedRoutes->map(function ($routeInfo) use ($prefix) { 91 | $routeInfo['uri'] = $prefix . $routeInfo['uri']; 92 | 93 | return $routeInfo; 94 | }); 95 | } 96 | 97 | return $parsedRoutes->values()->all(); 98 | } 99 | 100 | /** 101 | * Get the route information for a given route. 102 | * 103 | * @param \Illuminate\Routing\Route $route 104 | * 105 | * @return array|null 106 | */ 107 | protected function getRouteInformation(Route $route) 108 | { 109 | if ($route->getName()) { 110 | return [ 111 | 'uri' => $route->uri(), 112 | 'name' => $route->getName(), 113 | 'middleware' => $route->middleware(), 114 | ]; 115 | } 116 | 117 | return null; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Laravel Javascript Routes 2 | ========================= 3 | 4 | [![Travis Badge](https://secure.travis-ci.org/LaravelBA/laravel-js-routes.png)](http://travis-ci.org/LaravelBA/laravel-js-routes) 5 | [![Latest Stable Version](https://poser.pugx.org/LaravelBA/laravel-js-routes/v/stable.png)](https://packagist.org/packages/LaravelBA/laravel-js-routes) 6 | [![Latest Unstable Version](https://poser.pugx.org/LaravelBA/laravel-js-routes/v/unstable.png)](https://packagist.org/packages/LaravelBA/laravel-js-routes) 7 | [![Total Downloads](https://poser.pugx.org/LaravelBA/laravel-js-routes/downloads.png)](https://packagist.org/packages/LaravelBA/laravel-js-routes) 8 | [![License](https://poser.pugx.org/LaravelBA/laravel-js-routes/license.png)](https://packagist.org/packages/LaravelBA/laravel-js-routes) 9 | 10 | # DEPRECATED 11 | 12 | This package is no longer maintained. Please use https://github.com/aaronlord/laroute or any other alternative you may find! 13 | 14 | ## Why? 15 | We love the Laravel routing system and we often use named routes like `route('users.show', ['id' => 1])` to generate `http://domain.tld/users/1`. 16 | With the amazing uprising of Javascript frameworks (AngularJS, EmberJS, Backbone, etc.) it's hard to track changes on your routes between the backend and the REST calls from your Javascript. 17 | The goal of this library is to expose those named routes to your frontend so you can do: `Router.route('users.show', {id: 1})` and get the same result. 18 | 19 | ## Installation 20 | 21 | Begin by installing this package through Composer. 22 | 23 | ```shell 24 | composer require laravelba/laravel-js-routes 25 | ``` 26 | 27 | To use this package, add its service provider to your `config/app.php` providers array. 28 | ```php 29 | 'providers' => [ 30 | // ... 31 | LaravelBA\LaravelJsRoutes\LaravelJsRoutesServiceProvider::class, 32 | ], 33 | ``` 34 | 35 | ## Usage 36 | The ServiceProvider will add a new command `routes:javascript` to your `artisan` commands. 37 | By default, this command will generate a `routes.js` file on your `resources/assets/js` folder. This contains all **named** routes in your app. 38 | That's it! You're all set to go. 39 | 40 | ```shell 41 | $ php artisan routes:javascript 42 | ``` 43 | 44 | > **Lazy Tip** If you use elixir (or any js task manager), set up a watcher that runs this command whenever your php routes change. 45 | 46 | ## Arguments 47 | 48 | | Name | Default | Description | 49 | | -------- |:-----------:| --------------- | 50 | | **name** | *routes.js* | Output filename | 51 | 52 | ## Options 53 | 54 | | Name | Default | Description | 55 | | -------------- |:---------------------:| --------------- | 56 | | **path** | *resources/assets/js* | Where to save the generated filename, relative to the base path. (ie. "public/assets" folder if you don't plan to mix it.) | 57 | | **middleware** | *null* | If you want only some routes to be available on JS, you can use a middleware (like js-routable) to select only those | 58 | | **object** | *Router* | If you want to choose your own global JS object (to avoid collision) | 59 | | **prefix** | *null* | If you want to a path to prefix to all your routes | 60 | 61 | ## Javascript usage 62 | 63 | By default, the command will generate a `routes.js` file on your `resources/assets/js` folder, so you can use elixir: 64 | 65 | ```js 66 | elixir(function(mix){ 67 | mix.scripts([ 68 | 'routes.js', 69 | 'app.js' 70 | ]); 71 | }); 72 | ``` 73 | 74 | You may generate the routes file in your public folder instead... 75 | 76 | ```shell 77 | php artisan routes:javascript --path public/js 78 | ``` 79 | ...then include it in your views: 80 | 81 | ```html 82 |