1
1
/*
2
- Create an immortal DOM node. This is a way to render HTML that stays stable
2
+ Create stable unsafe HTML DOM node. This is a way to render HTML that stays stable
3
3
irregardless of it being unmounted/remounted.
4
- This supports virtualization, window splitting, etc., without loss of state.
4
+ This supports virtualization, window splitting, etc., without loss of state...
5
+ unless there are too many of them, then we delete the oldest.
6
+
7
+ Unsafe is in the name since there is NO SANITIZATION. Only use this on trusted
8
+ documents.
5
9
*/
6
10
7
11
import { useCallback , useEffect , useRef } from "react" ;
@@ -16,11 +20,24 @@ interface Props {
16
20
zIndex ?: number ;
17
21
}
18
22
19
- const immortals : { [ globalKey : string ] : any } = { } ;
23
+ import LRU from "lru-cache" ;
24
+
25
+ const CACHE_SIZE = 100 ;
26
+
27
+ const immortals = new LRU < string , any > ( {
28
+ max : CACHE_SIZE ,
29
+ updateAgeOnGet : true ,
30
+ updateAgeOnHas : true ,
31
+ dispose : ( elt ) => {
32
+ elt . empty ( ) ;
33
+ elt . remove ( ) ;
34
+ } ,
35
+ } ) ;
36
+ // const immortals: { [globalKey: string]: any } = {};
20
37
21
38
const Z_INDEX = 1 ;
22
39
23
- const SCROLL_COUNT = 10 ;
40
+ const SCROLL_COUNT = 25 ;
24
41
25
42
// make it really standout:
26
43
// const PADDING = 5;
@@ -35,7 +52,7 @@ const SCROLL_COUNT = 10;
35
52
const PADDING = 0 ;
36
53
const STYLE = { } as const ;
37
54
38
- export default function ImmortalDomNode ( {
55
+ export default function StableUnsafeHtml ( {
39
56
docId,
40
57
html,
41
58
zIndex = Z_INDEX , // todo: support changing?
@@ -117,14 +134,18 @@ export default function ImmortalDomNode({
117
134
} , [ ] ) ;
118
135
119
136
const getElt = ( ) => {
120
- if ( immortals [ globalKey ] == null ) {
121
- const elt = ( immortals [ globalKey ] = $ (
137
+ console . log ( "size" , immortals . size ) ;
138
+ if ( ! immortals . has ( globalKey ) ) {
139
+ console . log ( "cache miss" , globalKey ) ;
140
+ const elt = $ (
122
141
`<div id="${ globalKey } " style="border:0;position:absolute;overflow-y:hidden;z-index:${ zIndex } "/>${ html } </div>` ,
123
- ) ) ;
142
+ ) ;
143
+ immortals . set ( globalKey , elt ) ;
124
144
$ ( "body" ) . append ( elt ) ;
125
145
return elt ;
126
146
} else {
127
- return immortals [ globalKey ] ;
147
+ console . log ( "cache hit" , globalKey ) ;
148
+ return immortals . get ( globalKey ) ;
128
149
}
129
150
} ;
130
151
@@ -161,7 +182,7 @@ export default function ImmortalDomNode({
161
182
// in order to make it so the iframe doesn't appear
162
183
// to just get "dragged along" nearly as much, as
163
184
// onScroll is throttled.
164
- count = Math . min ( SCROLL_COUNT , SCROLL_COUNT + 100 ) ;
185
+ count = SCROLL_COUNT ;
165
186
while ( count > 0 ) {
166
187
position ( ) ;
167
188
await new Promise ( requestAnimationFrame ) ;
0 commit comments