Skip to content

Commit 53b13c0

Browse files
authored
Merge pull request #710 from mathjax/nonscript
Add \noscript command
2 parents 657594c + c54a989 commit 53b13c0

4 files changed

Lines changed: 111 additions & 10 deletions

File tree

ts/input/tex/base/BaseConfiguration.ts

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import * as bitem from './BaseItems.js';
3232
import {AbstractTags} from '../Tags.js';
3333
import './BaseMappings.js';
3434
import {getRange} from '../../../core/MmlTree/OperatorDictionary.js';
35+
import {MmlNode} from '../../../core/MmlTree/MmlNode.js';
36+
import ParseOptions from '../ParseOptions.js';
3537

3638
/**
3739
* Remapping some ASCII characters to their Unicode operator equivalent.
@@ -89,6 +91,45 @@ function envUndefined(_parser: TexParser, env: string) {
8991
throw new TexError('UnknownEnv', 'Unknown environment \'%1\'', env);
9092
}
9193

94+
/**
95+
* Filter for removing spacing following \nonscript
96+
* @param{ParseOptions} data The active tex parser.
97+
*/
98+
function filterNonscript({data}: {data: ParseOptions}) {
99+
for (const mml of data.getList('nonscript')) {
100+
//
101+
// This is the list of mspace elements or mrow > mstyle > mspace
102+
// that followed \nonscript macros to be tested for removal.
103+
//
104+
if (mml.attributes.get('scriptlevel') > 0) {
105+
//
106+
// The mspace needs to be removed, since we are in a script style.
107+
// Remove it from the DOM and from the list of mspace elements.
108+
//
109+
const parent = mml.parent;
110+
parent.childNodes.splice(parent.childIndex(mml), 1);
111+
data.removeFromList(mml.kind, [mml]);
112+
//
113+
// If it is an mrow > mstyle > mspace, then we have just
114+
// removed the mrow from its list, and must remove
115+
// the mstyle and mspace from their lists as well.
116+
//
117+
if (mml.isKind('mrow')) {
118+
const mstyle = mml.childNodes[0] as MmlNode;
119+
data.removeFromList('mstyle', [mstyle]);
120+
data.removeFromList('mspace', mstyle.childNodes[0].childNodes as MmlNode[]);
121+
}
122+
} else if (mml.isKind('mrow')) {
123+
//
124+
// This is an mrow > mstyle > mspace but we're not in a script
125+
// style, so remove the mrow that we had added in the NonscriptItem.
126+
//
127+
mml.parent.replaceChild(mml.childNodes[0], mml);
128+
data.removeFromList('mrow', [mml]);
129+
}
130+
}
131+
}
132+
92133

93134
/**
94135
* @constructor
@@ -135,19 +176,21 @@ export const BaseConfiguration: Configuration = Configuration.create(
135176
[bitem.MmlItem.prototype.kind]: bitem.MmlItem,
136177
[bitem.FnItem.prototype.kind]: bitem.FnItem,
137178
[bitem.NotItem.prototype.kind]: bitem.NotItem,
179+
[bitem.NonscriptItem.prototype.kind]: bitem.NonscriptItem,
138180
[bitem.DotsItem.prototype.kind]: bitem.DotsItem,
139181
[bitem.ArrayItem.prototype.kind]: bitem.ArrayItem,
140182
[bitem.EqnArrayItem.prototype.kind]: bitem.EqnArrayItem,
141183
[bitem.EquationItem.prototype.kind]: bitem.EquationItem
142-
},
143-
options: {
144-
maxMacros: 1000,
145-
baseURL: (typeof(document) === 'undefined' ||
146-
document.getElementsByTagName('base').length === 0) ?
147-
'' : String(document.location).replace(/#.*$/, '')
148-
},
149-
tags: {
150-
base: BaseTags
151-
}
184+
},
185+
options: {
186+
maxMacros: 1000,
187+
baseURL: (typeof(document) === 'undefined' ||
188+
document.getElementsByTagName('base').length === 0) ?
189+
'' : String(document.location).replace(/#.*$/, '')
190+
},
191+
tags: {
192+
base: BaseTags
193+
},
194+
postprocessors: [[filterNonscript, -4]]
152195
}
153196
);

ts/input/tex/base/BaseItems.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,53 @@ export class NotItem extends BaseItem {
773773
}
774774
}
775775

776+
/**
777+
* A StackItem that removes an mspace that follows it (for \nonscript).
778+
*/
779+
export class NonscriptItem extends BaseItem {
780+
781+
/**
782+
* @override
783+
*/
784+
public get kind() {
785+
return 'nonscript';
786+
}
787+
788+
/**
789+
* @override
790+
*/
791+
public checkItem(item: StackItem): CheckType {
792+
//
793+
// Check if the next item is an mspace (or an mspace in an mstyle) and remove it.
794+
//
795+
if (item.isKind('mml') && item.Size() === 1) {
796+
let mml = item.First;
797+
//
798+
// Space macros like \, are wrapped with an mstyle to set scriptlevel="0"
799+
// (so size is independent of level), we look at the contents of the mstyle for the mspace.
800+
//
801+
if (mml.isKind('mstyle') && mml.notParent) {
802+
mml = NodeUtil.getChildren(NodeUtil.getChildren(mml)[0])[0];
803+
}
804+
if (mml.isKind('mspace')) {
805+
//
806+
// If the space is in an mstyle, wrap it in an mrow so we can test its scriptlevel
807+
// in the post-filter (the mrow will be removed in the filter). We can't test
808+
// the mstyle's scriptlevel, since it is ecxplicitly setting it to 0.
809+
//
810+
if (mml !== item.First) {
811+
const mrow = this.create('node', 'mrow', [item.Pop()]);
812+
item.Push(mrow);
813+
}
814+
//
815+
// Save the mspace for later post-processing.
816+
//
817+
this.factory.configuration.addNode('nonscript', item.First);
818+
}
819+
}
820+
return [[item], true];
821+
}
822+
}
776823

777824
/**
778825
* Item indicating a dots command has been encountered.

ts/input/tex/base/BaseMappings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ new sm.CommandMap('macros', {
575575
rule: 'rule',
576576
Rule: ['Rule'],
577577
Space: ['Rule', 'blank'],
578+
nonscript: 'Nonscript',
578579

579580
big: ['MakeBig', TEXCLASS.ORD, 0.85],
580581
Big: ['MakeBig', TEXCLASS.ORD, 1.15],

ts/input/tex/base/BaseMethods.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,16 @@ BaseMethods.Hskip = function(parser: TexParser, name: string) {
896896
};
897897

898898

899+
/**
900+
* Handle removal of spaces in script modes
901+
* @param {TexParser} parser The calling parser.
902+
* @param {string} name The macro name.
903+
*/
904+
BaseMethods.Nonscript = function(parser: TexParser, _name: string) {
905+
parser.Push(parser.itemFactory.create('nonscript'));
906+
};
907+
908+
899909
/**
900910
* Handle Rule and Space command
901911
* @param {TexParser} parser The calling parser.

0 commit comments

Comments
 (0)