Skip to content

Commit

Permalink
$mol_dom_point, $mol_dom_range, $mol_dom = $mol_dom_context
Browse files Browse the repository at this point in the history
  • Loading branch information
jin committed Dec 29, 2024
1 parent 32ba95f commit 374764d
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 0 deletions.
5 changes: 5 additions & 0 deletions dom/dom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace $ {

export var $mol_dom = $mol_dom_context

}
106 changes: 106 additions & 0 deletions dom/point/point.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
namespace $ {

export class $mol_dom_point extends Object {

constructor(
public node: Node,
public pos: number,
) { super() }

static start( node: Node ) {
return new this( node, 0 )
}

static end( node: Node ) {
const length = node.nodeValue?.length ?? node.childNodes.length
return new this( node, length )
}

to( point: $mol_dom_point ) {
this.node = point.node
this.pos = point.pos
}

to_start() {
this.pos = 0
return this
}

to_end() {
this.pos = this.node.nodeValue?.length ?? this.node.childNodes.length
return this
}

is_start() {
return this.pos <= 0
}

is_end() {
return this.pos >= ( this.node.nodeValue?.length ?? this.node.childNodes.length )
}

char_backward( root: Element ): $mol_dom_point {
return this.backward( ()=> {
if( this.node === root && this.is_start() ) return true
if( this.node.nodeType !== this.node.TEXT_NODE ) return false
if( this.is_start() ) return false
this.pos -= 1
return true
} )
}

char_forward( root: Element ): $mol_dom_point {
return this.forward( ()=> {
if( this.node === root && this.is_end() ) return true
if( this.node.nodeType !== this.node.TEXT_NODE ) return false
if( this.is_end() ) return false
this.pos += 1
return true
} )
}

backward( check: ()=> boolean ): $mol_dom_point {

if( check() ) return this

if( !this.is_start() ) {
const kid = this.node.childNodes[ this.pos - 1 ]
this.node = kid
this.to_end()
return this.backward( check )
}

const parent = this.node.parentElement
if( !parent ) return this

const offset = [ ... parent.childNodes ].indexOf( this.node as ChildNode )
this.node = parent
this.pos = offset
return this.backward( check )

}

forward( check: ()=> boolean ): $mol_dom_point {

if( check() ) return this

if( !this.is_end() ) {
const kid = this.node.childNodes[ this.pos ]
this.node = kid
this.to_start()
return this.forward( check )
}

const parent = this.node.parentElement
if( !parent ) return this

const offset = [ ... parent.childNodes ].indexOf( this.node as ChildNode ) + 1
this.node = parent
this.pos = offset
return this.forward( check )

}

}

}
61 changes: 61 additions & 0 deletions dom/range/range.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
namespace $ {
export class $mol_dom_range extends Object {

constructor(
readonly head: $mol_dom_point,
readonly foot: $mol_dom_point,
) { super() }

static from_selection( sel = $mol_dom_context.getSelection()! ) {
return this.from_native( sel?.getRangeAt(0) )
}

static from_native( range: Range ) {
return new this(
new $mol_dom_point( range.startContainer, range.startOffset ),
new $mol_dom_point( range.endContainer, range.endOffset ),
)
}

static inside( node: Node ) {
return new this(
$mol_dom_point.start( node ),
$mol_dom_point.end( node ),
)
}

static around( node: Node ) {

const parent = node.parentNode!
const pos = [ ... parent.childNodes ].indexOf( node as ChildNode )

return new this(
new $mol_dom_point( parent, pos ),
new $mol_dom_point( parent, pos + 1 ),
)

}

is_empty() {
return this.head.node === this.foot.node && this.head.pos === this.foot.pos
}

clear() {
this.native().deleteContents()
}

select() {
const sel = $mol_dom_context.document.getSelection()!
sel.removeAllRanges()
sel.addRange( this.native() )
}

native() {
const range = $mol_dom_context.document.createRange()
range.setEnd( this.foot.node, this.foot.pos )
range.setStart( this.head.node, this.head.pos )
return range
}

}
}

0 comments on commit 374764d

Please sign in to comment.