mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
...
This commit is contained in:
parent
c14fd982e4
commit
a0e85d7c4a
@ -5,10 +5,35 @@
|
|||||||
Copyright 2011, Kovid Goyal <kovid@kovidgoyal.net>
|
Copyright 2011, Kovid Goyal <kovid@kovidgoyal.net>
|
||||||
Released under the GPLv3 License
|
Released under the GPLv3 License
|
||||||
###
|
###
|
||||||
|
#
|
||||||
log = (error) ->
|
log = (error) ->
|
||||||
if error and window?.console?.log
|
if error
|
||||||
|
if window?.console?.log
|
||||||
window.console.log(error)
|
window.console.log(error)
|
||||||
|
else if process?.stdout?.write
|
||||||
|
process.stdout.write(error + '\n')
|
||||||
|
|
||||||
|
# CFI escaping {{{
|
||||||
|
escape_for_cfi = (raw) ->
|
||||||
|
if raw
|
||||||
|
for c in ['^', '[', ']', ',', '(', ')', ';', '~', '@', '-', '!']
|
||||||
|
raw = raw.replace(c, '^'+c)
|
||||||
|
raw
|
||||||
|
|
||||||
|
unescape_from_cfi = (raw) ->
|
||||||
|
ans = raw
|
||||||
|
if raw
|
||||||
|
dropped = false
|
||||||
|
ans = []
|
||||||
|
for c in raw
|
||||||
|
if not dropped and c == '^'
|
||||||
|
dropped = true
|
||||||
|
continue
|
||||||
|
dropped = false
|
||||||
|
ans.push(c)
|
||||||
|
ans = ans.join('')
|
||||||
|
ans
|
||||||
|
# }}}
|
||||||
|
|
||||||
fstr = (d) -> # {{{
|
fstr = (d) -> # {{{
|
||||||
# Convert a timestamp floating point number to a string
|
# Convert a timestamp floating point number to a string
|
||||||
@ -76,14 +101,70 @@ class CanonicalFragmentIdentifier
|
|||||||
|
|
||||||
# Add id assertions for robustness where possible
|
# Add id assertions for robustness where possible
|
||||||
id = node.getAttribute?('id')
|
id = node.getAttribute?('id')
|
||||||
idspec = if id then "[#{ id }]" else ''
|
idspec = if id then "[#{ escape_for_cfi(id) }]" else ''
|
||||||
cfi = '/' + index + idspec + cfi
|
cfi = '/' + index + idspec + cfi
|
||||||
node = p
|
node = p
|
||||||
|
|
||||||
cfi
|
cfi
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
at: (x, y, doc=window.document) -> # {{{
|
decode: (cfi, doc=window?.document) -> # {{{
|
||||||
|
simple_node_regex = ///
|
||||||
|
^/(\d+) # The node count
|
||||||
|
(\[[^\]]*\])? # The optional id assertion
|
||||||
|
///
|
||||||
|
error = null
|
||||||
|
node = doc
|
||||||
|
|
||||||
|
until cfi.length <= 0 or error
|
||||||
|
if ( (r = cfi.match(simple_node_regex)) is not null ) # Path step
|
||||||
|
target = parseInt(r[1])
|
||||||
|
assertion = r[2]
|
||||||
|
if assertion
|
||||||
|
assertion = unescape_from_cfi(assertion.slice(1, assertion.length-1))
|
||||||
|
index = 0
|
||||||
|
child = node.firstChild
|
||||||
|
|
||||||
|
while true
|
||||||
|
if not child
|
||||||
|
if assertion # Try to use the assertion to find the node
|
||||||
|
child = doc.getElementById(assertion)
|
||||||
|
if child
|
||||||
|
node = child
|
||||||
|
if not child
|
||||||
|
error = "No matching child found for CFI: " + cfi
|
||||||
|
break
|
||||||
|
index |= 1 # Increment index by 1 if it is even
|
||||||
|
if child.nodeType in [1, 7] # We have an element or a PI
|
||||||
|
index++
|
||||||
|
if ( index == target )
|
||||||
|
cfi = cfi.substr(r[0].length)
|
||||||
|
node = child
|
||||||
|
break
|
||||||
|
child = child.nextSibling
|
||||||
|
|
||||||
|
else if cfi[0] == '!' # Indirection
|
||||||
|
if node.contentDocument
|
||||||
|
node = node.contentDocument
|
||||||
|
cfi = cfi.substr(1)
|
||||||
|
else
|
||||||
|
error = "Cannot reference #{ node.nodeName }'s content:" + cfi
|
||||||
|
|
||||||
|
else
|
||||||
|
break
|
||||||
|
|
||||||
|
if error
|
||||||
|
log(error)
|
||||||
|
return null
|
||||||
|
|
||||||
|
point = {}
|
||||||
|
error = null
|
||||||
|
|
||||||
|
point
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
at: (x, y, doc=window?.document) -> # {{{
|
||||||
cdoc = doc
|
cdoc = doc
|
||||||
target = null
|
target = null
|
||||||
cwin = cdoc.defaultView
|
cwin = cdoc.defaultView
|
||||||
@ -116,11 +197,11 @@ class CanonicalFragmentIdentifier
|
|||||||
if name in ['audio', 'video']
|
if name in ['audio', 'video']
|
||||||
tail = "~" + fstr target.currentTime
|
tail = "~" + fstr target.currentTime
|
||||||
|
|
||||||
else if name in ['img']
|
if name in ['img', 'video']
|
||||||
px = ((x + cwin.scrollX - target.offsetLeft)*100)/target.offsetWidth
|
px = ((x + cwin.scrollX - target.offsetLeft)*100)/target.offsetWidth
|
||||||
py = ((y + cwin.scrollY - target.offsetTop)*100)/target.offsetHeight
|
py = ((y + cwin.scrollY - target.offsetTop)*100)/target.offsetHeight
|
||||||
tail = "#{ tail }@#{ fstr px },#{ fstr py }"
|
tail = "#{ tail }@#{ fstr px },#{ fstr py }"
|
||||||
else
|
else if name != 'audio'
|
||||||
if cdoc.caretRangeFromPoint # WebKit
|
if cdoc.caretRangeFromPoint # WebKit
|
||||||
range = cdoc.caretRangeFromPoint(x, y)
|
range = cdoc.caretRangeFromPoint(x, y)
|
||||||
if range
|
if range
|
||||||
@ -133,4 +214,12 @@ class CanonicalFragmentIdentifier
|
|||||||
this.encode(doc, target, offset, tail)
|
this.encode(doc, target, offset, tail)
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
if window?
|
||||||
window.cfi = new CanonicalFragmentIdentifier()
|
window.cfi = new CanonicalFragmentIdentifier()
|
||||||
|
else if process?
|
||||||
|
# Some debugging code goes here to be run with the coffee interpreter
|
||||||
|
cfi = new CanonicalFragmentIdentifier()
|
||||||
|
t = 'a^!,1'
|
||||||
|
log(t)
|
||||||
|
log(escape_for_cfi(t))
|
||||||
|
log(unescape_from_cfi(escape_for_cfi(t)))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user