deckar01-task_list 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0ede80f64a73125eacfa02592290df623f5fba44
4
+ data.tar.gz: a68b79a9b6aa1f8a616ea4a56b68751f404d4dc0
5
+ SHA512:
6
+ metadata.gz: 5605f90ee454095d54491ca31cd53da4e03910400615474760e7c87acb590a9437a89d8ca6d4e4376a94b506bf30476856962625240ee260abee2d4e36e1ab8e
7
+ data.tar.gz: aa65c07c23206eb84d93b0286eeaf573e7ff6c2d75acd7f5a5735e6c93d3efd7b6c8389dd22a41f3a2be23e5b2a5d6c9bf00b07a19e65c385defde7c1daf3762
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ bin/
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ bower_components
20
+ node_modules
21
+ vendor/gems/
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ sudo: false
3
+ install: ./script/bootstrap
4
+ script: ./script/cibuild
5
+ rvm:
6
+ - 1.9.3
7
+ - 2.0
8
+ - 2.1
9
+ - 2.2
10
+ notifications:
11
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Jared Deckard
4
+ Copyright (c) 2014 GitHub, Inc.
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # Task Lists
2
+
3
+ [![Build Status](http://img.shields.io/travis/deckar01/task_list.svg)][travis]
4
+
5
+ [travis]: https://travis-ci.org/deckar01/task_list
6
+
7
+ This package provides various components necessary for integrating
8
+ [Task Lists](https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments)
9
+ into your Markdown user content.
10
+
11
+ ## Components
12
+
13
+ The Task List feature is made of several different components:
14
+
15
+ * Markdown Ruby Filter
16
+ * Summary Ruby Model: summarizes task list items
17
+ * JavaScript: frontend task list update behavior
18
+ * CSS: styles Markdown task list items
19
+
20
+ ## Usage & Integration
21
+
22
+ The backend components are designed for rendering the Task List item checkboxes, and the frontend components handle updating the Markdown source (embedded in the markup).
23
+
24
+ ### Backend: Markdown pipeline filter
25
+
26
+ Rendering Task List item checkboxes from source Markdown depends on the `TaskList::Filter`, designed to integrate with the [`html-pipeline`](https://github.com/jch/html-pipeline) gem. For example:
27
+
28
+ ``` ruby
29
+ require 'html/pipeline'
30
+ require 'deckar01-task_list/filter'
31
+
32
+ pipeline = HTML::Pipeline.new [
33
+ HTML::Pipeline::MarkdownFilter,
34
+ TaskList::Filter
35
+ ]
36
+
37
+ pipeline.call "- [ ] task list item"
38
+ ```
39
+
40
+ ### Frontend: Markdown Updates
41
+
42
+ Task List updates on the frontend require specific HTML markup structure, and must be enabled with JavaScript.
43
+
44
+ Rendered HTML (the `<ul>` element below) should be contained in a `js-task-list-container` container element and include a sibling `textarea.js-task-list-field` element that is updated when checkboxes are changed.
45
+
46
+ ``` markdown
47
+ - [ ] text
48
+ ```
49
+
50
+ ``` html
51
+ <div class="js-task-list-container">
52
+ <ul class="task-list">
53
+ <li class="task-list-item">
54
+ <input type="checkbox" class="js-task-list-item-checkbox" disabled />
55
+ text
56
+ </li>
57
+ </ul>
58
+ <form>
59
+ <textarea class="js-task-list-field">- [ ] text</textarea>
60
+ </form>
61
+ </div>
62
+ ```
63
+
64
+ Enable Task List updates with:
65
+
66
+ ``` javascript
67
+ $('.js-task-list-container').taskList('enable')
68
+ ```
69
+
70
+ NOTE: Updates are not persisted to the server automatically. Persistence is the responsibility of the integrating application, accomplished by hooking into the `tasklist:change` JavaScript event. For instance, we use AJAX to submit a hidden form on update.
71
+
72
+ Read through the documented behaviors and samples [in the source][frontend_behaviors] for more detail, including documented events.
73
+
74
+ [frontend_behaviors]: https://github.com/deckar01/task_list/blob/master/app/assets/javascripts/task_list.coffee
75
+
76
+ ## Installation
77
+
78
+ Task Lists are packaged as both a RubyGem with both backend and frontend behavior, and a Bower package with just the frontend behavior.
79
+
80
+ ### Backend: RubyGem
81
+
82
+ For the backend Ruby components, add this line to your application's Gemfile:
83
+
84
+ gem 'deckar01-task_list'
85
+
86
+ And then execute:
87
+
88
+ $ bundle
89
+
90
+ ### Frontend: Bower
91
+
92
+ For the frontend components, add `deckar01-task_list` to your Bower dependencies config.
93
+
94
+ This is the preferred method for including the frontend assets in your application. Alternatively, for Rails methods using `Sprockets`, see below.
95
+
96
+ ### Frontend: Rails 3+ Railtie method
97
+
98
+ ``` ruby
99
+ # config/application.rb
100
+ require 'deckar01-task_list/railtie'
101
+ ```
102
+
103
+ ### Frontend: Rails 2.3 Manual method
104
+
105
+ Wherever you have your Sprockets setup:
106
+
107
+ ``` ruby
108
+ Sprockets::Environment.new(Rails.root) do |env|
109
+ # Load TaskList assets
110
+ require 'deckar01-task_list/railtie'
111
+ TaskList.asset_paths.each do |path|
112
+ env.append_path path
113
+ end
114
+ end
115
+ ```
116
+
117
+ If you're not using Sprockets, you're on your own but it's pretty straight
118
+ forward. `deckar01-task_list/railtie` defines `TaskList.asset_paths` which you can use
119
+ to manage building your asset bundles.
120
+
121
+ ### Dependencies
122
+
123
+ At a high level, the Ruby components integrate with the [`html-pipeline`](https://github.com/jch/html-pipeline) library, and the frontend components depend on the jQuery library. The frontend components are written in CoffeeScript and need to be preprocessed for production use.
124
+
125
+ ## Testing and Development
126
+
127
+ JavaScript unit tests can be run with `script/testsuite`.
128
+
129
+ Ruby unit tests can be run with `rake test`.
130
+
131
+ Functional tests are useful for manual testing in the browser. To run, install
132
+ the necessary components with `script/bootstrap` then run the server:
133
+
134
+ ```
135
+ rackup -p 4011
136
+ ```
137
+
138
+ Navigate to http://localhost:4011/test/functional/test_task_lists_behavior.html
139
+
140
+ ## Community Integration
141
+ - [Waffle.io](http://waffle.io)
142
+ - [HuBoard](https://huboard.com/)
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ task :default => :test
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ t.verbose = true
9
+ end
@@ -0,0 +1,237 @@
1
+ # TaskList Behavior
2
+ #
3
+ #= provides tasklist:enabled
4
+ #= provides tasklist:disabled
5
+ #= provides tasklist:change
6
+ #= provides tasklist:changed
7
+ #
8
+ #= require jquery
9
+ #
10
+ # Enables Task List update behavior.
11
+ #
12
+ # ### Example Markup
13
+ #
14
+ # <div class="js-task-list-container">
15
+ # <ul class="task-list">
16
+ # <li class="task-list-item">
17
+ # <input type="checkbox" class="js-task-list-item-checkbox" disabled />
18
+ # text
19
+ # </li>
20
+ # </ul>
21
+ # <form>
22
+ # <textarea class="js-task-list-field">- [ ] text</textarea>
23
+ # </form>
24
+ # </div>
25
+ #
26
+ # ### Specification
27
+ #
28
+ # TaskLists MUST be contained in a `(div).js-task-list-container`.
29
+ #
30
+ # TaskList Items SHOULD be an a list (`UL`/`OL`) element.
31
+ #
32
+ # Task list items MUST match `(input).task-list-item-checkbox` and MUST be
33
+ # `disabled` by default.
34
+ #
35
+ # TaskLists MUST have a `(textarea).js-task-list-field` form element whose
36
+ # `value` attribute is the source (Markdown) to be udpated. The source MUST
37
+ # follow the syntax guidelines.
38
+ #
39
+ # TaskList updates trigger `tasklist:change` events. If the change is
40
+ # successful, `tasklist:changed` is fired. The change can be canceled.
41
+ #
42
+ # jQuery is required.
43
+ #
44
+ # ### Methods
45
+ #
46
+ # `.taskList('enable')` or `.taskList()`
47
+ #
48
+ # Enables TaskList updates for the container.
49
+ #
50
+ # `.taskList('disable')`
51
+ #
52
+ # Disables TaskList updates for the container.
53
+ #
54
+ ## ### Events
55
+ #
56
+ # `tasklist:enabled`
57
+ #
58
+ # Fired when the TaskList is enabled.
59
+ #
60
+ # * **Synchronicity** Sync
61
+ # * **Bubbles** Yes
62
+ # * **Cancelable** No
63
+ # * **Target** `.js-task-list-container`
64
+ #
65
+ # `tasklist:disabled`
66
+ #
67
+ # Fired when the TaskList is disabled.
68
+ #
69
+ # * **Synchronicity** Sync
70
+ # * **Bubbles** Yes
71
+ # * **Cancelable** No
72
+ # * **Target** `.js-task-list-container`
73
+ #
74
+ # `tasklist:change`
75
+ #
76
+ # Fired before the TaskList item change takes affect.
77
+ #
78
+ # * **Synchronicity** Sync
79
+ # * **Bubbles** Yes
80
+ # * **Cancelable** Yes
81
+ # * **Target** `.js-task-list-field`
82
+ #
83
+ # `tasklist:changed`
84
+ #
85
+ # Fired once the TaskList item change has taken affect.
86
+ #
87
+ # * **Synchronicity** Sync
88
+ # * **Bubbles** Yes
89
+ # * **Cancelable** No
90
+ # * **Target** `.js-task-list-field`
91
+ #
92
+ # ### NOTE
93
+ #
94
+ # Task list checkboxes are rendered as disabled by default because rendered
95
+ # user content is cached without regard for the viewer.
96
+
97
+ incomplete = "[ ]"
98
+ complete = "[x]"
99
+
100
+ # Escapes the String for regular expression matching.
101
+ escapePattern = (str) ->
102
+ str.
103
+ replace(/([\[\]])/g, "\\$1"). # escape square brackets
104
+ replace(/\s/, "\\s"). # match all white space
105
+ replace("x", "[xX]") # match all cases
106
+
107
+ incompletePattern = ///
108
+ #{escapePattern(incomplete)}
109
+ ///
110
+ completePattern = ///
111
+ #{escapePattern(complete)}
112
+ ///
113
+
114
+ # Pattern used to identify all task list items.
115
+ # Useful when you need iterate over all items.
116
+ itemPattern = ///
117
+ ^
118
+ (?: # prefix, consisting of
119
+ \s* # optional leading whitespace
120
+ (?:>\s*)* # zero or more blockquotes
121
+ (?:[-+*]|(?:\d+\.)) # list item indicator
122
+ )
123
+ \s* # optional whitespace prefix
124
+ ( # checkbox
125
+ #{escapePattern(complete)}|
126
+ #{escapePattern(incomplete)}
127
+ )
128
+ \s+ # is followed by whitespace
129
+ (?!
130
+ \(.*?\) # is not part of a [foo](url) link
131
+ )
132
+ (?= # and is followed by zero or more links
133
+ (?:\[.*?\]\s*(?:\[.*?\]|\(.*?\))\s*)*
134
+ (?:[^\[]|$) # and either a non-link or the end of the string
135
+ )
136
+ ///
137
+
138
+ # Used to filter out code fences from the source for comparison only.
139
+ # http://rubular.com/r/x5EwZVrloI
140
+ # Modified slightly due to issues with JS
141
+ codeFencesPattern = ///
142
+ ^`{3} # ```
143
+ (?:\s*\w+)? # followed by optional language
144
+ [\S\s] # whitespace
145
+ .* # code
146
+ [\S\s] # whitespace
147
+ ^`{3}$ # ```
148
+ ///mg
149
+
150
+ # Used to filter out potential mismatches (items not in lists).
151
+ # http://rubular.com/r/OInl6CiePy
152
+ itemsInParasPattern = ///
153
+ ^
154
+ (
155
+ #{escapePattern(complete)}|
156
+ #{escapePattern(incomplete)}
157
+ )
158
+ .+
159
+ $
160
+ ///g
161
+
162
+ # Given the source text, updates the appropriate task list item to match the
163
+ # given checked value.
164
+ #
165
+ # Returns the updated String text.
166
+ updateTaskListItem = (source, itemIndex, checked) ->
167
+ clean = source.replace(/\r/g, '').replace(codeFencesPattern, '').
168
+ replace(itemsInParasPattern, '').split("\n")
169
+ index = 0
170
+ result = for line in source.split("\n")
171
+ if line in clean && line.match(itemPattern)
172
+ index += 1
173
+ if index == itemIndex
174
+ line =
175
+ if checked
176
+ line.replace(incompletePattern, complete)
177
+ else
178
+ line.replace(completePattern, incomplete)
179
+ line
180
+ result.join("\n")
181
+
182
+ # Updates the $field value to reflect the state of $item.
183
+ # Triggers the `tasklist:change` event before the value has changed, and fires
184
+ # a `tasklist:changed` event once the value has changed.
185
+ updateTaskList = ($item) ->
186
+ $container = $item.closest '.js-task-list-container'
187
+ $field = $container.find '.js-task-list-field'
188
+ index = 1 + $container.find('.task-list-item-checkbox').index($item)
189
+ checked = $item.prop 'checked'
190
+
191
+ event = $.Event 'tasklist:change'
192
+ $field.trigger event, [index, checked]
193
+
194
+ unless event.isDefaultPrevented()
195
+ $field.val updateTaskListItem($field.val(), index, checked)
196
+ $field.trigger 'change'
197
+ $field.trigger 'tasklist:changed', [index, checked]
198
+
199
+ # When the task list item checkbox is updated, submit the change
200
+ $(document).on 'change', '.task-list-item-checkbox', ->
201
+ updateTaskList $(this)
202
+
203
+ # Enables TaskList item changes.
204
+ enableTaskList = ($container) ->
205
+ if $container.find('.js-task-list-field').length > 0
206
+ $container.
207
+ find('.task-list-item').addClass('enabled').
208
+ find('.task-list-item-checkbox').attr('disabled', null)
209
+ $container.addClass('is-task-list-enabled').
210
+ trigger 'tasklist:enabled'
211
+
212
+ # Enables a collection of TaskList containers.
213
+ enableTaskLists = ($containers) ->
214
+ for container in $containers
215
+ enableTaskList $(container)
216
+
217
+ # Disable TaskList item changes.
218
+ disableTaskList = ($container) ->
219
+ $container.
220
+ find('.task-list-item').removeClass('enabled').
221
+ find('.task-list-item-checkbox').attr('disabled', 'disabled')
222
+ $container.removeClass('is-task-list-enabled').
223
+ trigger 'tasklist:disabled'
224
+
225
+ # Disables a collection of TaskList containers.
226
+ disableTaskLists = ($containers) ->
227
+ for container in $containers
228
+ disableTaskList $(container)
229
+
230
+ $.fn.taskList = (method) ->
231
+ $container = $(this).closest('.js-task-list-container')
232
+
233
+ methods =
234
+ enable: enableTaskLists
235
+ disable: disableTaskLists
236
+
237
+ methods[method || 'enable']($container)