action_policy 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +233 -171
  3. data/LICENSE.txt +1 -1
  4. data/README.md +7 -11
  5. data/lib/action_policy.rb +7 -1
  6. data/lib/action_policy/behaviour.rb +22 -16
  7. data/lib/action_policy/behaviours/policy_for.rb +10 -3
  8. data/lib/action_policy/behaviours/scoping.rb +2 -1
  9. data/lib/action_policy/behaviours/thread_memoized.rb +1 -3
  10. data/lib/action_policy/ext/module_namespace.rb +1 -6
  11. data/lib/action_policy/ext/policy_cache_key.rb +15 -33
  12. data/lib/action_policy/ext/{symbol_classify.rb → symbol_camelize.rb} +6 -6
  13. data/lib/action_policy/i18n.rb +1 -1
  14. data/lib/action_policy/lookup_chain.rb +41 -21
  15. data/lib/action_policy/policy/aliases.rb +7 -12
  16. data/lib/action_policy/policy/authorization.rb +14 -17
  17. data/lib/action_policy/policy/cache.rb +34 -18
  18. data/lib/action_policy/policy/core.rb +25 -12
  19. data/lib/action_policy/policy/defaults.rb +3 -9
  20. data/lib/action_policy/policy/execution_result.rb +3 -9
  21. data/lib/action_policy/policy/pre_check.rb +19 -58
  22. data/lib/action_policy/policy/reasons.rb +30 -20
  23. data/lib/action_policy/policy/scoping.rb +5 -6
  24. data/lib/action_policy/rails/controller.rb +6 -1
  25. data/lib/action_policy/rails/ext/active_record.rb +7 -0
  26. data/lib/action_policy/rails/policy/instrumentation.rb +1 -1
  27. data/lib/action_policy/rspec/be_authorized_to.rb +5 -9
  28. data/lib/action_policy/rspec/dsl.rb +3 -3
  29. data/lib/action_policy/rspec/have_authorized_scope.rb +5 -7
  30. data/lib/action_policy/testing.rb +1 -1
  31. data/lib/action_policy/utils/pretty_print.rb +21 -24
  32. data/lib/action_policy/utils/suggest_message.rb +1 -3
  33. data/lib/action_policy/version.rb +1 -1
  34. data/lib/generators/action_policy/install/templates/{application_policy.rb → application_policy.rb.tt} +1 -1
  35. data/lib/generators/action_policy/policy/policy_generator.rb +4 -1
  36. data/lib/generators/action_policy/policy/templates/{policy.rb → policy.rb.tt} +0 -0
  37. data/lib/generators/rspec/templates/{policy_spec.rb → policy_spec.rb.tt} +0 -0
  38. data/lib/generators/test_unit/templates/{policy_test.rb → policy_test.rb.tt} +0 -0
  39. metadata +30 -119
  40. data/.gitattributes +0 -2
  41. data/.github/FUNDING.yml +0 -1
  42. data/.github/ISSUE_TEMPLATE.md +0 -18
  43. data/.github/PULL_REQUEST_TEMPLATE.md +0 -29
  44. data/.gitignore +0 -15
  45. data/.rubocop.yml +0 -54
  46. data/.tidelift.yml +0 -6
  47. data/.travis.yml +0 -31
  48. data/Gemfile +0 -22
  49. data/Rakefile +0 -27
  50. data/action_policy.gemspec +0 -44
  51. data/benchmarks/namespaced_lookup_cache.rb +0 -71
  52. data/bin/console +0 -14
  53. data/bin/setup +0 -8
  54. data/docs/.nojekyll +0 -0
  55. data/docs/CNAME +0 -1
  56. data/docs/README.md +0 -77
  57. data/docs/_sidebar.md +0 -27
  58. data/docs/aliases.md +0 -122
  59. data/docs/assets/docsify-search.js +0 -364
  60. data/docs/assets/docsify.min.js +0 -3
  61. data/docs/assets/fonts/FiraCode-Medium.woff +0 -0
  62. data/docs/assets/fonts/FiraCode-Regular.woff +0 -0
  63. data/docs/assets/images/banner.png +0 -0
  64. data/docs/assets/images/cache.png +0 -0
  65. data/docs/assets/images/cache.svg +0 -70
  66. data/docs/assets/images/layer.png +0 -0
  67. data/docs/assets/images/layer.svg +0 -35
  68. data/docs/assets/prism-ruby.min.js +0 -1
  69. data/docs/assets/styles.css +0 -347
  70. data/docs/assets/vue.min.css +0 -1
  71. data/docs/authorization_context.md +0 -92
  72. data/docs/behaviour.md +0 -113
  73. data/docs/caching.md +0 -273
  74. data/docs/controller_action_aliases.md +0 -109
  75. data/docs/custom_lookup_chain.md +0 -48
  76. data/docs/custom_policy.md +0 -53
  77. data/docs/debugging.md +0 -55
  78. data/docs/decorators.md +0 -27
  79. data/docs/favicon.ico +0 -0
  80. data/docs/graphql.md +0 -302
  81. data/docs/i18n.md +0 -44
  82. data/docs/index.html +0 -43
  83. data/docs/instrumentation.md +0 -84
  84. data/docs/lookup_chain.md +0 -17
  85. data/docs/namespaces.md +0 -77
  86. data/docs/non_rails.md +0 -28
  87. data/docs/pre_checks.md +0 -57
  88. data/docs/pundit_migration.md +0 -80
  89. data/docs/quick_start.md +0 -118
  90. data/docs/rails.md +0 -120
  91. data/docs/reasons.md +0 -120
  92. data/docs/scoping.md +0 -255
  93. data/docs/testing.md +0 -333
  94. data/docs/writing_policies.md +0 -107
  95. data/gemfiles/jruby.gemfile +0 -8
  96. data/gemfiles/rails42.gemfile +0 -8
  97. data/gemfiles/rails6.gemfile +0 -8
  98. data/gemfiles/railsmaster.gemfile +0 -6
  99. data/lib/action_policy/ext/string_match.rb +0 -14
  100. data/lib/action_policy/ext/yield_self_then.rb +0 -25
@@ -1,27 +0,0 @@
1
- * Getting Started
2
- * [Quick Start](quick_start.md)
3
- * [Writing Policies](writing_policies.md)
4
- * [Rails Integration](rails.md)
5
- * [Non-Rails Usage](non_rails.md)
6
- * [GraphQL Integration](graphql.md)
7
- * [Testing](testing.md)
8
- * Features
9
- * [Authorization Behaviour](behaviour.md)
10
- * [Policy Lookup](lookup_chain.md)
11
- * [Authorization Context](authorization_context.md)
12
- * [Aliases](aliases.md)
13
- * [Pre-Checks](pre_checks.md)
14
- * [Scoping](scoping.md)
15
- * [Caching](caching.md)
16
- * [Namespaces](namespaces.md)
17
- * [Failure Reasons](reasons.md)
18
- * [Instrumentation](instrumentation.md)
19
- * [I18n Support](i18n.md)
20
- * [Debugging](debugging.md)
21
- * Tips & Tricks
22
- * [From Pundit to Action Policy](./pundit_migration.md)
23
- * [Dealing with Decorators](./decorators.md)
24
- * [Controller Action Aliases](controller_action_aliases.md)
25
- * Customize
26
- * [Base Policy](custom_policy.md)
27
- * [Lookup Chain](custom_lookup_chain.md)
@@ -1,122 +0,0 @@
1
- # Rule Aliases
2
-
3
- Action Policy allows you to add rule aliases. It is useful when you rely on _implicit_ rules in controllers. For example:
4
-
5
- ```ruby
6
- class PostsController < ApplicationController
7
- before_action :load_post, only: [:edit, :update, :destroy]
8
-
9
- private
10
-
11
- def load_post
12
- @post = Post.find(params[:id])
13
- # depending on action, an `edit?`, `update?` or `destroy?`
14
- # rule would be applied
15
- authorize! @post
16
- end
17
- end
18
- ```
19
-
20
- In your policy, you can create aliases to avoid duplication:
21
-
22
- ```ruby
23
- class PostPolicy < ApplicationPolicy
24
- alias_rule :edit?, :destroy?, to: :update?
25
- end
26
- ```
27
-
28
- **NOTE**: `alias_rule` is available only if you inherit from `ActionPolicy::Base` or include `ActionPolicy::Policy::Aliases` into your `ApplicationPolicy`.
29
-
30
- **Why not just use Ruby's `alias`?**
31
-
32
- An alias created with `alias_rule` is resolved at _authorization time_ (during an `authorize!` or `allowed_to?` call), and it does not add an alias method to the class.
33
-
34
- That allows us to write tests easier, as we should only test the rule, not the alias–and to leverage [caching](caching.md) better.
35
-
36
- By default, `ActionPolicy::Base` adds one alias: `alias_rule :new?, to: :create?`.
37
-
38
- ## Default rule
39
-
40
- You can add a _default_ rule–the rule that would be applied if the rule specified during authorization is missing (like a "wildcard" alias):
41
-
42
- ```ruby
43
- class PostPolicy < ApplicationPolicy
44
- # For an ApplicationPolicy, makes :manage? match anything that is
45
- # not :index?, :create? or :new?
46
- default_rule :manage?
47
-
48
- # If you want manage? to catch really everything, place this alias
49
- #alias_rule :index?, :create?, :new?, to: :manage?
50
- def manage?
51
- # ...
52
- end
53
- end
54
- ```
55
-
56
- Now when you call `authorize! post` with any rule not defined in the policy class, the `manage?` rule is applied. Note that `index?` `create?` and `new?` are already defined in the [superclass by default](custom_policy.md) (returning `false`) - if you want the same behaviour for *all* actions, define aliases like in the example above (commented out).
57
-
58
- By default, `ActionPolicy::Base` sets `manage?` as a default rule.
59
-
60
- ## Aliases and Private Methods
61
-
62
- Rules in `action_policy` can only be public methods. Trying to use a private method as a rule will raise an error. Thus, aliases can also only point to public methods.
63
-
64
- ## Rule resolution with subclasses
65
-
66
- Here's the order in which aliases and concrete rule methods are resolved in regards to subclasses:
67
-
68
- 1. If there is a concrete rule method on the subclass, this is called, else
69
- 2. If there is a matching alias then this is called, else
70
- * When aliases are defined on the subclass they will overwrite matching aliases on the superclass.
71
- 3. If there is a concrete rule method on the superclass, then this is called, else
72
- 4. If there is a default rule defined, then this is called, else
73
- 5. `ActionPolicy::UnknownRule` is raised.
74
-
75
- Here's an example with the expected results:
76
-
77
- ```ruby
78
- class SuperPolicy < ApplicationPolicy
79
- default_rule :manage?
80
-
81
- alias_rule :update?, :destroy?, :create?, to: :edit?
82
-
83
- def manage?
84
- end
85
-
86
- def edit?
87
- end
88
-
89
- def index?
90
- end
91
- end
92
-
93
- class SubPolicy < AbstractPolicy
94
- default_rule nil
95
-
96
- alias_rule :index?, :update?, to: :manage?
97
-
98
- def create?
99
- end
100
- end
101
- ```
102
-
103
- Authorizing against the SuperPolicy:
104
-
105
- * `update?` will resolve to `edit?`
106
- * `destroy?` will resolve to `edit?`
107
- * `create?` will resolve to `edit?`
108
- * `manage?` will resolve to `manage?`
109
- * `edit?` will resolve to `edit?`
110
- * `index?` will resolve to `index?`
111
- * `something?` will resolve to `manage?`
112
-
113
- Authorizing against the SubPolicy:
114
-
115
- * `index?` will resolve to `manage?`
116
- * `update?` will resolve to `manage?`
117
- * `create?` will resolve to `create?`
118
- * `destroy?` will resolve to `edit?`
119
- * `manage?` will resolve to `manage?`
120
- * `edit?` will resolve to `edit?`
121
- * `index?` will resolve to `manage?`
122
- * `something?` will raise `ActionPolicy::UnknownRule`
@@ -1,364 +0,0 @@
1
- (function () {
2
- var INDEXS = {};
3
-
4
- var LOCAL_STORAGE = {
5
- EXPIRE_KEY: 'docsify.search.expires',
6
- INDEX_KEY: 'docsify.search.index'
7
- };
8
-
9
- function resolveExpireKey(namespace) {
10
- return namespace ? ((LOCAL_STORAGE.EXPIRE_KEY) + "/" + namespace) : LOCAL_STORAGE.EXPIRE_KEY
11
- }
12
- function resolveIndexKey(namespace) {
13
- return namespace ? ((LOCAL_STORAGE.INDEX_KEY) + "/" + namespace) : LOCAL_STORAGE.INDEX_KEY
14
- }
15
-
16
- function escapeHtml(string) {
17
- var entityMap = {
18
- '&': '&amp;',
19
- '<': '&lt;',
20
- '>': '&gt;',
21
- '"': '&quot;',
22
- '\'': '&#39;',
23
- '/': '&#x2F;'
24
- };
25
-
26
- return String(string).replace(/[&<>"'/]/g, function (s) { return entityMap[s]; })
27
- }
28
-
29
- function getAllPaths(router) {
30
- var paths = [];
31
-
32
- Docsify.dom.findAll('.sidebar-nav a:not(.section-link):not([data-nosearch])').forEach(function (node) {
33
- var href = node.href;
34
- var originHref = node.getAttribute('href');
35
- var path = router.parse(href).path;
36
-
37
- if (
38
- path &&
39
- paths.indexOf(path) === -1 &&
40
- !Docsify.util.isAbsolutePath(originHref)
41
- ) {
42
- paths.push(path);
43
- }
44
- });
45
-
46
- return paths
47
- }
48
-
49
- function saveData(maxAge, expireKey, indexKey) {
50
- localStorage.setItem(expireKey, Date.now() + maxAge);
51
- localStorage.setItem(indexKey, JSON.stringify(INDEXS));
52
- }
53
-
54
- function genIndex(path, content, router, depth) {
55
- if ( content === void 0 ) content = '';
56
-
57
- var tokens = window.marked.lexer(content);
58
- var slugify = window.Docsify.slugify;
59
- var index = {};
60
- var slug;
61
-
62
- tokens.forEach(function (token) {
63
- if (token.type === 'heading' && token.depth <= depth) {
64
- slug = router.toURL(path, {id: slugify(token.text)});
65
- index[slug] = {slug: slug, title: token.text, body: ''};
66
- } else {
67
- if (!slug) {
68
- return
69
- }
70
- if (!index[slug]) {
71
- index[slug] = {slug: slug, title: '', body: ''};
72
- } else if (index[slug].body) {
73
- index[slug].body += '\n' + (token.text || '');
74
- } else {
75
- index[slug].body = token.text;
76
- }
77
- }
78
- });
79
- slugify.clear();
80
- return index
81
- }
82
-
83
- /**
84
- * @param {String} query
85
- * @returns {Array}
86
- */
87
- function search(query) {
88
- var matchingResults = [];
89
- var data = [];
90
- Object.keys(INDEXS).forEach(function (key) {
91
- data = data.concat(Object.keys(INDEXS[key]).map(function (page) { return INDEXS[key][page]; }));
92
- });
93
-
94
- query = query.trim();
95
- var keywords = query.split(/[\s\-,\\/]+/);
96
- if (keywords.length !== 1) {
97
- keywords = [].concat(query, keywords);
98
- }
99
-
100
- var loop = function ( i ) {
101
- var post = data[i];
102
- var matchesScore = 0;
103
- var resultStr = '';
104
- var postTitle = post.title && post.title.trim();
105
- var postContent = post.body && post.body.trim();
106
- var postUrl = post.slug || '';
107
-
108
- if (postTitle) {
109
- keywords.forEach( function (keyword) {
110
- // From https://github.com/sindresorhus/escape-string-regexp
111
- var regEx = new RegExp(
112
- keyword.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'),
113
- 'gi'
114
- );
115
- var indexTitle = -1;
116
- var indexContent = -1;
117
-
118
- indexTitle = postTitle ? postTitle.search(regEx) : -1;
119
- indexContent = postContent ? postContent.search(regEx) : -1;
120
-
121
- if (indexTitle >= 0 || indexContent >= 0) {
122
- matchesScore += indexTitle >= 0 ? 3 : indexContent >= 0 ? 2 : 0;
123
- if (indexContent < 0) {
124
- indexContent = 0;
125
- }
126
-
127
- var start = 0;
128
- var end = 0;
129
-
130
- start = indexContent < 11 ? 0 : indexContent - 10;
131
- end = start === 0 ? 70 : indexContent + keyword.length + 60;
132
-
133
- if (end > postContent.length) {
134
- end = postContent.length;
135
- }
136
-
137
- var matchContent =
138
- '...' +
139
- escapeHtml(postContent)
140
- .substring(start, end)
141
- .replace(regEx, ("<em class=\"search-keyword\">" + keyword + "</em>")) +
142
- '...';
143
-
144
- resultStr += matchContent;
145
- }
146
- });
147
-
148
- if (matchesScore > 0) {
149
- var matchingPost = {
150
- title: escapeHtml(postTitle),
151
- content: postContent ? resultStr : '',
152
- url: postUrl,
153
- score: matchesScore
154
- };
155
-
156
- matchingResults.push(matchingPost);
157
- }
158
- }
159
- };
160
-
161
- for (var i = 0; i < data.length; i++) loop( i );
162
-
163
- return matchingResults.sort(function (r1, r2) { return r2.score - r1.score; });
164
- }
165
-
166
- function init$1(config, vm) {
167
- var isAuto = config.paths === 'auto';
168
-
169
- var expireKey = resolveExpireKey(config.namespace);
170
- var indexKey = resolveIndexKey(config.namespace);
171
-
172
- var isExpired = localStorage.getItem(expireKey) < Date.now();
173
-
174
- INDEXS = JSON.parse(localStorage.getItem(indexKey));
175
-
176
- if (isExpired) {
177
- INDEXS = {};
178
- } else if (!isAuto) {
179
- return
180
- }
181
-
182
- var paths = isAuto ? getAllPaths(vm.router) : config.paths;
183
- var len = paths.length;
184
- var count = 0;
185
-
186
- paths.forEach(function (path) {
187
- if (INDEXS[path]) {
188
- return count++
189
- }
190
-
191
- Docsify
192
- .get(vm.router.getFile(path), false, vm.config.requestHeaders)
193
- .then(function (result) {
194
- INDEXS[path] = genIndex(path, result, vm.router, config.depth);
195
- len === ++count && saveData(config.maxAge, expireKey, indexKey);
196
- });
197
- });
198
- }
199
-
200
- var NO_DATA_TEXT = '';
201
- var options;
202
-
203
- function style() {
204
- var code = "\n.sidebar {\n padding-top: 0;\n}\n\n.search {\n margin-bottom: 20px;\n padding: 6px;\n border-bottom: 1px solid #eee;\n}\n\n.search .input-wrap {\n display: flex;\n align-items: center;\n}\n\n.search .results-panel {\n display: none;\n}\n\n.search .results-panel.show {\n display: block;\n}\n\n.search input {\n outline: none;\n border: none;\n width: 100%;\n padding: 0 7px;\n line-height: 36px;\n font-size: 14px;\n}\n\n.search input::-webkit-search-decoration,\n.search input::-webkit-search-cancel-button,\n.search input {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n.search .clear-button {\n width: 36px;\n text-align: right;\n display: none;\n}\n\n.search .clear-button.show {\n display: block;\n}\n\n.search .clear-button svg {\n transform: scale(.5);\n}\n\n.search h2 {\n font-size: 17px;\n margin: 10px 0;\n}\n\n.search a {\n text-decoration: none;\n color: inherit;\n}\n\n.search .matching-post {\n border-bottom: 1px solid #eee;\n}\n\n.search .matching-post:last-child {\n border-bottom: 0;\n}\n\n.search p {\n font-size: 14px;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n.search p.empty {\n text-align: center;\n}\n\n.app-name.hide, .sidebar-nav.hide {\n display: none;\n}";
205
-
206
- Docsify.dom.style(code);
207
- }
208
-
209
- function tpl(defaultValue) {
210
- if ( defaultValue === void 0 ) defaultValue = '';
211
-
212
- var html =
213
- "<div class=\"input-wrap\">\n <input type=\"search\" value=\"" + defaultValue + "\" />\n <div class=\"clear-button\">\n <svg width=\"26\" height=\"24\">\n <circle cx=\"12\" cy=\"12\" r=\"11\" fill=\"#ccc\" />\n <path stroke=\"white\" stroke-width=\"2\" d=\"M8.25,8.25,15.75,15.75\" />\n <path stroke=\"white\" stroke-width=\"2\"d=\"M8.25,15.75,15.75,8.25\" />\n </svg>\n </div>\n </div>\n <div class=\"results-panel\"></div>\n </div>";
214
- var el = Docsify.dom.create('div', html);
215
- var aside = Docsify.dom.find('aside');
216
-
217
- Docsify.dom.toggleClass(el, 'search');
218
- Docsify.dom.before(aside, el);
219
- }
220
-
221
- function doSearch(value) {
222
- var $search = Docsify.dom.find('div.search');
223
- var $panel = Docsify.dom.find($search, '.results-panel');
224
- var $clearBtn = Docsify.dom.find($search, '.clear-button');
225
- var $sidebarNav = Docsify.dom.find('.sidebar-nav');
226
- var $appName = Docsify.dom.find('.app-name');
227
-
228
- if (!value) {
229
- $panel.classList.remove('show');
230
- $clearBtn.classList.remove('show');
231
- $panel.innerHTML = '';
232
-
233
- if (options.hideOtherSidebarContent) {
234
- $sidebarNav.classList.remove('hide');
235
- $appName.classList.remove('hide');
236
- }
237
- return
238
- }
239
- var matchs = search(value);
240
-
241
- var html = '';
242
- matchs.forEach(function (post) {
243
- html += "<div class=\"matching-post\">\n<a href=\"" + (post.url) + "\">\n<h2>" + (post.title) + "</h2>\n<p>" + (post.content) + "</p>\n</a>\n</div>";
244
- });
245
-
246
- $panel.classList.add('show');
247
- $clearBtn.classList.add('show');
248
- $panel.innerHTML = html || ("<p class=\"empty\">" + NO_DATA_TEXT + "</p>");
249
- if (options.hideOtherSidebarContent) {
250
- $sidebarNav.classList.add('hide');
251
- $appName.classList.add('hide');
252
- }
253
- }
254
-
255
- function bindEvents() {
256
- var $search = Docsify.dom.find('div.search');
257
- var $input = Docsify.dom.find($search, 'input');
258
- var $inputWrap = Docsify.dom.find($search, '.input-wrap');
259
-
260
- var timeId;
261
- // Prevent to Fold sidebar
262
- Docsify.dom.on(
263
- $search,
264
- 'click',
265
- function (e) { return e.target.tagName !== 'A' && e.stopPropagation(); }
266
- );
267
- Docsify.dom.on($input, 'input', function (e) {
268
- clearTimeout(timeId);
269
- timeId = setTimeout(function (_) { return doSearch(e.target.value.trim()); }, 100);
270
- });
271
- Docsify.dom.on($inputWrap, 'click', function (e) {
272
- // Click input outside
273
- if (e.target.tagName !== 'INPUT') {
274
- $input.value = '';
275
- doSearch();
276
- }
277
- });
278
- }
279
-
280
- function updatePlaceholder(text, path) {
281
- var $input = Docsify.dom.getNode('.search input[type="search"]');
282
-
283
- if (!$input) {
284
- return
285
- }
286
- if (typeof text === 'string') {
287
- $input.placeholder = text;
288
- } else {
289
- var match = Object.keys(text).filter(function (key) { return path.indexOf(key) > -1; })[0];
290
- $input.placeholder = text[match];
291
- }
292
- }
293
-
294
- function updateNoData(text, path) {
295
- if (typeof text === 'string') {
296
- NO_DATA_TEXT = text;
297
- } else {
298
- var match = Object.keys(text).filter(function (key) { return path.indexOf(key) > -1; })[0];
299
- NO_DATA_TEXT = text[match];
300
- }
301
- }
302
-
303
- function updateOptions(opts) {
304
- options = opts;
305
- }
306
-
307
- function init(opts, vm) {
308
- var keywords = vm.router.parse().query.s;
309
-
310
- updateOptions(opts);
311
- style();
312
- tpl(keywords);
313
- bindEvents();
314
- keywords && setTimeout(function (_) { return doSearch(keywords); }, 500);
315
- }
316
-
317
- function update(opts, vm) {
318
- updateOptions(opts);
319
- updatePlaceholder(opts.placeholder, vm.route.path);
320
- updateNoData(opts.noData, vm.route.path);
321
- }
322
-
323
- var CONFIG = {
324
- placeholder: 'Type to search',
325
- noData: 'No Results!',
326
- paths: 'auto',
327
- depth: 2,
328
- maxAge: 86400000, // 1 day
329
- hideOtherSidebarContent: false,
330
- namespace: undefined
331
- };
332
-
333
- var install = function (hook, vm) {
334
- var util = Docsify.util;
335
- var opts = vm.config.search || CONFIG;
336
-
337
- if (Array.isArray(opts)) {
338
- CONFIG.paths = opts;
339
- } else if (typeof opts === 'object') {
340
- CONFIG.paths = Array.isArray(opts.paths) ? opts.paths : 'auto';
341
- CONFIG.maxAge = util.isPrimitive(opts.maxAge) ? opts.maxAge : CONFIG.maxAge;
342
- CONFIG.placeholder = opts.placeholder || CONFIG.placeholder;
343
- CONFIG.noData = opts.noData || CONFIG.noData;
344
- CONFIG.depth = opts.depth || CONFIG.depth;
345
- CONFIG.hideOtherSidebarContent = opts.hideOtherSidebarContent || CONFIG.hideOtherSidebarContent;
346
- CONFIG.namespace = opts.namespace || CONFIG.namespace;
347
- }
348
-
349
- var isAuto = CONFIG.paths === 'auto';
350
-
351
- hook.mounted(function (_) {
352
- init(CONFIG, vm);
353
- !isAuto && init$1(CONFIG, vm);
354
- });
355
- hook.doneEach(function (_) {
356
- update(CONFIG, vm);
357
- isAuto && init$1(CONFIG, vm);
358
- });
359
- };
360
-
361
- $docsify.plugins = [].concat(install, $docsify.plugins);
362
-
363
- }());
364
-