@@ -13,6 +13,8 @@ import { Compiler } from './compiler';
13
13
import * as tpl from './tpl' ;
14
14
import { prerenderEmbed } from './embed' ;
15
15
16
+ let vueGlobalData ;
17
+
16
18
function executeScript ( ) {
17
19
const script = dom
18
20
. findAll ( '.markdown-section>script' )
@@ -41,58 +43,103 @@ function formatUpdated(html, updated, fn) {
41
43
}
42
44
43
45
function renderMain ( html ) {
46
+ const docsifyConfig = this . config ;
47
+ const markdownElm = dom . find ( '.markdown-section' ) ;
48
+ const vueVersion =
49
+ 'Vue' in window &&
50
+ window . Vue . version &&
51
+ Number ( window . Vue . version . charAt ( 0 ) ) ;
52
+
53
+ const isMountedVue = elm => {
54
+ const isVue2 = Boolean ( elm . __vue__ && elm . __vue__ . _isVue ) ;
55
+ const isVue3 = Boolean ( elm . _vnode && elm . _vnode . __v_skip ) ;
56
+
57
+ return isVue2 || isVue3 ;
58
+ } ;
59
+
44
60
if ( ! html ) {
45
61
html = '<h1>404 - Not found</h1>' ;
46
62
}
47
63
48
- this . _renderTo ( '.markdown-section' , html ) ;
64
+ if ( 'Vue' in window ) {
65
+ const mountedElms = dom
66
+ . findAll ( '.markdown-section > *' )
67
+ . filter ( elm => isMountedVue ( elm ) ) ;
68
+
69
+ // Store global data() return value as shared data object
70
+ if ( ! vueGlobalData && docsifyConfig . vueGlobalOptions . data ) {
71
+ vueGlobalData = docsifyConfig . vueGlobalOptions . data ( ) ;
72
+ }
73
+
74
+ // Destroy/unmount existing Vue instances
75
+ for ( const mountedElm of mountedElms ) {
76
+ if ( vueVersion === 2 ) {
77
+ mountedElm . __vue__ . $destroy ( ) ;
78
+ } else if ( vueVersion === 3 ) {
79
+ mountedElm . __vue_app__ . unmount ( ) ;
80
+ }
81
+ }
82
+ }
83
+
84
+ this . _renderTo ( markdownElm , html ) ;
49
85
50
86
// Render sidebar with the TOC
51
- ! this . config . loadSidebar && this . _renderSidebar ( ) ;
87
+ ! docsifyConfig . loadSidebar && this . _renderSidebar ( ) ;
52
88
53
89
// Execute markdown <script>
54
90
if (
55
- this . config . executeScript ||
56
- ( 'Vue' in window && this . config . executeScript !== false )
91
+ docsifyConfig . executeScript ||
92
+ ( 'Vue' in window && docsifyConfig . executeScript !== false )
57
93
) {
58
94
executeScript ( ) ;
59
95
}
60
96
61
- // Handle Vue content not handled by markdown <script>
97
+ // Handle Vue content not mounted by markdown <script>
62
98
if ( 'Vue' in window ) {
63
- const mainElm = document . querySelector ( '#main' ) || { } ;
64
- const childElms = mainElm . children || [ ] ;
65
- const vueVersion =
66
- window . Vue . version && Number ( window . Vue . version . charAt ( 0 ) ) ;
67
-
68
- for ( let i = 0 , len = childElms . length ; i < len ; i ++ ) {
69
- const elm = childElms [ i ] ;
70
- const isValid = elm . tagName !== 'SCRIPT' ;
71
-
72
- if ( ! isValid ) {
73
- continue ;
74
- }
99
+ const vueMountData = [ ] ;
100
+
101
+ if ( docsifyConfig . vueOptions ) {
102
+ vueMountData . push (
103
+ ... Object . entries ( docsifyConfig . vueOptions || { } )
104
+ . map ( ( [ cssSelector , vueConfig ] ) => [
105
+ dom . find ( markdownElm , cssSelector ) ,
106
+ vueConfig ,
107
+ ] )
108
+ . filter ( ( [ elm , vueConfig ] ) => elm )
109
+ ) ;
110
+ }
75
111
76
- // Vue 3
77
- if ( vueVersion === 3 ) {
78
- const isAlreadyVue = Boolean ( elm . _vnode && elm . _vnode . __v_skip ) ;
112
+ if ( docsifyConfig . vueGlobalOptions ) {
113
+ vueMountData . push (
114
+ ...dom
115
+ . findAll ( '.markdown-section > *' )
116
+ // Remove duplicates
117
+ . filter ( elm => ! vueMountData . some ( ( [ e , c ] ) => e === elm ) )
118
+ . map ( elm => [
119
+ elm ,
120
+ ! docsifyConfig . vueGlobalOptions . data
121
+ ? docsifyConfig . vueGlobalOptions
122
+ : // Replace data() return value with shared data object. This
123
+ // mimics the behavior of a global store when using the same
124
+ // configuration with multiple Vue instances.
125
+ Object . assign ( { } , docsifyConfig . vueGlobalOptions , {
126
+ data ( ) {
127
+ return vueGlobalData ;
128
+ } ,
129
+ } ) ,
130
+ ] )
131
+ ) ;
132
+ }
79
133
80
- if ( ! isAlreadyVue ) {
81
- const app = window . Vue . createApp ( { } ) ;
134
+ for ( const [ mountElm , vueConfig ] of vueMountData ) {
135
+ const isValidTag = mountElm . tagName !== 'SCRIPT' ;
136
+ const hasBrackets = / { { 2 } [ ^ { } ] * } { 2 } / . test ( mountElm . outerHTML ) ;
82
137
83
- app . mount ( elm ) ;
84
- }
85
- }
86
- // Vue 2
87
- else if ( vueVersion === 2 ) {
88
- const isAlreadyVue = Boolean ( elm . __vue__ && elm . __vue__ . _isVue ) ;
89
-
90
- if ( ! isAlreadyVue ) {
91
- new window . Vue ( {
92
- mounted : function ( ) {
93
- this . $destroy ( ) ;
94
- } ,
95
- } ) . $mount ( elm ) ;
138
+ if ( isValidTag && hasBrackets && ! isMountedVue ( mountElm ) ) {
139
+ if ( vueVersion === 2 ) {
140
+ new window . Vue ( vueConfig ) . $mount ( mountElm ) ;
141
+ } else if ( vueVersion === 3 ) {
142
+ window . Vue . createApp ( vueConfig ) . mount ( mountElm ) ;
96
143
}
97
144
}
98
145
}
0 commit comments