1
1
import ParsoidDocument from '@chlodalejandro/parsoid' ;
2
2
import last from '../../../util/last' ;
3
+ import AttributionNotice from './AttributionNotice' ;
4
+ import WikiAttributionNotices from './WikiAttributionNotices' ;
3
5
import CopiedTemplate from './CopiedTemplate' ;
4
6
5
7
/**
6
8
* An event dispatched when a template inside a `CopiedTemplateEditorDialog` is inserted.
7
9
*/
8
10
export class TemplateInsertEvent extends Event {
9
11
10
- template : CopiedTemplate ;
12
+ template : AttributionNotice ;
11
13
12
14
/**
13
15
* @param template The template that was inserted
14
16
* @param eventInitDict
15
17
*/
16
- constructor ( template : CopiedTemplate , eventInitDict ?: EventInit ) {
18
+ constructor ( template : AttributionNotice , eventInitDict ?: EventInit ) {
17
19
super ( 'templateInsert' , eventInitDict ) ;
18
20
this . template = template ;
19
21
}
@@ -64,25 +66,15 @@ export default class CTEParsoidDocument extends ParsoidDocument {
64
66
'<html><body><section data-mw-section-id="0"></section></body></html>' ;
65
67
66
68
/**
67
- * Aliases of the {{copied}} template. This must be in lowercase and all
68
- * spaces must be replaced with underscores.
69
+ * A map of all Parsoid HTML elements and their attribution notices. When notices are
70
+ * detected, they are added here. ParsoidTemplateTransclusionNode is not used here
71
+ * since they are regenerated every time `findTemplate` is called.
69
72
*/
70
- static readonly copiedTemplateAliases = < const > [
71
- 'copied' ,
72
- 'copied_from' ,
73
- 'copywithin'
74
- ] ;
75
-
76
- /**
77
- * A list of {{copied}} notices in the document.
78
- *
79
- * @type {CopiedTemplate[] }
80
- */
81
- copiedNotices : CopiedTemplate [ ] ;
73
+ notices : Map < HTMLElement , AttributionNotice > = new Map ( ) ;
82
74
/**
83
75
* The original number of {{copied}} notices in the document.
84
76
*/
85
- originalNoticeCount : number ;
77
+ originalCount : number = null ;
86
78
87
79
/**
88
80
* Creates a new CTE-specific ParsoidDocument. This extends from the existing
@@ -100,8 +92,8 @@ export default class CTEParsoidDocument extends ParsoidDocument {
100
92
return ;
101
93
}
102
94
103
- this . findCopiedNotices ( ) ;
104
- this . originalNoticeCount = this . copiedNotices . length ;
95
+ const notices = this . findCopiedNotices ( ) ;
96
+ this . originalCount = notices . length ;
105
97
} ) ;
106
98
}
107
99
@@ -110,52 +102,53 @@ export default class CTEParsoidDocument extends ParsoidDocument {
110
102
*/
111
103
reset ( ) {
112
104
super . reset ( ) ;
113
- this . originalNoticeCount = undefined ;
114
- this . copiedNotices = undefined ;
105
+ this . originalCount = undefined ;
106
+ this . notices . clear ( ) ;
115
107
}
116
108
117
109
/**
118
- * Finds this document's {{copied}} notices.
110
+ * Finds all content attribution notices in the talk page. This includes {{copied}},
111
+ * {{merged to}}, {{merged from}}, etc.
112
+ *
113
+ * @return An array of AttributionNotice objects.
119
114
*/
120
- findCopiedNotices ( ) {
121
- if ( ! this . copiedNotices ) {
122
- this . copiedNotices = [ ] ;
123
- }
124
-
125
- const newCopiedNotices : CopiedTemplate [ ] = [ ] ;
115
+ findNotices ( ) : AttributionNotice [ ] {
126
116
this . buildIndex ( ) ;
117
+ // Used instead of `this.notices.values()` to exclude nodes that are no longer on the DOM.
118
+ const notices : AttributionNotice [ ] = [ ] ;
127
119
128
- for ( const templateElement of this . findTemplate (
129
- new RegExp (
130
- CTEParsoidDocument . copiedTemplateAliases . map (
131
- ( v ) => `(${ mw . util . escapeRegExp ( v ) } )`
132
- ) . join ( '|' ) ,
133
- 'gi'
134
- )
135
- ) ) {
136
- // This is a copied template.
137
- const existing = this . copiedNotices . find (
138
- ( v ) => v . element === templateElement . originalElement
139
- ) ;
140
- if ( existing ) {
141
- // Record exists, reuse that same object (prevents memory leaks).
142
- newCopiedNotices . push ( existing ) ;
143
- } else {
144
- // Not yet in the existing array, create a new object.
145
- const notice = new CopiedTemplate (
146
- CTEParsoidTransclusionTemplateNode . upgradeNode ( templateElement , this )
147
- ) ;
148
- newCopiedNotices . push (
149
- notice
120
+ for (
121
+ const node of this . findTemplate ( WikiAttributionNotices . templateAliasRegExp )
122
+ ) {
123
+ if ( ! this . notices . has ( node . originalElement ) ) {
124
+ // Notice not yet cached, but this is an attribution notice.
125
+ // Now to determine what type.
126
+ const type = WikiAttributionNotices . getTemplateNoticeType (
127
+ node . getTarget ( ) . href
150
128
) ;
151
- notice . addEventListener ( 'destroy' , ( ) => {
152
- const i = this . copiedNotices . indexOf ( notice ) ;
153
- this . copiedNotices . splice ( i , 1 ) ;
154
- } ) ;
129
+
130
+ const noticeInstance = new (
131
+ WikiAttributionNotices . attributionNoticeClasses [ type ]
132
+ ) ( CTEParsoidTransclusionTemplateNode . upgradeNode ( node , this ) ) ;
133
+ this . notices . set ( node . originalElement , noticeInstance ) ;
155
134
}
135
+
136
+ notices . push ( this . notices . get ( node . originalElement ) ) ;
156
137
}
157
138
158
- this . copiedNotices = newCopiedNotices ;
139
+ return notices ;
140
+ }
141
+
142
+ /**
143
+ * Finds this document's {{copied}} notices.
144
+ *
145
+ * @return An array of all CopiedTemplate objects found
146
+ */
147
+ findCopiedNotices ( ) : CopiedTemplate [ ] {
148
+ return this . findNotices ( ) . filter (
149
+ ( notice ) => notice instanceof
150
+ WikiAttributionNotices . attributionNoticeClasses . copied
151
+ ) as CopiedTemplate [ ] ;
159
152
}
160
153
161
154
/**
@@ -237,9 +230,7 @@ export default class CTEParsoidDocument extends ParsoidDocument {
237
230
// Insert.
238
231
element . insertAdjacentElement ( position , template ) ;
239
232
this . findCopiedNotices ( ) ;
240
- const templateObject = this . copiedNotices . find (
241
- ( v ) => v . element === template
242
- ) ;
233
+ const templateObject = this . notices . get ( template ) ;
243
234
this . dispatchEvent ( new TemplateInsertEvent ( templateObject ) ) ;
244
235
}
245
236
}
0 commit comments