1
+ function add_link_to_headings ( ) {
2
+ $ ( ".from-markdown" )
3
+ . not ( ".revision-content" )
4
+ . find ( "h1, h2, h3, h4, h5, h6" )
5
+ . each ( ( i , $heading ) => {
6
+ const text = $heading . textContent . trim ( ) ;
7
+ $heading . id = text
8
+ . replace ( / [ ^ \u00C0 - \u1FFF \u2C00 - \uD7FF \w \- ] / g, "" )
9
+ . replace ( / [ ] / g, "-" )
10
+ . toLowerCase ( ) ;
11
+
12
+ let id = $heading . id ;
13
+ let $a = $ ( '<a class="no-underline">' )
14
+ . prop ( "href" , "#" + id )
15
+ . attr ( "aria-hidden" , "true" ) . html ( `
16
+ <svg xmlns="http://www.w3.org/2000/svg" style="width: 0.8em; height: 0.8em;" viewBox="0 0 24 24" fill="none" stroke="currentColor"
17
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link">
18
+ <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
19
+ <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
20
+ </svg>
21
+ ` ) ;
22
+ $ ( $heading ) . append ( $a ) ;
23
+ } ) ;
24
+ }
25
+
26
+ function add_click_to_copy ( ) {
27
+ $ ( "pre code" )
28
+ . parent ( "pre" )
29
+ . prepend (
30
+ `<button title="Copy Code" class="btn copy-btn" data-toggle="tooltip"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clipboard"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg></button>`
31
+ ) ;
32
+
33
+ $ ( ".copy-btn" ) . on ( "click" , function ( ) {
34
+ frappe . utils . copy_to_clipboard ( $ ( this ) . siblings ( "code" ) . text ( ) ) ;
35
+ } ) ;
36
+ }
37
+
38
+ function set_toc ( ) {
39
+ // Reset scroll event listener to avoid scroll jitterness
40
+ $ ( window ) . off ( "scroll" ) ;
41
+ $ ( document ) . ready ( function ( ) {
42
+ $ ( window ) . scroll ( function ( ) {
43
+ if ( currentAnchor ( ) . not ( ".no-underline" ) . hasClass ( "active" ) ) return ;
44
+ $ ( ".page-toc a" ) . removeClass ( "active" ) ;
45
+ currentAnchor ( ) . addClass ( "active" ) ;
46
+ } ) ;
47
+
48
+ const navbarHeight = $ ( ".navbar" ) . height ( ) ;
49
+ $ ( ".page-toc a" ) . click ( function ( e ) {
50
+ e . preventDefault ( ) ;
51
+ var target = $ ( this ) . attr ( "href" ) ;
52
+ var offset = $ ( target ) . offset ( ) . top - navbarHeight - 50 ;
53
+ $ ( "html, body" ) . animate (
54
+ {
55
+ scrollTop : offset ,
56
+ } ,
57
+ 100
58
+ ) ;
59
+ } ) ;
60
+ } ) ;
61
+
62
+ function tocItem ( anchor ) {
63
+ return $ ( '[href="' + anchor + '"]' ) ;
64
+ }
65
+
66
+ function heading ( anchor ) {
67
+ return $ ( "[id=" + anchor . substr ( 1 ) + "]" ) ;
68
+ }
69
+
70
+ var _anchors = null ;
71
+ function anchors ( ) {
72
+ if ( ! _anchors ) {
73
+ _anchors = $ ( ".page-toc .list-unstyled a" ) . map ( function ( ) {
74
+ return $ ( this ) . attr ( "href" ) ;
75
+ } ) ;
76
+ }
77
+ return _anchors ;
78
+ }
79
+
80
+ function currentAnchor ( ) {
81
+ var winY = window . pageYOffset ;
82
+ var currAnchor = null ;
83
+ anchors ( ) . each ( function ( ) {
84
+ var y = heading ( this ) . position ( ) ?. top ;
85
+ if ( y < winY + window . innerHeight * 0.23 ) {
86
+ currAnchor = this ;
87
+ return ;
88
+ }
89
+ } ) ;
90
+ return tocItem ( currAnchor ) ;
91
+ }
92
+ }
93
+
1
94
window . Wiki = class Wiki {
2
95
activate_sidebars ( ) {
3
96
$ ( ".sidebar-item" ) . each ( function ( index ) {
@@ -18,6 +111,20 @@ window.Wiki = class Wiki {
18
111
. scrollTo ( 0 , topOffset - 200 ) ;
19
112
} , 50 ) ;
20
113
}
114
+
115
+ $ ( $ ( this ) )
116
+ . find ( "a" )
117
+ . on ( "click" , ( e ) => {
118
+ e . preventDefault ( ) ;
119
+ const href = $ ( e . currentTarget ) . attr ( "href" ) ;
120
+ loadWikiPage ( href , e . currentTarget ) ;
121
+ $ ( "html, body" ) . animate (
122
+ {
123
+ scrollTop : 0 ,
124
+ } ,
125
+ 100
126
+ ) ;
127
+ } ) ;
21
128
} ) ;
22
129
}
23
130
@@ -96,41 +203,16 @@ window.Wiki = class Wiki {
96
203
} ) ;
97
204
}
98
205
206
+ set_toc ( ) {
207
+ set_toc ( ) ;
208
+ }
209
+
99
210
add_link_to_headings ( ) {
100
- $ ( ".from-markdown" )
101
- . not ( ".revision-content" )
102
- . find ( "h1, h2, h3, h4, h5, h6" )
103
- . each ( ( i , $heading ) => {
104
- const text = $heading . textContent . trim ( ) ;
105
- $heading . id = text
106
- . replace ( / [ ^ \u00C0 - \u1FFF \u2C00 - \uD7FF \w \- ] / g, "" )
107
- . replace ( / [ ] / g, "-" )
108
- . toLowerCase ( ) ;
109
-
110
- let id = $heading . id ;
111
- let $a = $ ( '<a class="no-underline">' )
112
- . prop ( "href" , "#" + id )
113
- . attr ( "aria-hidden" , "true" ) . html ( `
114
- <svg xmlns="http://www.w3.org/2000/svg" style="width: 0.8em; height: 0.8em;" viewBox="0 0 24 24" fill="none" stroke="currentColor"
115
- stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link">
116
- <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
117
- <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
118
- </svg>
119
- ` ) ;
120
- $ ( $heading ) . append ( $a ) ;
121
- } ) ;
211
+ add_link_to_headings ( ) ;
122
212
}
123
213
124
214
add_click_to_copy ( ) {
125
- $ ( "pre code" )
126
- . parent ( "pre" )
127
- . prepend (
128
- `<button title="Copy Code" class="btn copy-btn" data-toggle="tooltip"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clipboard"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg></button>`
129
- ) ;
130
-
131
- $ ( ".copy-btn" ) . on ( "click" , function ( ) {
132
- frappe . utils . copy_to_clipboard ( $ ( this ) . siblings ( "code" ) . text ( ) ) ;
133
- } ) ;
215
+ add_click_to_copy ( ) ;
134
216
}
135
217
} ;
136
218
@@ -146,3 +228,64 @@ $(document).on("click", function (e) {
146
228
$ ( "#navbar-dropdown-content" ) . addClass ( "hide" ) ;
147
229
}
148
230
} ) ;
231
+
232
+ function loadWikiPage ( url , pageElement , replaceState = false ) {
233
+ // Update URL and history state
234
+ const historyMethod = replaceState ? "replaceState" : "pushState" ;
235
+ window [ `history` ] [ historyMethod ] (
236
+ {
237
+ pageName : $ ( pageElement ) . closest ( ".sidebar-item" ) . data ( "name" ) ,
238
+ url : url ,
239
+ } ,
240
+ "" ,
241
+ url
242
+ ) ;
243
+
244
+ // Get the wiki page name from the parent element's data attribute
245
+ const pageName = $ ( pageElement ) . closest ( ".sidebar-item" ) . data ( "name" ) ;
246
+
247
+ frappe . call ( {
248
+ method : "wiki.wiki.doctype.wiki_page.wiki_page.get_page_content" ,
249
+ args : { wiki_page_name : pageName } ,
250
+ callback : ( r ) => {
251
+ if ( r . message ) {
252
+ $ ( ".wiki-content" ) . html ( r . message . content ) ;
253
+
254
+ $ ( ".wiki-title" ) . html ( r . message . title ) ;
255
+
256
+ if ( r . message . toc_html ) {
257
+ $ ( ".page-toc .list-unstyled" ) . html ( r . message . toc_html ) ;
258
+ }
259
+
260
+ // Update active sidebar item
261
+ $ ( ".sidebar-item" ) . removeClass ( "active" ) ;
262
+ $ ( ".sidebar-item" ) . find ( "a" ) . removeClass ( "active" ) ;
263
+ $ ( pageElement ) . closest ( ".sidebar-item" ) . addClass ( "active" ) ;
264
+ $ ( pageElement ) . addClass ( "active" ) ;
265
+
266
+ // Re-initialize necessary components
267
+ add_link_to_headings ( ) ;
268
+ add_click_to_copy ( ) ;
269
+ set_toc ( ) ;
270
+ }
271
+ } ,
272
+ } ) ;
273
+ }
274
+
275
+ window . addEventListener ( "popstate" , function ( event ) {
276
+ if ( event . state && event . state . pageName ) {
277
+ const sidebarItem = $ ( `.sidebar-item[data-name="${ event . state . pageName } "]` ) ;
278
+ if ( sidebarItem . length ) {
279
+ const pageElement = sidebarItem . find ( "a" ) [ 0 ] ;
280
+ loadWikiPage ( event . state . url , pageElement , true ) ;
281
+ }
282
+ } else {
283
+ // Fallback to path-based lookup
284
+ const path = window . location . pathname ;
285
+ const sidebarItem = $ ( `.sidebar-item[data-route="${ path . slice ( 1 ) } "]` ) ;
286
+ if ( sidebarItem . length ) {
287
+ const pageElement = sidebarItem . find ( "a" ) [ 0 ] ;
288
+ loadWikiPage ( path , pageElement , true ) ;
289
+ }
290
+ }
291
+ } ) ;
0 commit comments