@@ -7,10 +7,12 @@ import { Comp, CompT } from "../base/Comp";
7
7
import ReactMarkdownComp from "../core/ReactMarkdownComp" ;
8
8
import { NodeInfo } from "../../JavaIntf" ;
9
9
import { UrlInfo } from "../../plugins/base/TypeBase" ;
10
+ import QuickLRU from 'quick-lru' ;
11
+
12
+ const cache = new QuickLRU ( { maxSize : 1000 } ) ;
10
13
11
14
interface LS {
12
15
content : string ;
13
- pendingDecrypt ?: string ;
14
16
}
15
17
16
18
export class NodeCompMarkdown extends Comp {
@@ -28,48 +30,26 @@ export class NodeCompMarkdown extends Comp {
28
30
// but is ok named as 'cont'
29
31
cont : string ;
30
32
31
- /* This makes the encrypted text visible without editing the node which is important to have
32
- on so nodes shared to you can be seen, because a user can't edit nodes they don't own */
33
- private autoDecrypting : boolean = true ;
34
-
35
- constructor ( public node : NodeInfo , extraContainerClass : string , _tabData : TabBase < any > , urls : Map < string , UrlInfo > ) {
33
+ constructor ( public node : NodeInfo , extraContainerClass : string , _tabData : TabBase < any > , private urls : Map < string , UrlInfo > ) {
36
34
super ( { key : "ncmkd_" + node . id } ) ;
37
35
this . cont = node . renderContent || node . content ;
38
- const ast = getAs ( ) ;
39
36
this . attribs . nodeId = node . id ; // this 'nodeId' is needed to track expand collapse of code blocks.
40
37
this . attribs . className = "mkCont" ;
41
38
42
39
if ( extraContainerClass ) {
43
40
this . attribs . className += " " + extraContainerClass ;
44
41
}
45
42
46
- const content = this . cont || "" ;
47
- const state : LS = {
48
- content : null
49
- } ;
50
-
51
- /* If this content is encrypted we set it in 'pendingDecrypt' to decrypt it asynchronously */
52
- if ( S . props . isEncrypted ( node ) ) {
53
- state . content = "[Encrypted]" ;
54
-
55
- if ( ! ast . isAnonUser ) {
56
- state . pendingDecrypt = content ;
57
- }
58
- }
59
- /* otherwise it's not encrypted and we display the normal way */
60
- else {
61
- state . content = this . preprocessMarkdown ( node , null , urls ) ;
62
- }
63
-
64
- this . mergeState < LS > ( state ) ;
43
+ this . mergeState < LS > ( {
44
+ content : this . cont || ""
45
+ } ) ;
65
46
}
66
47
67
48
/* If content is passed in it will be used. It will only be passed in when the node is encrypted and the text
68
49
has been decrypted and needs to be rendered, in which case we don't need the node.content, but use the 'content' parameter here */
69
- preprocessMarkdown ( node : NodeInfo , content : string = null , urls : Map < string , UrlInfo > ) : string {
70
- content = content || this . cont || "" ;
71
- let val = "" ;
72
- val = S . render . injectSubstitutions ( node , content ) ;
50
+ preprocessMarkdown ( node : NodeInfo , urls : Map < string , UrlInfo > ) : string {
51
+ const content = this . cont || "" ;
52
+ let val = S . render . injectSubstitutions ( node , content ) ;
73
53
74
54
if ( S . props . isMine ( node ) ) {
75
55
val = S . util . makeHtmlCommentsVisible ( val ) ;
@@ -103,52 +83,30 @@ export class NodeCompMarkdown extends Comp {
103
83
. replaceAll ( "\\]" , "$$" ) ;
104
84
}
105
85
106
- override preRender ( ) : boolean | null {
107
- const state : LS = this . getState < LS > ( ) ;
108
-
109
- if ( this . autoDecrypting && state . pendingDecrypt ) {
110
- let cipherText = null ;
111
- if ( state . pendingDecrypt . startsWith ( J . Constant . ENC_TAG ) ) {
112
- cipherText = state . pendingDecrypt . substring ( J . Constant . ENC_TAG . length ) ;
113
- }
114
-
115
- if ( ! cipherText ) {
116
- console . log ( "not decrypting. cipherText was unexpected format: " + cipherText ) ;
117
- return ;
118
- }
119
-
120
- const cipherHash = S . util . hashOfString ( cipherText ) ;
121
- let clearText = S . quanta . decryptCache . get ( cipherHash ) ;
122
- // if we have already decrypted this data use the result.
123
- if ( clearText ) {
124
- clearText = this . preprocessMarkdown ( this . node , clearText , null ) ;
125
-
126
- this . mergeState < LS > ( {
127
- content : clearText ,
128
- pendingDecrypt : null
129
- } ) ;
130
- }
131
- else {
132
- setTimeout ( ( ) => {
133
- this . decrypt ( ) ;
134
- } , 10 ) ;
135
- }
136
- }
137
- return true ;
138
- }
139
-
140
86
override compRender ( _children : CompT [ ] ) : ReactNode {
141
87
const state = this . getState < LS > ( ) ;
142
88
143
89
// ReactMarkdown can't have this 'ref' and would throw a warning if we did
144
90
delete this . attribs . ref ;
145
91
92
+ if ( state . content ?. indexOf ( J . Constant . ENC_TAG ) === 0 ) {
93
+ return createElement ( ReactMarkdownComp as any , this . attribs , "[Encrypted]" ) ;
94
+ }
95
+
96
+ const key = this . attribs . key + "_" + state . content ;
97
+ let ret : any = cache . get ( key ) ;
98
+ if ( ret ) {
99
+ return cache . get ( key ) as ReactNode ;
100
+ }
101
+
102
+ const content = this . preprocessMarkdown ( this . node , this . urls ) ;
146
103
// Process with special markdown if there is any.
147
- const sections = this . processSpecialMarkdown ( state . content ) ;
148
- if ( sections ) {
149
- return sections ;
104
+ ret = this . processSpecialMarkdown ( content ) ;
105
+ if ( ! ret ) {
106
+ ret = createElement ( ReactMarkdownComp as any , this . attribs , content ) ;
150
107
}
151
- return createElement ( ReactMarkdownComp as any , this . attribs , state . content ) ;
108
+ cache . set ( key , ret ) ;
109
+ return ret ;
152
110
}
153
111
154
112
/* When any markdown content contains something like "-**My Section Title**-" that will be
@@ -272,31 +230,4 @@ export class NodeCompMarkdown extends Comp {
272
230
children . push ( createElement ( ReactMarkdownComp as any , attribs , curBuf ) ) ;
273
231
}
274
232
}
275
-
276
- async decrypt ( ) {
277
- if ( ! S . crypto . avail ) return ;
278
- const state : LS = this . getState < LS > ( ) ;
279
- if ( ! state . pendingDecrypt ) return ;
280
- let clearText = null ;
281
- // console.log("decrypting (in NodeCompMarkdown): " + state.pendingDecrypt);
282
-
283
- if ( state . pendingDecrypt . startsWith ( J . Constant . ENC_TAG ) ) {
284
- const cipherText = state . pendingDecrypt . substring ( J . Constant . ENC_TAG . length ) ;
285
- const cipherKey = S . props . getCryptoKey ( this . node ) ;
286
- if ( cipherKey ) {
287
- // console.log("CIPHERKEY " + cipherKey);
288
- clearText = await S . crypto . decryptSharableString ( null , { cipherKey, cipherText } ) ;
289
- }
290
- }
291
-
292
- // console.log("Decrypted to " + clearText);
293
- // Warning clearText can be "" (which is a 'falsy' value and a valid decrypted string!)
294
- clearText = clearText !== null ? clearText : "[Decrypt Failed]" ;
295
- clearText = this . preprocessMarkdown ( this . node , clearText , null ) ;
296
-
297
- this . mergeState < LS > ( {
298
- content : clearText ,
299
- pendingDecrypt : null
300
- } ) ;
301
- }
302
233
}
0 commit comments