action_policy 0.4.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +203 -174
  3. data/README.md +5 -4
  4. data/lib/action_policy.rb +7 -1
  5. data/lib/action_policy/behaviour.rb +22 -16
  6. data/lib/action_policy/behaviours/policy_for.rb +10 -3
  7. data/lib/action_policy/behaviours/scoping.rb +2 -1
  8. data/lib/action_policy/behaviours/thread_memoized.rb +1 -3
  9. data/lib/action_policy/ext/module_namespace.rb +1 -6
  10. data/lib/action_policy/ext/policy_cache_key.rb +10 -30
  11. data/lib/action_policy/i18n.rb +1 -1
  12. data/lib/action_policy/lookup_chain.rb +29 -15
  13. data/lib/action_policy/policy/aliases.rb +7 -12
  14. data/lib/action_policy/policy/authorization.rb +8 -7
  15. data/lib/action_policy/policy/cache.rb +11 -17
  16. data/lib/action_policy/policy/core.rb +25 -12
  17. data/lib/action_policy/policy/defaults.rb +3 -9
  18. data/lib/action_policy/policy/execution_result.rb +3 -9
  19. data/lib/action_policy/policy/pre_check.rb +19 -58
  20. data/lib/action_policy/policy/reasons.rb +29 -19
  21. data/lib/action_policy/policy/scoping.rb +5 -6
  22. data/lib/action_policy/rails/controller.rb +6 -1
  23. data/lib/action_policy/rails/policy/instrumentation.rb +1 -1
  24. data/lib/action_policy/rspec/be_authorized_to.rb +5 -9
  25. data/lib/action_policy/rspec/dsl.rb +1 -1
  26. data/lib/action_policy/rspec/have_authorized_scope.rb +5 -7
  27. data/lib/action_policy/utils/pretty_print.rb +21 -24
  28. data/lib/action_policy/utils/suggest_message.rb +1 -3
  29. data/lib/action_policy/version.rb +1 -1
  30. data/lib/generators/action_policy/install/templates/{application_policy.rb → application_policy.rb.tt} +0 -0
  31. data/lib/generators/action_policy/policy/policy_generator.rb +4 -1
  32. data/lib/generators/action_policy/policy/templates/{policy.rb → policy.rb.tt} +0 -0
  33. data/lib/generators/rspec/templates/{policy_spec.rb → policy_spec.rb.tt} +0 -0
  34. data/lib/generators/test_unit/templates/{policy_test.rb → policy_test.rb.tt} +0 -0
  35. metadata +29 -119
  36. data/.gitattributes +0 -2
  37. data/.github/ISSUE_TEMPLATE.md +0 -21
  38. data/.github/PULL_REQUEST_TEMPLATE.md +0 -29
  39. data/.github/bug_report_template.rb +0 -175
  40. data/.gitignore +0 -15
  41. data/.rubocop.yml +0 -54
  42. data/.tidelift.yml +0 -6
  43. data/.travis.yml +0 -31
  44. data/Gemfile +0 -22
  45. data/Rakefile +0 -27
  46. data/action_policy.gemspec +0 -44
  47. data/benchmarks/namespaced_lookup_cache.rb +0 -74
  48. data/benchmarks/pre_checks.rb +0 -73
  49. data/bin/console +0 -14
  50. data/bin/setup +0 -8
  51. data/docs/.nojekyll +0 -0
  52. data/docs/CNAME +0 -1
  53. data/docs/README.md +0 -79
  54. data/docs/_sidebar.md +0 -27
  55. data/docs/aliases.md +0 -122
  56. data/docs/assets/docsify-search.js +0 -364
  57. data/docs/assets/docsify.min.js +0 -3
  58. data/docs/assets/fonts/FiraCode-Medium.woff +0 -0
  59. data/docs/assets/fonts/FiraCode-Regular.woff +0 -0
  60. data/docs/assets/images/banner.png +0 -0
  61. data/docs/assets/images/cache.png +0 -0
  62. data/docs/assets/images/cache.svg +0 -70
  63. data/docs/assets/images/layer.png +0 -0
  64. data/docs/assets/images/layer.svg +0 -35
  65. data/docs/assets/prism-ruby.min.js +0 -1
  66. data/docs/assets/styles.css +0 -347
  67. data/docs/assets/vue.min.css +0 -1
  68. data/docs/authorization_context.md +0 -92
  69. data/docs/behaviour.md +0 -113
  70. data/docs/caching.md +0 -291
  71. data/docs/controller_action_aliases.md +0 -109
  72. data/docs/custom_lookup_chain.md +0 -48
  73. data/docs/custom_policy.md +0 -53
  74. data/docs/debugging.md +0 -55
  75. data/docs/decorators.md +0 -27
  76. data/docs/favicon.ico +0 -0
  77. data/docs/graphql.md +0 -302
  78. data/docs/i18n.md +0 -44
  79. data/docs/index.html +0 -43
  80. data/docs/instrumentation.md +0 -84
  81. data/docs/lookup_chain.md +0 -22
  82. data/docs/namespaces.md +0 -77
  83. data/docs/non_rails.md +0 -28
  84. data/docs/pre_checks.md +0 -57
  85. data/docs/pundit_migration.md +0 -80
  86. data/docs/quick_start.md +0 -118
  87. data/docs/rails.md +0 -120
  88. data/docs/reasons.md +0 -120
  89. data/docs/scoping.md +0 -255
  90. data/docs/testing.md +0 -390
  91. data/docs/writing_policies.md +0 -107
  92. data/gemfiles/jruby.gemfile +0 -8
  93. data/gemfiles/rails42.gemfile +0 -9
  94. data/gemfiles/rails6.gemfile +0 -8
  95. data/gemfiles/railsmaster.gemfile +0 -6
  96. data/lib/action_policy/ext/string_match.rb +0 -14
  97. 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
-