├── .eslintrc.js
├── .gitignore
├── LICENSE
├── README.md
├── example
├── App.vue
├── Character.vue
├── View.vue
└── main.js
├── package.json
├── resources
├── ss1.png
├── ss2.png
├── ss3.png
├── vue-smart-route-swapi.gif
├── vue-smart-route.gif
└── vue-smart-route.png
├── src
└── vue-smart-route.js
└── yarn.lock
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parserOptions: {
4 | sourceType: 'module'
5 | },
6 |
7 | extends: 'standard',
8 | // required to lint *.vue files
9 | plugins: [
10 | 'html'
11 | ]
12 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # parcel-bundler cache (https://parceljs.org/)
61 | .cache
62 |
63 | # next.js build output
64 | .next
65 |
66 | # nuxt.js build output
67 | .nuxt
68 |
69 | # vuepress build output
70 | .vuepress/dist
71 |
72 | # Serverless directories
73 | .serverless/
74 |
75 | # FuseBox cache
76 | .fusebox/
77 |
78 | #DynamoDB Local files
79 | .dynamodb/
80 |
81 | .DS_Store
82 | dist
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Fatih Kadir Akın
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Make your users dynamically navigate routes, make smart commands and queries with a single directive.
5 |
6 |
7 |
8 |
9 |
10 | Vue Smart Route allows you to create a **query** system based on your **routes**. You can simply create a command input that creates **smart** actions, both static routes and the **async ones**:
11 |
12 |
13 |
14 |
15 |
16 | ## Install
17 |
18 | ```
19 | yarn add vue-smart-route
20 | ```
21 |
22 | Then install it:
23 |
24 | ```js
25 | import Vue from 'vue'
26 | import VueRouter from 'vue-router'
27 | import VueSmartRoute from 'vue-smart-route'
28 |
29 | Vue.use(VueRouter)
30 | Vue.use(VueSmartRoute)
31 | ```
32 |
33 | ## Overview
34 |
35 | This is a well known route in **VueRouter**:
36 |
37 | ```js
38 | routes: [
39 | {
40 | name: 'about',
41 | path: '/about'
42 | }
43 | ]
44 | ```
45 |
46 | To make it **smart route**, just add a `smart` key:
47 |
48 | ```js
49 | routes: [
50 | {
51 | name: 'about',
52 | path: '/about',
53 | // Adding smart key with `matcher` and `handler` (optional)
54 | smart: {
55 | matcher: {
56 | search: [/about/],
57 | title: () => 'About us'
58 | }
59 | }
60 | }
61 | ]
62 | ```
63 |
64 | Then, you need to use **`v-smart-routes`** directive to connect possible routes you asked with **`search`**:
65 |
66 | ```vue
67 |
68 |
69 |
70 |
71 |
81 | ```
82 |
83 | Now, `routes` and `search` are connected each other and `routes` will be **smartly calculated** according to `search` property.
84 |
85 | > Following examples are styled. **`vue-smart-route` does not contain any style or component.**
86 |
87 |
88 |
89 | [▶︎ Try in Example](https://f.github.io/vue-smart-route)
90 |
91 | You can check `/example` to see a working example.
92 |
93 | ## Passing Parameters
94 |
95 | **vue-smart-route** is simple yet powerful. You can extend your logic to **make your route smarter.**
96 |
97 | Let's create a smart `/search` route:
98 |
99 | ```js
100 | {
101 | name: 'search',
102 | path: '/search',
103 | component: () => import('./Search.vue'),
104 | smart: {
105 | matcher: {
106 | // Named RegExp will be passed to the `title` function:
107 | search: [/^search\:?\s+(?.+)/i],
108 | title: ({ query }) => `Search about *${query}*`
109 | }
110 | }
111 | }
112 | ```
113 |
114 |
115 |
116 | [▶︎ Try in Example](https://f.github.io/vue-smart-route)
117 |
118 | When you click to the link, it will be navigated to the `/search?query=how+to+be+smart`.
119 |
120 | Then you'll be able to access to the query using `$route.query.query` from your view.
121 |
122 | ## Passing Optional Parameters
123 |
124 | You can simply make your search smarter by adding more logic:
125 |
126 | ```js
127 | {
128 | name: 'mail',
129 | path: '/mail',
130 | component: () => import('./SendMail.vue'),
131 | smart: {
132 | matcher: {
133 | search: [
134 | /(?[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)/i,
135 | /(?[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)\s+(?\w+)/i
136 | ],
137 | title({ email, subject }) {
138 | if (subject) {
139 | return `Send email to *${email}* with subject *${subject}*`;
140 | }
141 | return `Send email to *${email}*`;
142 | }
143 | }
144 | }
145 | }
146 | ```
147 |
148 | - You can pass multiple `RegExp` for search,
149 | - `title` gets all the named matches and may include logic.
150 |
151 |
152 |
153 | [▶︎ Try in Example](https://f.github.io/vue-smart-route)
154 |
155 | It lists all the routes.
156 |
157 | ## The Directive
158 |
159 | vue-smart-route includes only a directive that makes all the magic.
160 |
161 | Directive requires to be bound an **input with a `v-model`**, and using `v-smart-routes` you will bind results to another property.
162 |
163 | E.g. if you bind `v-smart-routes` to `results` property, it will be an array of route objects.
164 |
165 | | key | Type | Description |
166 | | --- | ---- | ----------- |
167 | | `name` | `String` | Route name, e.g. `home` |
168 | | `path` | `String` | Route path, e.g. `/` |
169 | | `title` | `String` | Route title generated by `title` function of the smart route |
170 | | `handler` | `Function` | A function that triggers the navigation. It can be overriden.
171 |
172 | ## Customizing the `handler` behaviour
173 |
174 | `handler` navigates to page by default, but it can be changed.
175 |
176 | Let's make `email` example smarter by changing the navigation handler:
177 |
178 | ```js
179 | {
180 | name: 'mail',
181 | path: '/mail',
182 | component: () => import('./SendMail.vue'),
183 | smart: {
184 | matcher: {
185 | search: [
186 | /(?[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)/i,
187 | /(?[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)\s+(?\w+)/i
188 | ],
189 | title({ email, subject }) {
190 | if (subject) {
191 | return `Send email to *${email}* with subject *${subject}*`;
192 | }
193 | return `Send email to *${email}*`;
194 | }
195 | },
196 |
197 | // Customizing the handler
198 | handler(route, next) {
199 | if (route.query.subject) {
200 | location.href = `mailto:${route.query.email}?subject=${
201 | route.query.subject
202 | }`;
203 | // Calling next will continue navigation by default, you can redirect or just stop here.
204 | next(route);
205 | return;
206 | }
207 | location.href = `mailto:${route.query.email}`;
208 | next(route);
209 | }
210 | }
211 | }
212 | ```
213 |
214 | According to this example, you will be able to navigate your user to the mail application.
215 |
216 | ## Async Route Generation (Autocomplete-like)
217 |
218 | **vue-smart-route** supports `async routes` that you can generate routes on demand, on runtime. To do that, you should use `async routes` method to matcher:
219 |
220 | ```js
221 | smart: {
222 | matcher: {
223 | search: [/swapi\s(?.*)/],
224 | async routes({ query }) {
225 | const people = await fetch(`https://swapi.co/api/people/?search=${encodeURIComponent(query)}`).then(r => r.json())
226 | return people.results.map(character => ({
227 | name: 'character',
228 | title: `Go to character *${character.name}*`,
229 | params: { url: character.url }
230 | }))
231 | }
232 | }
233 | }
234 | ```
235 |
236 | This will help you to generate new routes dynamically:
237 |
238 |
239 |
240 | ## i18n
241 |
242 | You can also use `i18n` features in `vue-smart-route`:
243 |
244 | `search`, `title` and `handler` takes `ctx` parameters which you can access to current component.
245 |
246 | ```js
247 | routes: [
248 | {
249 | name: 'about',
250 | path: '/about',
251 | smart: {
252 | matcher: {
253 | search: (ctx) => {
254 | switch (ctx.$i18n.locale) {
255 | case 'tr':
256 | return [/hakkinda/]
257 | case 'en':
258 | default:
259 | return [/about/]
260 | }
261 | },
262 | title: ({}, ctx) => ctx.$i18n.t('navigation.about_us')
263 | },
264 | handler (route, next, ctx) {
265 | location.href = `https://${ctx.i18n.locale}.example.com/about`
266 | }
267 | }
268 | }
269 | ]
270 | ```
271 |
272 | ## License
273 |
274 | MIT.
275 |
--------------------------------------------------------------------------------
/example/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
You can write about, search: {query}, user {username}, user {id}, user {username} {id} or a mail address and the subject, also sw {query} will search characters from SWAPI.