written 0.0.5 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/LICENSE +8 -0
- data/README.md +63 -0
- data/Rakefile +17 -27
- data/lib/written.rb +0 -8
- data/lib/written/app/assets/images/written/placeholder.png +0 -0
- data/lib/written/app/assets/javascripts/written.coffee +2 -0
- data/lib/written/app/assets/javascripts/written/core/content.coffee +53 -35
- data/lib/written/app/assets/javascripts/written/core/cursor.coffee +33 -12
- data/lib/written/app/assets/javascripts/written/core/document.coffee +16 -11
- data/lib/written/app/assets/javascripts/written/core/extensions/string.coffee +9 -0
- data/lib/written/app/assets/javascripts/written/core/extensions/text.coffee +2 -0
- data/lib/written/app/assets/javascripts/written/core/history.coffee +2 -0
- data/lib/written/app/assets/javascripts/written/core/observer.coffee +6 -2
- data/lib/written/app/assets/javascripts/written/core/stringify.coffee +15 -0
- data/lib/written/app/assets/javascripts/written/parsers/block.coffee +69 -0
- data/lib/written/app/assets/javascripts/written/parsers/block/code.coffee +79 -15
- data/lib/written/app/assets/javascripts/written/parsers/block/heading.coffee +60 -5
- data/lib/written/app/assets/javascripts/written/parsers/block/image.coffee +103 -9
- data/lib/written/app/assets/javascripts/written/parsers/block/olist.coffee +94 -12
- data/lib/written/app/assets/javascripts/written/parsers/block/paragraph.coffee +63 -5
- data/lib/written/app/assets/javascripts/written/parsers/block/quote.coffee +92 -0
- data/lib/written/app/assets/javascripts/written/parsers/block/ulist.coffee +93 -12
- data/lib/written/app/assets/javascripts/written/parsers/inline.coffee +81 -0
- data/lib/written/app/assets/javascripts/written/parsers/inline/code.coffee +57 -0
- data/lib/written/app/assets/javascripts/written/parsers/inline/italic.coffee +40 -7
- data/lib/written/app/assets/javascripts/written/parsers/inline/link.coffee +43 -13
- data/lib/written/app/assets/javascripts/written/parsers/inline/list.coffee +27 -0
- data/lib/written/app/assets/javascripts/written/parsers/inline/strong.coffee +41 -7
- data/lib/written/app/assets/javascripts/written/parsers/parsers.coffee +21 -107
- data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/CustomElements.js +32 -0
- data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/base.js +40 -0
- data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/boot.js +124 -0
- data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/observe.js +318 -0
- data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/register.js +369 -0
- data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/traverse.js +86 -0
- data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/upgrade.js +130 -0
- data/lib/written/app/assets/javascripts/written/polyfills/MutationObserver/MutationObserver.js +575 -0
- data/lib/written/app/assets/javascripts/written/polyfills/WeakMap/WeakMap.js +49 -0
- data/lib/written/app/assets/javascripts/written/polyfills/base.coffee +10 -0
- data/lib/written/app/assets/javascripts/written/polyfills/dom.js +104 -0
- data/lib/written/app/assets/javascripts/written/uploaders/aws.coffee +125 -0
- data/lib/written/app/assets/stylesheets/written.scss +80 -11
- data/lib/written/version.rb +1 -1
- data/test/server/app/assets/javascripts/application.coffee +20 -2
- data/test/server/app/assets/stylesheets/application.scss +2 -2
- data/test/server/app/assets/stylesheets/prism.css +0 -1
- data/test/server/app/views/posts/show.html.erb +10 -3
- metadata +26 -20
- data/lib/written/app/assets/javascripts/written/core/ext.coffee +0 -109
- data/lib/written/app/assets/javascripts/written/core/extensions.coffee +0 -2
- data/lib/written/document.rb +0 -42
- data/lib/written/node.rb +0 -21
- data/lib/written/nodes/code.rb +0 -65
- data/lib/written/nodes/heading.rb +0 -15
- data/lib/written/nodes/image.rb +0 -14
- data/lib/written/nodes/ordered_list.rb +0 -18
- data/lib/written/nodes/unordered_list.rb +0 -19
- data/lib/written/parsers.rb +0 -11
- data/lib/written/parsers/base.rb +0 -26
- data/lib/written/parsers/code.rb +0 -60
- data/lib/written/parsers/heading.rb +0 -19
- data/lib/written/parsers/image.rb +0 -19
- data/lib/written/parsers/link.rb +0 -12
- data/lib/written/parsers/list.rb +0 -33
- data/lib/written/parsers/word.rb +0 -16
@@ -23,7 +23,11 @@ class Written.Observer
|
|
23
23
|
|
24
24
|
@pause(callback)
|
25
25
|
|
26
|
+
resume: =>
|
27
|
+
@mutations.observe @element(), @settings()
|
28
|
+
|
26
29
|
pause: (callback) =>
|
27
30
|
@mutations.disconnect()
|
28
|
-
callback
|
29
|
-
|
31
|
+
if callback?
|
32
|
+
callback()
|
33
|
+
@resume()
|
@@ -0,0 +1,15 @@
|
|
1
|
+
ElementString = (node) ->
|
2
|
+
node.textContent
|
3
|
+
|
4
|
+
CustomElementString = (node) ->
|
5
|
+
node.toString()
|
6
|
+
|
7
|
+
TextNodeString = (node) ->
|
8
|
+
node.textContent
|
9
|
+
|
10
|
+
Written.Stringify = (node) ->
|
11
|
+
switch
|
12
|
+
when node.nodeType == Node.TEXT_NODE then TextNodeString(node)
|
13
|
+
when node.hasAttribute('is') then CustomElementString(node)
|
14
|
+
else ElementString(node)
|
15
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class @Written.Parsers.Block
|
2
|
+
constructor: ->
|
3
|
+
@parsers = []
|
4
|
+
|
5
|
+
freeze: ->
|
6
|
+
if Written.Parsers.Block.parsers.default?
|
7
|
+
@parsers.push Written.Parsers.Block.parsers.default
|
8
|
+
|
9
|
+
Object.freeze(this)
|
10
|
+
Object.freeze(@parsers)
|
11
|
+
|
12
|
+
use: (names) ->
|
13
|
+
if typeof names == 'string' && names == 'all'
|
14
|
+
@parsers = Written.Parsers.Block.parsers.available.slice()
|
15
|
+
return this
|
16
|
+
|
17
|
+
if typeof names == 'string'
|
18
|
+
names = names.split(',').map (name) ->
|
19
|
+
name.trim()
|
20
|
+
|
21
|
+
parser = Written.Parsers.Block.parsers.available.find (obj) ->
|
22
|
+
names.contains(obj.parser.name)
|
23
|
+
|
24
|
+
if !parser?
|
25
|
+
throw "Couldn't find parser #{names}."
|
26
|
+
return this
|
27
|
+
|
28
|
+
@parsers.push(parser)
|
29
|
+
return this
|
30
|
+
|
31
|
+
parse: (lines) =>
|
32
|
+
blocks = []
|
33
|
+
while (line = lines.pop()) != undefined
|
34
|
+
str = line.toString()
|
35
|
+
block = blocks[blocks.length - 1]
|
36
|
+
|
37
|
+
if block? && block.multiline && block.accepts(line)
|
38
|
+
block.append(line)
|
39
|
+
continue
|
40
|
+
|
41
|
+
blocks.push(@find(str))
|
42
|
+
|
43
|
+
blocks
|
44
|
+
|
45
|
+
find: (str) ->
|
46
|
+
parser = undefined
|
47
|
+
for p in @parsers
|
48
|
+
if match = p.rule.exec(str)
|
49
|
+
parser = new p(match)
|
50
|
+
break
|
51
|
+
|
52
|
+
return parser
|
53
|
+
|
54
|
+
|
55
|
+
@Written.Parsers.Block.parsers = {
|
56
|
+
available: []
|
57
|
+
default: undefined
|
58
|
+
}
|
59
|
+
|
60
|
+
@Written.Parsers.Block.get = (name) ->
|
61
|
+
Written.Parsers.Block.parsers.available.find (p) ->
|
62
|
+
p.name.localeCompare(name) == 0
|
63
|
+
|
64
|
+
@Written.Parsers.Block.register = (parser, defaultParser = false) ->
|
65
|
+
if defaultParser
|
66
|
+
Written.Parsers.Block.parsers.default = parser
|
67
|
+
else
|
68
|
+
Written.Parsers.Block.parsers.available.push parser
|
69
|
+
|
@@ -1,26 +1,90 @@
|
|
1
1
|
class Code
|
2
|
+
multiline: true
|
3
|
+
|
2
4
|
constructor: (match) ->
|
3
|
-
@
|
4
|
-
@
|
5
|
+
@matches = [match]
|
6
|
+
@content = "\n"
|
7
|
+
@opened = true
|
8
|
+
|
9
|
+
|
10
|
+
accepts: (text) ->
|
11
|
+
@opened
|
12
|
+
|
13
|
+
append: (text) ->
|
14
|
+
match = /(~{3})$/i.exec(text)
|
15
|
+
if match?
|
16
|
+
@matches.push(match)
|
17
|
+
@opened = false
|
18
|
+
else
|
19
|
+
@content += text + "\n"
|
20
|
+
|
21
|
+
@content
|
22
|
+
|
23
|
+
processContent: (callback) =>
|
24
|
+
|
25
|
+
identical: (current, rendered) ->
|
26
|
+
current.outerHTML == rendered.outerHTML
|
27
|
+
|
28
|
+
markdown: =>
|
29
|
+
node = "<pre is='written-pre'><code></code></pre>".toHTML()
|
30
|
+
code = node.querySelector('code')
|
31
|
+
|
32
|
+
if @matches[0][3]?
|
33
|
+
code.classList.add("language-#{@matches[0][3]}")
|
34
|
+
|
35
|
+
code.appendChild(document.createTextNode(@content))
|
36
|
+
if @highlight?
|
37
|
+
@highlight(code)
|
38
|
+
|
39
|
+
code.insertAdjacentHTML('afterbegin', @matches[0][0])
|
40
|
+
if !@opened
|
41
|
+
code.insertAdjacentHTML('beforeend', @matches[1][0])
|
42
|
+
|
43
|
+
node
|
44
|
+
|
45
|
+
html: =>
|
46
|
+
node = "<pre><code></code></pre>".toHTML()
|
47
|
+
code = node.querySelector('code')
|
48
|
+
|
49
|
+
if @matches[0][3]?
|
50
|
+
code.classList.add("language-#{@matches[0][3]}")
|
51
|
+
|
52
|
+
if @matches[0][4]?
|
53
|
+
code.insertAdjacentHTML('beforebegin', "<header>#{@matches[0][4]}</header>")
|
54
|
+
|
55
|
+
code.appendChild(document.createTextNode(@content))
|
5
56
|
|
57
|
+
node
|
6
58
|
|
7
|
-
|
8
|
-
true
|
59
|
+
Code.rule = /^((~{3})([a-z]+)?)(?:\s(.*))?/i
|
9
60
|
|
10
|
-
|
11
|
-
if @match[3]?
|
12
|
-
@node.querySelector('code').classList.add("language-#{@match[3]}")
|
61
|
+
Written.Parsers.Block.register Code
|
13
62
|
|
14
|
-
|
15
|
-
code.appendChild(document.createTextNode(text + "\n"))
|
63
|
+
prototype = Object.create(HTMLPreElement.prototype)
|
16
64
|
|
17
|
-
|
18
|
-
|
65
|
+
prototype.getRange = (offset, walker) ->
|
66
|
+
range = document.createRange()
|
19
67
|
|
20
|
-
|
21
|
-
|
68
|
+
if !@firstChild?
|
69
|
+
range.setStart(this, 0)
|
70
|
+
else
|
71
|
+
while walker.nextNode()
|
72
|
+
if walker.currentNode.length < offset
|
73
|
+
offset -= walker.currentNode.length
|
74
|
+
continue
|
22
75
|
|
23
|
-
|
76
|
+
range.setStart(walker.currentNode, offset)
|
77
|
+
break
|
24
78
|
|
79
|
+
range.collapse(true)
|
80
|
+
range
|
81
|
+
prototype.toString = ->
|
82
|
+
if @textContent[@textContent.length - 1] == '\n'
|
83
|
+
@textContent.substr(0, @textContent.length - 1)
|
84
|
+
else
|
85
|
+
@textContent
|
25
86
|
|
26
|
-
|
87
|
+
document.registerElement('written-pre', {
|
88
|
+
prototype: prototype
|
89
|
+
extends: 'pre'
|
90
|
+
})
|
@@ -1,10 +1,65 @@
|
|
1
1
|
class Header
|
2
|
+
multiline: false
|
3
|
+
|
2
4
|
constructor: (match) ->
|
3
5
|
@match = match
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
processContent: (callback) =>
|
8
|
+
if @content?
|
9
|
+
throw "Content Error: The content was already processed"
|
10
|
+
return
|
11
|
+
|
12
|
+
@content = callback(@match[3])
|
13
|
+
|
14
|
+
identical: (current, rendered) ->
|
15
|
+
current.outerHTML == rendered.outerHTML
|
16
|
+
|
17
|
+
markdown: =>
|
18
|
+
node = "<h#{@match[2].length} is='written-h#{@match[2].length}'>".toHTML()
|
19
|
+
for text in @content
|
20
|
+
if text.markdown?
|
21
|
+
node.appendChild(text.markdown())
|
22
|
+
else
|
23
|
+
node.appendChild(document.createTextNode(text))
|
24
|
+
|
25
|
+
node.insertAdjacentHTML('afterbegin', @match[1])
|
26
|
+
node
|
27
|
+
|
28
|
+
html: =>
|
29
|
+
node = "<h#{@match[2].length}>".toHTML()
|
30
|
+
for text in @content
|
31
|
+
if text.html?
|
32
|
+
node.appendChild(text.html())
|
33
|
+
else
|
34
|
+
node.appendChild(document.createTextNode(text))
|
35
|
+
node
|
36
|
+
|
37
|
+
Header.rule = /^((#{1,6})\s)(.*)$/i
|
38
|
+
|
39
|
+
Written.Parsers.Block.register Header
|
40
|
+
|
41
|
+
[1,2,3,4,5,6].forEach (size) ->
|
42
|
+
prototype = Object.create(HTMLHeadingElement.prototype)
|
43
|
+
prototype.getRange = (offset, walker) ->
|
44
|
+
range = document.createRange()
|
45
|
+
|
46
|
+
if !@firstChild?
|
47
|
+
range.setStart(this, 0)
|
48
|
+
else
|
49
|
+
while walker.nextNode()
|
50
|
+
if walker.currentNode.length < offset
|
51
|
+
offset -= walker.currentNode.length
|
52
|
+
continue
|
53
|
+
|
54
|
+
range.setStart(walker.currentNode, offset)
|
55
|
+
break
|
56
|
+
|
57
|
+
range.collapse(true)
|
58
|
+
range
|
59
|
+
prototype.toString = ->
|
60
|
+
@textContent
|
9
61
|
|
10
|
-
|
62
|
+
document.registerElement("written-h#{size}", {
|
63
|
+
prototype: prototype
|
64
|
+
extends: "h#{size}"
|
65
|
+
})
|
@@ -1,18 +1,112 @@
|
|
1
1
|
class Image
|
2
|
+
multiline: false
|
3
|
+
|
2
4
|
constructor: (match) ->
|
3
5
|
@match = match
|
4
|
-
@figure = "<figure><div contenteditable='false'><img/></div><figcaption /></figure>".toHTML()
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
processContent: (callback) =>
|
8
|
+
if @content?
|
9
|
+
throw "Content Error: The content was already processed"
|
10
|
+
return
|
11
|
+
|
12
|
+
@content = callback(@match[2])
|
13
|
+
|
14
|
+
identical: (current, rendered) ->
|
15
|
+
|
16
|
+
sameNode = (current, rendered) ->
|
17
|
+
current.nodeName == rendered.nodeName
|
18
|
+
|
19
|
+
sameImages = (current, rendered) ->
|
20
|
+
(current? && current.dataset.image) == (rendered? && rendered.dataset.image)
|
21
|
+
|
22
|
+
sameTexts = (current, rendered) ->
|
23
|
+
(current? && current.innerHTML) == (rendered? && rendered.innerHTML)
|
24
|
+
|
25
|
+
|
26
|
+
sameNode(current, rendered) &&
|
27
|
+
sameImages(current.querySelector('img'), rendered.querySelector('img')) &&
|
28
|
+
sameTexts(current.querySelector('figcaption'), rendered.querySelector('figcaption'))
|
29
|
+
|
30
|
+
|
31
|
+
markdown: =>
|
32
|
+
figure = "<figure is='written-figure'><div contenteditable='false'><div class='progress'></div><input type='file' /><img/></div><figcaption /></figure>".toHTML()
|
33
|
+
caption = figure.querySelector('figcaption')
|
34
|
+
container = figure.querySelector('div')
|
35
|
+
|
36
|
+
for text in @content
|
37
|
+
if text.markdown?
|
38
|
+
caption.appendChild(text.markdown())
|
39
|
+
else
|
40
|
+
caption.appendChild(document.createTextNode(text))
|
41
|
+
|
42
|
+
caption.insertAdjacentHTML('afterbegin', '![')
|
43
|
+
caption.insertAdjacentHTML('beforeend', ']')
|
44
|
+
caption.insertAdjacentHTML('beforeend', @match[3])
|
45
|
+
|
46
|
+
img = figure.querySelector('img')
|
10
47
|
if @match[4]?
|
11
|
-
|
48
|
+
img.src = img.dataset.image = @match[4]
|
49
|
+
img.onerror = @placeholder.bind(this, img, true)
|
50
|
+
else
|
51
|
+
img.src = '/assets/written/placeholder.png'
|
52
|
+
|
53
|
+
if @configure?
|
54
|
+
@configure(figure)
|
55
|
+
|
56
|
+
figure
|
57
|
+
|
58
|
+
html: ->
|
59
|
+
figure = "<figure><div><img/></div><figcaption /></figure>".toHTML()
|
60
|
+
img = figure.querySelector('img')
|
61
|
+
caption = figure.querySelector('figcaption')
|
12
62
|
|
13
|
-
img = @figure.querySelector('img')
|
14
63
|
img.src = @match[4]
|
15
64
|
|
16
|
-
@
|
65
|
+
for text in @content
|
66
|
+
if text.html?
|
67
|
+
caption.appendChild(text.html())
|
68
|
+
else
|
69
|
+
caption.appendChild(document.createTextNode(text))
|
70
|
+
|
71
|
+
figure
|
72
|
+
|
73
|
+
placeholder: (img, event, onerror = false) =>
|
74
|
+
img.src = '/assets/written/placeholder.png'
|
75
|
+
img.onerror = undefined
|
76
|
+
if onerror
|
77
|
+
img.classList.add 'error'
|
78
|
+
|
79
|
+
Image.rule = /^(!{1}\[([^\]]*)\])(\(([^\s]*)?\))$/i
|
80
|
+
|
81
|
+
Image.uploader = (uploader) ->
|
82
|
+
Image::configure = uploader.initialize
|
83
|
+
|
84
|
+
Written.Parsers.Block.register Image
|
85
|
+
|
86
|
+
prototype = Object.create(HTMLElement.prototype)
|
87
|
+
|
88
|
+
prototype.getRange = (offset, walker) ->
|
89
|
+
range = document.createRange()
|
90
|
+
|
91
|
+
if !@firstChild?
|
92
|
+
range.setStart(this, 0)
|
93
|
+
else
|
94
|
+
while walker.nextNode()
|
95
|
+
if walker.currentNode.length < offset
|
96
|
+
offset -= walker.currentNode.length
|
97
|
+
continue
|
98
|
+
|
99
|
+
range.setStart(walker.currentNode, offset)
|
100
|
+
break
|
101
|
+
|
102
|
+
range.collapse(true)
|
103
|
+
range
|
104
|
+
|
105
|
+
prototype.toString = ->
|
106
|
+
(@querySelector('figcaption') || this).textContent
|
107
|
+
|
108
|
+
document.registerElement('written-figure', {
|
109
|
+
prototype: prototype
|
110
|
+
extends: 'figure'
|
111
|
+
})
|
17
112
|
|
18
|
-
Written.Parsers.Block.register Image, /^(!{1}\[([^\]]+)\])(\(([^\s]+)?\))$/i
|
@@ -1,18 +1,100 @@
|
|
1
1
|
class OList
|
2
|
-
|
2
|
+
multiline: true
|
3
|
+
|
3
4
|
constructor: (match) ->
|
4
|
-
@
|
5
|
-
@
|
5
|
+
@matches = [match]
|
6
|
+
@opened = true
|
7
|
+
|
8
|
+
accepts: (text) ->
|
9
|
+
@opened = OList.rule.test(text)
|
10
|
+
|
11
|
+
@opened
|
12
|
+
|
13
|
+
append: (text) ->
|
14
|
+
@matches.push(OList.rule.exec(text))
|
15
|
+
|
16
|
+
processContent: (callback) =>
|
17
|
+
if @content?
|
18
|
+
throw "Content Error: The content was already processed"
|
19
|
+
return
|
20
|
+
|
21
|
+
lines = @matches.map (match) ->
|
22
|
+
match[2]
|
23
|
+
|
24
|
+
@content = callback(lines)
|
25
|
+
|
26
|
+
identical: (current, rendered) ->
|
27
|
+
current.outerHTML == rendered.outerHTML
|
28
|
+
|
29
|
+
markdown: =>
|
30
|
+
node = "<ol is='written-ol'></ol>".toHTML()
|
31
|
+
for line, index in @content
|
32
|
+
li = "<li is='written-li'>".toHTML()
|
33
|
+
li.appendChild(document.createTextNode(@matches[index][1]))
|
34
|
+
|
35
|
+
for text in line
|
36
|
+
if text.markdown?
|
37
|
+
li.appendChild(text.markdown())
|
38
|
+
else
|
39
|
+
li.appendChild(document.createTextNode(text.toString()))
|
40
|
+
|
41
|
+
node.appendChild(li)
|
42
|
+
|
43
|
+
node
|
44
|
+
|
45
|
+
html: =>
|
46
|
+
node = "<ol></ol>".toHTML()
|
47
|
+
for line, index in @content
|
48
|
+
li = "<li>".toHTML()
|
49
|
+
|
50
|
+
for text in line
|
51
|
+
if text.html?
|
52
|
+
li.appendChild(text.html())
|
53
|
+
else
|
54
|
+
li.appendChild(document.createTextNode(text.toString()))
|
55
|
+
|
56
|
+
node.appendChild(li)
|
57
|
+
|
58
|
+
node
|
59
|
+
|
60
|
+
|
61
|
+
OList.rule = /^(\d+\.\s)(.*)/i
|
62
|
+
|
63
|
+
Written.Parsers.Block.register OList
|
64
|
+
|
65
|
+
prototype = Object.create(HTMLOListElement.prototype)
|
66
|
+
|
67
|
+
prototype.toString = ->
|
68
|
+
texts = Array.prototype.slice.call(@children).map (li) ->
|
69
|
+
li.toString()
|
70
|
+
texts.join("\n")
|
71
|
+
|
72
|
+
prototype.getRange = (offset, walker) ->
|
73
|
+
range = document.createRange()
|
74
|
+
if !@firstChild?
|
75
|
+
range.setStart(this, 0)
|
76
|
+
return
|
77
|
+
|
78
|
+
li = this.firstElementChild
|
6
79
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
80
|
+
while walker.nextNode()
|
81
|
+
if !li.contains(walker.currentNode)
|
82
|
+
newList = walker.currentNode
|
83
|
+
while newList? && !(newList instanceof HTMLLIElement)
|
84
|
+
newList = newList.parentElement
|
85
|
+
li = newList
|
86
|
+
offset--
|
12
87
|
|
13
|
-
|
14
|
-
|
15
|
-
|
88
|
+
if walker.currentNode.length < offset
|
89
|
+
offset -= walker.currentNode.length
|
90
|
+
continue
|
91
|
+
range.setStart(walker.currentNode, offset)
|
92
|
+
break
|
16
93
|
|
17
|
-
|
94
|
+
range.collapse(true)
|
95
|
+
range
|
18
96
|
|
97
|
+
document.registerElement('written-ol', {
|
98
|
+
prototype: prototype
|
99
|
+
extends: 'ol'
|
100
|
+
})
|