@@ -87,6 +87,7 @@ export type MMLNODE = MmlNode | TextNode | XMLNode;
8787 */
8888
8989export interface MmlNode extends Node {
90+
9091 /**
9192 * Test various properties of MathML nodes
9293 */
@@ -95,21 +96,25 @@ export interface MmlNode extends Node {
9596 readonly isSpacelike : boolean ;
9697 readonly linebreakContainer : boolean ;
9798 readonly hasNewLine : boolean ;
99+
98100 /**
99101 * The expected number of children (-1 means use inferred mrow)
100102 */
101103 readonly arity : number ;
102104 readonly isInferred : boolean ;
105+
103106 /**
104107 * Get the parent node (skipping inferred mrows and
105108 * other nodes marked as notParent)
106109 */
107110 readonly Parent : MmlNode ;
108111 readonly notParent : boolean ;
112+
109113 /**
110114 * The actual parent in the tree
111115 */
112116 parent : MmlNode ;
117+
113118 /**
114119 * values needed for TeX spacing computations
115120 */
@@ -127,16 +132,19 @@ export interface MmlNode extends Node {
127132 * core <mo> node. For non-embellished nodes, the original node.
128133 */
129134 core ( ) : MmlNode ;
135+
130136 /**
131137 * @return {MmlNode } For embellished operators, the core <mo> element (at whatever
132138 * depth). For non-embellished nodes, the original node itself.
133139 */
134140 coreMO ( ) : MmlNode ;
141+
135142 /**
136143 * @return {number } For embellished operators, the index of the child node containing
137144 * the core <mo>. For non-embellished nodes, 0.
138145 */
139146 coreIndex ( ) : number ;
147+
140148 /**
141149 * @return {number } The index of this node in its parent's childNodes array.
142150 */
@@ -149,10 +157,12 @@ export interface MmlNode extends Node {
149157 * in the tree (usually, either the last child, or the node itself)
150158 */
151159 setTeXclass ( prev : MmlNode ) : MmlNode ;
160+
152161 /**
153162 * @return {string } The spacing to use before this element (one of TEXSPACELENGTH array above)
154163 */
155164 texSpacing ( ) : string ;
165+
156166 /**
157167 * @return {boolean } The core mo element has an explicit 'form', 'lspace', or 'rspace' attribute
158168 */
@@ -201,10 +211,12 @@ export interface MmlNode extends Node {
201211 */
202212
203213export interface MmlNodeClass extends NodeClass {
214+
204215 /**
205216 * The list of default attribute values for nodes of this class
206217 */
207218 defaults ?: PropertyList ;
219+
208220 /**
209221 * An MmlNode takes a NodeFactory (so it can create additional nodes as needed), a list
210222 * of attributes, and an array of children and returns the desired MmlNode with
@@ -216,6 +228,7 @@ export interface MmlNodeClass extends NodeClass {
216228 * @param {MmlNode[] } children The initial child nodes (more can be added later)
217229 */
218230 new ( factory : MmlFactory , attributes ?: PropertyList , children ?: MmlNode [ ] ) : MmlNode ;
231+
219232}
220233
221234
@@ -237,6 +250,7 @@ export abstract class AbstractMmlNode extends AbstractNode implements MmlNode {
237250 // scale all spaces, fractions, etc.
238251 dir : INHERIT
239252 } ;
253+
240254 /**
241255 * This lists properties that do NOT get inherited between specific kinds
242256 * of nodes. The outer keys are the node kinds that are being inherited FROM,
@@ -285,6 +299,7 @@ export abstract class AbstractMmlNode extends AbstractNode implements MmlNode {
285299 * The TeX class for the preceding node
286300 */
287301 public prevClass : number = null ;
302+
288303 /**
289304 * The scriptlevel of the preceding node
290305 */
@@ -299,10 +314,12 @@ export abstract class AbstractMmlNode extends AbstractNode implements MmlNode {
299314 * Child nodes are MmlNodes (special case of Nodes).
300315 */
301316 public childNodes : MmlNode [ ] ;
317+
302318 /**
303319 * The parent is an MmlNode
304320 */
305321 public parent : MmlNode ;
322+
306323 /**
307324 * The node factory is an MmlFactory
308325 */
@@ -335,6 +352,40 @@ export abstract class AbstractMmlNode extends AbstractNode implements MmlNode {
335352 this . attributes . setList ( attributes ) ;
336353 }
337354
355+ /**
356+ * @override
357+ *
358+ * @param {boolean } keepIds True to copy id attributes, false to skip them.
359+ * (May cause error in the future, since not part of the interface.)
360+ * @return {AbstractMmlNode } The copied node tree.
361+ */
362+ public copy ( keepIds : boolean = false ) : AbstractMmlNode {
363+ const node = this . factory . create ( this . kind ) as AbstractMmlNode ;
364+ node . properties = { ...this . properties } ;
365+ if ( this . attributes ) {
366+ const attributes = this . attributes . getAllAttributes ( ) ;
367+ for ( const name of Object . keys ( attributes ) ) {
368+ if ( name !== 'id' || keepIds ) {
369+ node . attributes . set ( name , attributes [ name ] ) ;
370+ }
371+ }
372+ }
373+ if ( this . childNodes && this . childNodes . length ) {
374+ let children = this . childNodes as MmlNode [ ] ;
375+ if ( children . length === 1 && children [ 0 ] . isInferred ) {
376+ children = children [ 0 ] . childNodes as MmlNode [ ] ;
377+ }
378+ for ( const child of children ) {
379+ if ( child ) {
380+ node . appendChild ( child . copy ( ) as MmlNode ) ;
381+ } else {
382+ node . childNodes . push ( null ) ;
383+ }
384+ }
385+ }
386+ return node ;
387+ }
388+
338389 /**
339390 * The TeX class for this node
340391 */
@@ -1176,6 +1227,13 @@ export class TextNode extends AbstractMmlEmptyNode {
11761227 return this ;
11771228 }
11781229
1230+ /**
1231+ * @override
1232+ */
1233+ public copy ( ) {
1234+ return ( this . factory . create ( this . kind ) as TextNode ) . setText ( this . getText ( ) ) ;
1235+ }
1236+
11791237 /**
11801238 * Just use the text
11811239 */
@@ -1234,6 +1292,13 @@ export class XMLNode extends AbstractMmlEmptyNode {
12341292 return this . adaptor . serializeXML ( this . xml ) ;
12351293 }
12361294
1295+ /**
1296+ * @override
1297+ */
1298+ public copy ( ) : XMLNode {
1299+ return ( this . factory . create ( this . kind ) as XMLNode ) . setXML ( this . adaptor . clone ( this . xml ) ) ;
1300+ }
1301+
12371302 /**
12381303 * Just indicate that this is XML data
12391304 */
0 commit comments