html-pipeline-task_list 0.0.1

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.
@@ -0,0 +1,20 @@
1
+ // Requires use of `.markdown-body` to override default markdown list styles
2
+ .markdown-body .task-list {
3
+ list-style-type: none;
4
+ padding-left: 10px;
5
+ }
6
+
7
+ .task-list-item {
8
+ padding-left: 20px;
9
+ }
10
+ .task-list-item label {
11
+ font-weight: normal;
12
+ }
13
+ .task-list-item + .task-list-item {
14
+ margin-top: 3px;
15
+ }
16
+ .task-list-item-checkbox {
17
+ float: left;
18
+ margin-left: -20px;
19
+ margin-top: 4px;
20
+ }
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'html/pipeline/task_list/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'html-pipeline-task_list'
9
+ gem.version = ::HTML::Pipeline::TaskList::VERSION
10
+ gem.license = 'MIT'
11
+ gem.authors = ['Codetree']
12
+ gem.email = ['support@codetree.com']
13
+ gem.homepage = 'https://github.com/codetree/html-pipeline-task_list'
14
+ gem.summary = 'An HTML::Pipeline filter for creating GitHub-flavored Markdown TaskLists'
15
+ gem.description = gem.summary
16
+
17
+ gem.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f =~ %r{^(test|script|gemfiles)/ }
19
+ end
20
+
21
+ gem.require_paths = ['lib']
22
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
23
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
24
+
25
+ gem.add_dependency 'html-pipeline', '~> 2.12'
26
+
27
+ gem.add_development_dependency 'bundler', '~> 2.1', '>=2.1.4'
28
+ gem.add_development_dependency 'commonmarker', '~> 0.21.0'
29
+ gem.add_development_dependency 'github-markdown', '~> 0.6.9'
30
+ gem.add_development_dependency 'guard', '~> 2.16'
31
+ gem.add_development_dependency 'guard-minitest', '~> 2.4'
32
+ gem.add_development_dependency 'guard-rubocop', '~> 1.3'
33
+ gem.add_development_dependency 'json', '~> 2.3'
34
+ gem.add_development_dependency 'minitest', '~> 5.14'
35
+ gem.add_development_dependency 'rake', '~> 13.0'
36
+ gem.add_development_dependency 'rubocop', '~> 0.80.1'
37
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'html/pipeline'
4
+ require 'html/pipeline/task_list/summary'
5
+
6
+ module HTML
7
+ class Pipeline
8
+ # Generates task lists (e.g., checkboxes) from Github falvored
9
+ # markdown. See ./filter.rb for more details
10
+ class TaskList
11
+ attr_reader :record
12
+
13
+ # `record` is the resource with the Markdown source text with task list items
14
+ # following this syntax:
15
+ #
16
+ # - [ ] a task list item
17
+ # - [ ] another item
18
+ # - [x] a completed item
19
+ #
20
+ def initialize(record)
21
+ @record = record
22
+ end
23
+
24
+ # Public: return the TaskList::Summary for this task list.
25
+ #
26
+ # Returns a TaskList::Summary.
27
+ def summary
28
+ @summary ||= HTML::Pipeline::TaskList::Summary.new(record.task_list_items)
29
+ end
30
+
31
+ Item = Struct.new(:checkbox_text, :source) do
32
+ COMPLETE = /\[[xX]\]/.freeze # see TaskList::Filter
33
+
34
+ # Public: Check if a task list is complete.
35
+ #
36
+ # Examples
37
+ #
38
+ # Item.new(checkbox_text: "- [x]").complete?
39
+ # # => true
40
+ #
41
+ # Item.new(checkbox_text: "- [ ]").complete?
42
+ # # => false
43
+ #
44
+ # Returns true for checked list, false otherwise
45
+ def complete?
46
+ checkbox_text =~ COMPLETE
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'html/pipeline'
4
+
5
+ module HTML
6
+ class Pipeline
7
+ # Generates task lists (e.g., checkboxes) from GitHub flavored
8
+ # markdown. Requires processing by Markdown filter and therefore
9
+ # must follow HTML::Pipeline::MarkdownFilter in the pipeline
10
+ #
11
+ # Usage:
12
+ #
13
+ # require 'html/pipeline'
14
+ # require 'html/pipeline/task_list/filter'
15
+ #
16
+ # pipeline = HTML::Pipeline.new [
17
+ # HTML::Pipeline::MarkdownFilter,
18
+ # HTML::Pipeline::TaskList::Filter
19
+ # ]
20
+ #
21
+ # pipeline.call "- [ ] task list item"
22
+ #
23
+ class TaskList
24
+ # Returns a `Nokogiri::DocumentFragment` object.
25
+ def self.filter(*args)
26
+ Filter.call(*args)
27
+ end
28
+
29
+ # TaskList filter replaces task list item markers (`[ ]` and `[x]`) with
30
+ # checkboxes, marked up with metadata and behavior.
31
+ #
32
+ # This should be run on the HTML generated by the Markdown filter, after the
33
+ # SanitizationFilter.
34
+ #
35
+ # Syntax
36
+ # ------
37
+ #
38
+ # Task list items must be in a list format:
39
+ #
40
+ # ```
41
+ # - [ ] incomplete
42
+ # - [x] complete
43
+ # ```
44
+ #
45
+ # Results
46
+ # -------
47
+ #
48
+ # The following keys are written to the result hash:
49
+ # :task_list_items - An array of TaskList::Item objects.
50
+ class Filter < HTML::Pipeline::Filter
51
+ INCOMPLETE = '[ ]'
52
+ COMPLETE = '[x]'
53
+
54
+ INCOMPLETE_PATTERN = /\[[[:space:]]\]/.freeze # matches all whitespace
55
+ COMPLETE_PATTERN = /\[[xX]\]/.freeze # matches any capitalization
56
+
57
+ # Pattern used to identify all task list items.
58
+ # Useful when you need iterate over all items.
59
+ ITEM_PATTERN = /
60
+ ^
61
+ (?:\s*[-+*]|(?:\d+\.))? # optional list prefix
62
+ \s* # optional whitespace prefix
63
+ ( # checkbox
64
+ #{COMPLETE_PATTERN}|
65
+ #{INCOMPLETE_PATTERN}
66
+ )
67
+ (?=\s) # followed by whitespace
68
+ /x.freeze
69
+
70
+ LIST_ITEM_SELECTOR = './/li[task_list_item(.)]'
71
+
72
+ # Underlying XPath Selector for identifying items matching
73
+ # the ITEM_PATTERN
74
+ class XPathSelectorFunction
75
+ def self.task_list_item(nodes)
76
+ nodes.find_all { |x| x.text =~ ITEM_PATTERN }
77
+ end
78
+ end
79
+
80
+ # Selects first P tag of an LI, if present
81
+ ITEM_PARA_SELECTOR = './p[1]'
82
+
83
+ # List of `TaskList::Item` objects that were recognized in the document.
84
+ # This is available in the result hash as `:task_list_items`.
85
+ #
86
+ # Returns an Array of TaskList::Item objects.
87
+ def task_list_items
88
+ result[:task_list_items] ||= []
89
+ end
90
+
91
+ # Renders the item checkbox in a span including the item state.
92
+ #
93
+ # Returns an HTML-safe String.
94
+ def render_item_checkbox(item)
95
+ %(<input type="checkbox"
96
+ class="task-list-item-checkbox"
97
+ #{'checked="checked"' if item.complete?}
98
+ disabled="disabled"
99
+ />)
100
+ end
101
+
102
+ # Public: Marks up the task list item checkbox with metadata and behavior.
103
+ #
104
+ # NOTE: produces a string that, when assigned to a Node's `inner_html`,
105
+ # will corrupt the string contents' encodings. Instead, we parse the
106
+ # rendered HTML and explicitly set its encoding so that assignment will
107
+ # not change the encodings.
108
+ #
109
+ # See [this pull](https://github.com/github/github/pull/8505) for details.
110
+ #
111
+ # Returns the marked up task list item Nokogiri::XML::NodeSet object.
112
+ def render_task_list_item(item)
113
+ Nokogiri::HTML.fragment \
114
+ item.source.sub(ITEM_PATTERN, render_item_checkbox(item)), 'utf-8'
115
+ end
116
+
117
+ # Public: Select all task lists from the `doc`.
118
+ #
119
+ # Returns an Array of Nokogiri::XML::Element objects for ordered and
120
+ # unordered lists.
121
+ def list_items
122
+ doc.xpath(LIST_ITEM_SELECTOR, XPathSelectorFunction)
123
+ end
124
+
125
+ # Filters the source for task list items.
126
+ #
127
+ # Each item is wrapped in HTML to identify, style, and layer
128
+ # useful behavior on top of.
129
+ #
130
+ # Modifications apply to the parsed document directly.
131
+ #
132
+ # Returns nothing.
133
+ def filter!
134
+ list_items.reverse.each do |li|
135
+ add_css_class(li.parent, 'task-list')
136
+
137
+ outer, inner = item_selector(li)
138
+
139
+ unless (match = (inner.chomp =~ ITEM_PATTERN && Regexp.last_match(1)))
140
+ next
141
+ end
142
+
143
+ item = HTML::Pipeline::TaskList::Item.new(match, inner)
144
+ # prepend because we're iterating in reverse
145
+ task_list_items.unshift item
146
+
147
+ add_css_class(li, 'task-list-item')
148
+ outer.inner_html = render_task_list_item(item)
149
+ end
150
+ end
151
+
152
+ def call
153
+ filter!
154
+ doc
155
+ end
156
+
157
+ # Private: adds a CSS class name to a node, respecting existing class
158
+ # names.
159
+ def add_css_class(node, *new_class_names)
160
+ class_names = (node['class'] || '').split(' ')
161
+ return if new_class_names.all? { |klass| class_names.include?(klass) }
162
+
163
+ class_names.concat(new_class_names)
164
+ node['class'] = class_names.uniq.join(' ')
165
+ end
166
+
167
+ private
168
+
169
+ def item_selector(item)
170
+ if (p = item.xpath(ITEM_PARA_SELECTOR)[0])
171
+ [p, p.inner_html]
172
+ else
173
+ [item, item.inner_html]
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTML
4
+ class Pipeline
5
+ # utilized to integrate into rails asset pipeline
6
+ class TaskList
7
+ class << self
8
+ def root_path
9
+ @root_path ||= Pathname.new(File.expand_path('../..', __dir__))
10
+ end
11
+
12
+ def asset_paths
13
+ @asset_paths ||= Dir[root_path.join('app/assets/*')]
14
+ end
15
+ end
16
+
17
+ if defined? ::Rails::Railtie
18
+ # If the Rails asset pipeline exists, incorporate into
19
+ # asset pipeline
20
+ class Railtie < ::Rails::Railtie
21
+ initializer 'task_list' do |app|
22
+ TaskList.asset_paths.each do |path|
23
+ app.config.assets.paths << path
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'html/pipeline'
4
+
5
+ module HTML
6
+ class Pipeline
7
+ class TaskList
8
+ # Provides a summary of provided TaskList `items`.
9
+ #
10
+ # `items` is an Array of TaskList::Item objects.
11
+ Summary = Struct.new(:items) do
12
+ # Public: returns true if there are any TaskList::Item objects.
13
+ def items?
14
+ item_count.positive?
15
+ end
16
+
17
+ # Public: returns the number of TaskList::Item objects.
18
+ def item_count
19
+ items.size
20
+ end
21
+
22
+ # Public: returns the number of complete TaskList::Item objects.
23
+ def complete_count
24
+ items.select(&:complete?).size
25
+ end
26
+
27
+ # Public: returns the number of incomplete TaskList::Item objects.
28
+ def incomplete_count
29
+ items.reject(&:complete?).size
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTML
4
+ class Pipeline
5
+ class TaskList
6
+ VERSION = '0.0.1'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,455 @@
1
+ {
2
+ "name": "task_list",
3
+ "version": "1.0.2",
4
+ "lockfileVersion": 1,
5
+ "requires": true,
6
+ "dependencies": {
7
+ "@types/mime-types": {
8
+ "version": "2.1.0",
9
+ "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz",
10
+ "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=",
11
+ "dev": true
12
+ },
13
+ "agent-base": {
14
+ "version": "5.1.1",
15
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz",
16
+ "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==",
17
+ "dev": true
18
+ },
19
+ "async-limiter": {
20
+ "version": "1.0.1",
21
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
22
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
23
+ "dev": true
24
+ },
25
+ "balanced-match": {
26
+ "version": "1.0.0",
27
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
28
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
29
+ "dev": true
30
+ },
31
+ "brace-expansion": {
32
+ "version": "1.1.11",
33
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
34
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
35
+ "dev": true,
36
+ "requires": {
37
+ "balanced-match": "^1.0.0",
38
+ "concat-map": "0.0.1"
39
+ }
40
+ },
41
+ "buffer-crc32": {
42
+ "version": "0.2.13",
43
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
44
+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
45
+ "dev": true
46
+ },
47
+ "buffer-from": {
48
+ "version": "1.1.1",
49
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
50
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
51
+ "dev": true
52
+ },
53
+ "colors": {
54
+ "version": "1.4.0",
55
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
56
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
57
+ "dev": true
58
+ },
59
+ "commander": {
60
+ "version": "2.12.2",
61
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz",
62
+ "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==",
63
+ "dev": true
64
+ },
65
+ "concat-map": {
66
+ "version": "0.0.1",
67
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
68
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
69
+ "dev": true
70
+ },
71
+ "concat-stream": {
72
+ "version": "1.6.2",
73
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
74
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
75
+ "dev": true,
76
+ "requires": {
77
+ "buffer-from": "^1.0.0",
78
+ "inherits": "^2.0.3",
79
+ "readable-stream": "^2.2.2",
80
+ "typedarray": "^0.0.6"
81
+ },
82
+ "dependencies": {
83
+ "process-nextick-args": {
84
+ "version": "2.0.1",
85
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
86
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
87
+ "dev": true
88
+ },
89
+ "readable-stream": {
90
+ "version": "2.3.7",
91
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
92
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
93
+ "dev": true,
94
+ "requires": {
95
+ "core-util-is": "~1.0.0",
96
+ "inherits": "~2.0.3",
97
+ "isarray": "~1.0.0",
98
+ "process-nextick-args": "~2.0.0",
99
+ "safe-buffer": "~5.1.1",
100
+ "string_decoder": "~1.1.1",
101
+ "util-deprecate": "~1.0.1"
102
+ }
103
+ },
104
+ "string_decoder": {
105
+ "version": "1.1.1",
106
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
107
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
108
+ "dev": true,
109
+ "requires": {
110
+ "safe-buffer": "~5.1.0"
111
+ }
112
+ }
113
+ }
114
+ },
115
+ "core-util-is": {
116
+ "version": "1.0.2",
117
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
118
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
119
+ "dev": true
120
+ },
121
+ "debug": {
122
+ "version": "2.6.9",
123
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
124
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
125
+ "dev": true,
126
+ "requires": {
127
+ "ms": "2.0.0"
128
+ }
129
+ },
130
+ "extract-zip": {
131
+ "version": "1.7.0",
132
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
133
+ "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
134
+ "dev": true,
135
+ "requires": {
136
+ "concat-stream": "^1.6.2",
137
+ "debug": "^2.6.9",
138
+ "mkdirp": "^0.5.4",
139
+ "yauzl": "^2.10.0"
140
+ }
141
+ },
142
+ "fd-slicer": {
143
+ "version": "1.1.0",
144
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
145
+ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
146
+ "dev": true,
147
+ "requires": {
148
+ "pend": "~1.2.0"
149
+ }
150
+ },
151
+ "fs.realpath": {
152
+ "version": "1.0.0",
153
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
154
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
155
+ "dev": true
156
+ },
157
+ "glob": {
158
+ "version": "7.1.6",
159
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
160
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
161
+ "dev": true,
162
+ "requires": {
163
+ "fs.realpath": "^1.0.0",
164
+ "inflight": "^1.0.4",
165
+ "inherits": "2",
166
+ "minimatch": "^3.0.4",
167
+ "once": "^1.3.0",
168
+ "path-is-absolute": "^1.0.0"
169
+ }
170
+ },
171
+ "https-proxy-agent": {
172
+ "version": "4.0.0",
173
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz",
174
+ "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==",
175
+ "dev": true,
176
+ "requires": {
177
+ "agent-base": "5",
178
+ "debug": "4"
179
+ },
180
+ "dependencies": {
181
+ "debug": {
182
+ "version": "4.1.1",
183
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
184
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
185
+ "dev": true,
186
+ "requires": {
187
+ "ms": "^2.1.1"
188
+ }
189
+ },
190
+ "ms": {
191
+ "version": "2.1.2",
192
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
193
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
194
+ "dev": true
195
+ }
196
+ }
197
+ },
198
+ "inflight": {
199
+ "version": "1.0.6",
200
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
201
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
202
+ "dev": true,
203
+ "requires": {
204
+ "once": "^1.3.0",
205
+ "wrappy": "1"
206
+ }
207
+ },
208
+ "inherits": {
209
+ "version": "2.0.4",
210
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
211
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
212
+ "dev": true
213
+ },
214
+ "isarray": {
215
+ "version": "1.0.0",
216
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
217
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
218
+ "dev": true
219
+ },
220
+ "jquery": {
221
+ "version": "3.4.1",
222
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
223
+ "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
224
+ },
225
+ "jquery-ujs": {
226
+ "version": "1.2.2",
227
+ "resolved": "https://registry.npmjs.org/jquery-ujs/-/jquery-ujs-1.2.2.tgz",
228
+ "integrity": "sha1-ao7xAg5rbdo4W5CkvdwSjCHFY5c=",
229
+ "requires": {
230
+ "jquery": ">=1.8.0"
231
+ }
232
+ },
233
+ "js-reporters": {
234
+ "version": "1.2.1",
235
+ "resolved": "https://registry.npmjs.org/js-reporters/-/js-reporters-1.2.1.tgz",
236
+ "integrity": "sha1-+IxgjjJKM3OpW8xFrTBeXJecRZs=",
237
+ "dev": true
238
+ },
239
+ "mime": {
240
+ "version": "2.4.4",
241
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
242
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
243
+ "dev": true
244
+ },
245
+ "mime-db": {
246
+ "version": "1.43.0",
247
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
248
+ "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
249
+ "dev": true
250
+ },
251
+ "mime-types": {
252
+ "version": "2.1.26",
253
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
254
+ "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
255
+ "dev": true,
256
+ "requires": {
257
+ "mime-db": "1.43.0"
258
+ }
259
+ },
260
+ "minimatch": {
261
+ "version": "3.0.4",
262
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
263
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
264
+ "dev": true,
265
+ "requires": {
266
+ "brace-expansion": "^1.1.7"
267
+ }
268
+ },
269
+ "minimist": {
270
+ "version": "1.2.5",
271
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
272
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
273
+ "dev": true
274
+ },
275
+ "mkdirp": {
276
+ "version": "0.5.4",
277
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
278
+ "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
279
+ "dev": true,
280
+ "requires": {
281
+ "minimist": "^1.2.5"
282
+ }
283
+ },
284
+ "ms": {
285
+ "version": "2.0.0",
286
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
287
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
288
+ "dev": true
289
+ },
290
+ "node-qunit-puppeteer": {
291
+ "version": "2.0.1",
292
+ "resolved": "https://registry.npmjs.org/node-qunit-puppeteer/-/node-qunit-puppeteer-2.0.1.tgz",
293
+ "integrity": "sha512-+zrhKqv73XcdGfQaneUejqYHyT3H5dYpHi71JWrTryMLrHefAwuRe5u0CxPDjAphmRI0Evshx2tcW9RdwV/+aA==",
294
+ "dev": true,
295
+ "requires": {
296
+ "colors": "^1.4.0",
297
+ "puppeteer": "^2.1.0"
298
+ }
299
+ },
300
+ "node-watch": {
301
+ "version": "0.6.1",
302
+ "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.6.1.tgz",
303
+ "integrity": "sha512-gwQiR7weFRV8mAtT0x0kXkZ18dfRLB45xH7q0hCOVQMLfLb2f1ZaSvR57q4/b/Vj6B0RwMNJYbvb69e1yM7qEA==",
304
+ "dev": true
305
+ },
306
+ "once": {
307
+ "version": "1.4.0",
308
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
309
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
310
+ "dev": true,
311
+ "requires": {
312
+ "wrappy": "1"
313
+ }
314
+ },
315
+ "path-is-absolute": {
316
+ "version": "1.0.1",
317
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
318
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
319
+ "dev": true
320
+ },
321
+ "path-parse": {
322
+ "version": "1.0.6",
323
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
324
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
325
+ "dev": true
326
+ },
327
+ "pend": {
328
+ "version": "1.2.0",
329
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
330
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
331
+ "dev": true
332
+ },
333
+ "proxy-from-env": {
334
+ "version": "1.1.0",
335
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
336
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
337
+ "dev": true
338
+ },
339
+ "puppeteer": {
340
+ "version": "2.1.1",
341
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-2.1.1.tgz",
342
+ "integrity": "sha512-LWzaDVQkk1EPiuYeTOj+CZRIjda4k2s5w4MK4xoH2+kgWV/SDlkYHmxatDdtYrciHUKSXTsGgPgPP8ILVdBsxg==",
343
+ "dev": true,
344
+ "requires": {
345
+ "@types/mime-types": "^2.1.0",
346
+ "debug": "^4.1.0",
347
+ "extract-zip": "^1.6.6",
348
+ "https-proxy-agent": "^4.0.0",
349
+ "mime": "^2.0.3",
350
+ "mime-types": "^2.1.25",
351
+ "progress": "^2.0.1",
352
+ "proxy-from-env": "^1.0.0",
353
+ "rimraf": "^2.6.1",
354
+ "ws": "^6.1.0"
355
+ },
356
+ "dependencies": {
357
+ "debug": {
358
+ "version": "4.1.1",
359
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
360
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
361
+ "dev": true,
362
+ "requires": {
363
+ "ms": "^2.1.1"
364
+ }
365
+ },
366
+ "ms": {
367
+ "version": "2.1.2",
368
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
369
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
370
+ "dev": true
371
+ },
372
+ "progress": {
373
+ "version": "2.0.3",
374
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
375
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
376
+ "dev": true
377
+ }
378
+ }
379
+ },
380
+ "qunit": {
381
+ "version": "2.9.3",
382
+ "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.9.3.tgz",
383
+ "integrity": "sha512-RH4VYSaVsNRDthMFFboTJAJ8q4kJM5LvOqWponKUYPEAeOcmc/YFV1QsZ7ikknA3TjqliWFJYEV63vvVXaALmQ==",
384
+ "dev": true,
385
+ "requires": {
386
+ "commander": "2.12.2",
387
+ "js-reporters": "1.2.1",
388
+ "minimatch": "3.0.4",
389
+ "node-watch": "0.6.1",
390
+ "resolve": "1.9.0"
391
+ }
392
+ },
393
+ "resolve": {
394
+ "version": "1.9.0",
395
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz",
396
+ "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==",
397
+ "dev": true,
398
+ "requires": {
399
+ "path-parse": "^1.0.6"
400
+ }
401
+ },
402
+ "rimraf": {
403
+ "version": "2.7.1",
404
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
405
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
406
+ "dev": true,
407
+ "requires": {
408
+ "glob": "^7.1.3"
409
+ }
410
+ },
411
+ "safe-buffer": {
412
+ "version": "5.1.2",
413
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
414
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
415
+ "dev": true
416
+ },
417
+ "typedarray": {
418
+ "version": "0.0.6",
419
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
420
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
421
+ "dev": true
422
+ },
423
+ "util-deprecate": {
424
+ "version": "1.0.2",
425
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
426
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
427
+ "dev": true
428
+ },
429
+ "wrappy": {
430
+ "version": "1.0.2",
431
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
432
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
433
+ "dev": true
434
+ },
435
+ "ws": {
436
+ "version": "6.2.1",
437
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
438
+ "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
439
+ "dev": true,
440
+ "requires": {
441
+ "async-limiter": "~1.0.0"
442
+ }
443
+ },
444
+ "yauzl": {
445
+ "version": "2.10.0",
446
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
447
+ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
448
+ "dev": true,
449
+ "requires": {
450
+ "buffer-crc32": "~0.2.3",
451
+ "fd-slicer": "~1.1.0"
452
+ }
453
+ }
454
+ }
455
+ }