html-pipeline-task_list 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }