Commit 166b1958 authored by Alf Eaton's avatar Alf Eaton
Browse files

Move MathJax code and improve HTML/SVG sanitization

parent 4d3aa3bc
......@@ -293,12 +293,21 @@ export const insertInlineEquation = (
selectedText().replace(/^\$/, '').replace(/\$$/, '')
)
const sourcePos = state.selection.from - 1
const tr = state.tr
.setMeta(modelsKey, { [INSERT]: [inlineMathFragment] })
.replaceSelectionWith(state.schema.nodes.inline_equation.create())
.replaceSelectionWith(
state.schema.nodes.inline_equation.create({
id: inlineMathFragment._id,
})
)
if (dispatch) {
const selection = NodeSelection.create(tr.doc, state.tr.selection.from)
const selection = NodeSelection.create(
tr.doc,
tr.mapping.map(sourcePos) + 1
)
dispatch(tr.setSelection(selection).scrollIntoView())
}
......
......@@ -40,8 +40,6 @@ export { Viewer } from './components/Viewer'
export { menus } from './menus'
export { ChangeReceiver } from './types'
export { PopperManager } from './lib/popper'
export { convertToMathML } from './lib/mathjax-mathml'
export { convertToSVG } from './lib/mathjax-svg'
export { toolbar } from './toolbar'
export * from './plugins/highlight'
export * from './plugins/keywords'
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`mathjax generate display mathml 1`] = `
"<math xmlns=\\"http://www.w3.org/1998/Math/MathML\\" display=\\"block\\">
<msqrt>
<mn>2</mn>
</msqrt>
<mo>&#x2212;</mo>
<msub>
<mi>z</mi>
<mrow>
<mi>f</mi>
<mi>o</mi>
<mi>o</mi>
</mrow>
</msub>
<mo>=</mo>
<mo data-mjx-texclass=\\"OP\\">&#x2211;</mo>
<mrow>
<mi>x</mi>
</mrow>
</math>"
`;
exports[`mathjax generate display svg 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" style=\\"vertical-align: -1.018ex;\\" width=\\"17.379ex\\" height=\\"3.299ex\\" role=\\"img\\" focusable=\\"false\\" viewBox=\\"0 -1008.3 7681.5 1458.3\\"><g stroke=\\"currentColor\\" fill=\\"currentColor\\" stroke-width=\\"0\\" transform=\\"matrix(1 0 0 -1 0 0)\\"><g data-mml-node=\\"math\\"><g data-mml-node=\\"msqrt\\"><g transform=\\"translate(853, 0)\\"><g data-mml-node=\\"mn\\"><path data-c=\\"32\\" d=\\"M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z\\"/></g></g><g data-mml-node=\\"mo\\" transform=\\"translate(0, 148.3)\\"><path data-c=\\"221A\\" d=\\"M95 178Q89 178 81 186T72 200T103 230T169 280T207 309Q209 311 212 311H213Q219 311 227 294T281 177Q300 134 312 108L397 -77Q398 -77 501 136T707 565T814 786Q820 800 834 800Q841 800 846 794T853 782V776L620 293L385 -193Q381 -200 366 -200Q357 -200 354 -197Q352 -195 256 15L160 225L144 214Q129 202 113 190T95 178Z\\"/></g><rect width=\\"500\\" height=\\"60\\" x=\\"853\\" y=\\"888.3\\"/></g><g data-mml-node=\\"mo\\" transform=\\"translate(1575.2, 0)\\"><path data-c=\\"2212\\" d=\\"M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z\\"/></g><g data-mml-node=\\"msub\\" transform=\\"translate(2575.4, 0)\\"><g data-mml-node=\\"mi\\"><path data-c=\\"1D467\\" d=\\"M347 338Q337 338 294 349T231 360Q211 360 197 356T174 346T162 335T155 324L153 320Q150 317 138 317Q117 317 117 325Q117 330 120 339Q133 378 163 406T229 440Q241 442 246 442Q271 442 291 425T329 392T367 375Q389 375 411 408T434 441Q435 442 449 442H462Q468 436 468 434Q468 430 463 420T449 399T432 377T418 358L411 349Q368 298 275 214T160 106L148 94L163 93Q185 93 227 82T290 71Q328 71 360 90T402 140Q406 149 409 151T424 153Q443 153 443 143Q443 138 442 134Q425 72 376 31T278 -11Q252 -11 232 6T193 40T155 57Q111 57 76 -3Q70 -11 59 -11H54H41Q35 -5 35 -2Q35 13 93 84Q132 129 225 214T340 322Q352 338 347 338Z\\"/></g><g data-mml-node=\\"TeXAtom\\" transform=\\"translate(465, -150) scale(0.707)\\" data-mjx-texclass=\\"ORD\\"><g data-mml-node=\\"mi\\"><path data-c=\\"1D453\\" d=\\"M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z\\"/></g><g data-mml-node=\\"mi\\" transform=\\"translate(550, 0)\\"><path data-c=\\"1D45C\\" d=\\"M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z\\"/></g><g data-mml-node=\\"mi\\" transform=\\"translate(1035, 0)\\"><path data-c=\\"1D45C\\" d=\\"M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z\\"/></g></g></g><g data-mml-node=\\"mo\\" transform=\\"translate(4443, 0)\\"><path data-c=\\"3D\\" d=\\"M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z\\"/></g><g data-mml-node=\\"mo\\" transform=\\"translate(5498.8, 0)\\"><path data-c=\\"2211\\" d=\\"M60 948Q63 950 665 950H1267L1325 815Q1384 677 1388 669H1348L1341 683Q1320 724 1285 761Q1235 809 1174 838T1033 881T882 898T699 902H574H543H251L259 891Q722 258 724 252Q725 250 724 246Q721 243 460 -56L196 -356Q196 -357 407 -357Q459 -357 548 -357T676 -358Q812 -358 896 -353T1063 -332T1204 -283T1307 -196Q1328 -170 1348 -124H1388Q1388 -125 1381 -145T1356 -210T1325 -294L1267 -449L666 -450Q64 -450 61 -448Q55 -446 55 -439Q55 -437 57 -433L590 177Q590 178 557 222T452 366T322 544L56 909L55 924Q55 945 60 948Z\\"/></g><g data-mml-node=\\"TeXAtom\\" data-mjx-texclass=\\"ORD\\" transform=\\"translate(7109.5, 0)\\"><g data-mml-node=\\"mi\\"><path data-c=\\"1D465\\" d=\\"M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z\\"/></g></g></g></g></svg>"`;
exports[`mathjax generate inline mathml 1`] = `
"<math xmlns=\\"http://www.w3.org/1998/Math/MathML\\">
<msqrt>
<mn>2</mn>
</msqrt>
<mo>&#x2212;</mo>
<msub>
<mi>z</mi>
<mrow>
<mi>f</mi>
<mi>o</mi>
<mi>o</mi>
</mrow>
</msub>
<mo>=</mo>
<mo data-mjx-texclass=\\"OP\\">&#x2211;</mo>
<mrow>
<mi>x</mi>
</mrow>
</math>"
`;
exports[`mathjax generate inline svg 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" style=\\"vertical-align: -0.667ex;\\" width=\\"16.501ex\\" height=\\"2.84ex\\" role=\\"img\\" focusable=\\"false\\" viewBox=\\"0 -960.5 7293.5 1255.5\\"><g stroke=\\"currentColor\\" fill=\\"currentColor\\" stroke-width=\\"0\\" transform=\\"matrix(1 0 0 -1 0 0)\\"><g data-mml-node=\\"math\\"><g data-mml-node=\\"msqrt\\"><g transform=\\"translate(853, 0)\\"><g data-mml-node=\\"mn\\"><path data-c=\\"32\\" d=\\"M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z\\"/></g></g><g data-mml-node=\\"mo\\" transform=\\"translate(0, 100.5)\\"><path data-c=\\"221A\\" d=\\"M95 178Q89 178 81 186T72 200T103 230T169 280T207 309Q209 311 212 311H213Q219 311 227 294T281 177Q300 134 312 108L397 -77Q398 -77 501 136T707 565T814 786Q820 800 834 800Q841 800 846 794T853 782V776L620 293L385 -193Q381 -200 366 -200Q357 -200 354 -197Q352 -195 256 15L160 225L144 214Q129 202 113 190T95 178Z\\"/></g><rect width=\\"500\\" height=\\"60\\" x=\\"853\\" y=\\"840.5\\"/></g><g data-mml-node=\\"mo\\" transform=\\"translate(1575.2, 0)\\"><path data-c=\\"2212\\" d=\\"M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z\\"/></g><g data-mml-node=\\"msub\\" transform=\\"translate(2575.4, 0)\\"><g data-mml-node=\\"mi\\"><path data-c=\\"1D467\\" d=\\"M347 338Q337 338 294 349T231 360Q211 360 197 356T174 346T162 335T155 324L153 320Q150 317 138 317Q117 317 117 325Q117 330 120 339Q133 378 163 406T229 440Q241 442 246 442Q271 442 291 425T329 392T367 375Q389 375 411 408T434 441Q435 442 449 442H462Q468 436 468 434Q468 430 463 420T449 399T432 377T418 358L411 349Q368 298 275 214T160 106L148 94L163 93Q185 93 227 82T290 71Q328 71 360 90T402 140Q406 149 409 151T424 153Q443 153 443 143Q443 138 442 134Q425 72 376 31T278 -11Q252 -11 232 6T193 40T155 57Q111 57 76 -3Q70 -11 59 -11H54H41Q35 -5 35 -2Q35 13 93 84Q132 129 225 214T340 322Q352 338 347 338Z\\"/></g><g data-mml-node=\\"TeXAtom\\" transform=\\"translate(465, -150) scale(0.707)\\" data-mjx-texclass=\\"ORD\\"><g data-mml-node=\\"mi\\"><path data-c=\\"1D453\\" d=\\"M118 -162Q120 -162 124 -164T135 -167T147 -168Q160 -168 171 -155T187 -126Q197 -99 221 27T267 267T289 382V385H242Q195 385 192 387Q188 390 188 397L195 425Q197 430 203 430T250 431Q298 431 298 432Q298 434 307 482T319 540Q356 705 465 705Q502 703 526 683T550 630Q550 594 529 578T487 561Q443 561 443 603Q443 622 454 636T478 657L487 662Q471 668 457 668Q445 668 434 658T419 630Q412 601 403 552T387 469T380 433Q380 431 435 431Q480 431 487 430T498 424Q499 420 496 407T491 391Q489 386 482 386T428 385H372L349 263Q301 15 282 -47Q255 -132 212 -173Q175 -205 139 -205Q107 -205 81 -186T55 -132Q55 -95 76 -78T118 -61Q162 -61 162 -103Q162 -122 151 -136T127 -157L118 -162Z\\"/></g><g data-mml-node=\\"mi\\" transform=\\"translate(550, 0)\\"><path data-c=\\"1D45C\\" d=\\"M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z\\"/></g><g data-mml-node=\\"mi\\" transform=\\"translate(1035, 0)\\"><path data-c=\\"1D45C\\" d=\\"M201 -11Q126 -11 80 38T34 156Q34 221 64 279T146 380Q222 441 301 441Q333 441 341 440Q354 437 367 433T402 417T438 387T464 338T476 268Q476 161 390 75T201 -11ZM121 120Q121 70 147 48T206 26Q250 26 289 58T351 142Q360 163 374 216T388 308Q388 352 370 375Q346 405 306 405Q243 405 195 347Q158 303 140 230T121 120Z\\"/></g></g></g><g data-mml-node=\\"mo\\" transform=\\"translate(4443, 0)\\"><path data-c=\\"3D\\" d=\\"M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z\\"/></g><g data-mml-node=\\"mo\\" transform=\\"translate(5498.8, 0)\\"><path data-c=\\"2211\\" d=\\"M61 748Q64 750 489 750H913L954 640Q965 609 976 579T993 533T999 516H979L959 517Q936 579 886 621T777 682Q724 700 655 705T436 710H319Q183 710 183 709Q186 706 348 484T511 259Q517 250 513 244L490 216Q466 188 420 134T330 27L149 -187Q149 -188 362 -188Q388 -188 436 -188T506 -189Q679 -189 778 -162T936 -43Q946 -27 959 6H999L913 -249L489 -250Q65 -250 62 -248Q56 -246 56 -239Q56 -234 118 -161Q186 -81 245 -11L428 206Q428 207 242 462L57 717L56 728Q56 744 61 748Z\\"/></g><g data-mml-node=\\"TeXAtom\\" data-mjx-texclass=\\"ORD\\" transform=\\"translate(6721.5, 0)\\"><g data-mml-node=\\"mi\\"><path data-c=\\"1D465\\" d=\\"M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z\\"/></g></g></g></g></svg>"`;
/*!
* © 2019 Atypon Systems LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { convertToMathML } from '../mathjax-mathml'
import { convertToSVG } from '../mathjax-svg'
describe('mathjax', () => {
it('generate inline svg', () => {
const tex = '\\sqrt{2}-z_{foo}=\\sum{x}'
const result = convertToSVG(tex, false)
expect(result).toMatchSnapshot()
})
it('generate display svg', () => {
const tex = '\\sqrt{2}-z_{foo}=\\sum{x}'
const result = convertToSVG(tex, true)
expect(result).toMatchSnapshot()
})
it('generate inline mathml', () => {
const tex = '\\sqrt{2}-z_{foo}=\\sum{x}'
const result = convertToMathML(tex, false)
expect(result).toMatchSnapshot()
})
it('generate display mathml', () => {
const tex = '\\sqrt{2}-z_{foo}=\\sum{x}'
const result = convertToMathML(tex, true)
expect(result).toMatchSnapshot()
})
})
......@@ -14,12 +14,20 @@
* limitations under the License.
*/
import purify from 'dompurify'
import purify, { Config } from 'dompurify'
type Sanitize = (dirty: string) => string
type Sanitize = (
dirty: string,
config?: Pick<Config, 'USE_PROFILES'>
) => DocumentFragment
export interface Purify {
sanitize: Sanitize
}
export const sanitize: Sanitize = (dirty) => purify.sanitize(dirty) // TODO: options
export const sanitize: Sanitize = (dirty, config) =>
purify.sanitize(dirty, {
RETURN_DOM_FRAGMENT: true,
RETURN_DOM_IMPORT: true,
...config,
})
/*!
* © 2019 Atypon Systems LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'mathjax-full/js/util/entities/all'
import { HTMLAdaptor } from 'mathjax-full/js/adaptors/HTMLAdaptor'
import { STATE } from 'mathjax-full/js/core/MathItem.js'
import { SerializedMmlVisitor } from 'mathjax-full/js/core/MmlTree/SerializedMmlVisitor'
import { HTMLDocument } from 'mathjax-full/js/handlers/html/HTMLDocument'
import { TeX } from 'mathjax-full/js/input/tex'
import { packages } from './mathjax-packages'
// TeX input
const InputJax = new TeX<HTMLElement, Text, Document>({
packages,
})
// @ts-ignore
const adaptor = new HTMLAdaptor<HTMLElement, Text, Document>(window)
const doc = new HTMLDocument<HTMLElement, Text, Document>(document, adaptor, {
InputJax,
})
const visitor = new SerializedMmlVisitor()
export const convertToMathML = (
tex: string,
display: boolean
): string | null => {
// TODO: set containerWidth and lineWidth for wrapping?
const item = doc.convert(tex, {
display,
em: 16,
ex: 8,
containerWidth: 1000000,
lineWidth: 1000000,
scale: 1,
end: STATE.CONVERT,
})
if (!item) {
return null
}
// TODO: use xml-serializer to avoid adding the namespace manually?
return visitor.visitTree(item)
}
/*!
* © 2019 Atypon Systems LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AllPackages } from 'mathjax-full/js/input/tex/AllPackages'
export const packages = AllPackages.filter(
(name) => name !== 'html' && name !== 'bussproofs'
)
/*!
* © 2019 Atypon Systems LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'mathjax-full/js/util/entities/all'
import { xmlSerializer } from '@manuscripts/manuscript-transform'
import { HTMLAdaptor } from 'mathjax-full/js/adaptors/HTMLAdaptor'
import { HTMLDocument } from 'mathjax-full/js/handlers/html/HTMLDocument'
import { TeX } from 'mathjax-full/js/input/tex'
import { SVG } from 'mathjax-full/js/output/svg'
import { packages } from './mathjax-packages'
// @ts-ignore for MinHTMLElement nodeValue compatibility
class ManuscriptsHTMLAdaptor extends HTMLAdaptor<HTMLElement, Text, Document> {
// CustomHTMLAdaptor subclasses HTMLAdaptor only to avoid setting an "xmlns" attribute
public setAttribute(
node: HTMLElement,
name: string,
value: string,
ns?: string
) {
if (name !== 'xmlns') {
ns ? node.setAttributeNS(ns, name, value) : node.setAttribute(name, value)
}
}
}
// TeX input
const InputJax = new TeX<HTMLElement, Text, Document>({
packages,
})
// SVG output
const OutputJax = new SVG<HTMLElement, Text, Document>({
fontCache: 'none', // avoid <defs> and <use xlink:href>
})
const adaptor = new ManuscriptsHTMLAdaptor(window)
const doc = new HTMLDocument<HTMLElement, Text, Document>(document, adaptor, {
InputJax,
OutputJax,
})
doc.addStyleSheet()
export const convertToSVG = (tex: string, display: boolean): string | null => {
// TODO: set containerWidth and lineWidth for wrapping?
const item = doc.convert(tex, {
display,
em: 16,
ex: 8,
containerWidth: 1000000,
lineWidth: 1000000,
scale: 1,
})
if (!item || !item.firstChild) {
return null
}
return xmlSerializer.serializeToString(item.firstChild)
}
......@@ -14,9 +14,8 @@
* limitations under the License.
*/
import { sanitize } from 'dompurify'
import { ViewerProps } from '../components/Viewer'
import { sanitize } from '../lib/dompurify'
import BlockView from './block_view'
import { createNodeView } from './creators'
......@@ -42,7 +41,9 @@ export class BibliographyElementBlockView<
this.element.removeAttribute('data-paragraph-style')
} else {
try {
this.element.innerHTML = sanitize(this.node.attrs.contents)
const fragment = sanitize(this.node.attrs.contents)
this.element.innerHTML = ''
this.element.appendChild(fragment)
} catch (e) {
console.error(e) // tslint:disable-line:no-console
// TODO: improve the UI for presenting offline/import errors
......
......@@ -21,10 +21,10 @@ import {
CitationItem,
ObjectTypes,
} from '@manuscripts/manuscripts-json-schema'
import { sanitize } from 'dompurify'
import React from 'react'
import { ViewerProps } from '../components/Viewer'
import { sanitize } from '../lib/dompurify'
import { BaseNodeView } from './base_node_view'
import { createNodeView } from './creators'
......@@ -115,7 +115,9 @@ export class CitationView<PropsType extends ViewerProps>
}
public updateContents = () => {
this.dom.innerHTML = sanitize(this.node.attrs.contents) // TODO: whitelist
const fragment = sanitize(this.node.attrs.contents) // TODO: whitelist
this.dom.innerHTML = ''
this.dom.appendChild(fragment)
}
public getCitation = () => {
......
......@@ -15,9 +15,9 @@
*/
import { ManuscriptNodeView } from '@manuscripts/manuscript-transform'
import { sanitize } from 'dompurify'
import { ViewerProps } from '../components/Viewer'
import { sanitize } from '../lib/dompurify'
import { BaseNodeView } from './base_node_view'
import { createNodeView } from './creators'
......@@ -38,15 +38,16 @@ export class EquationView<PropsType extends ViewerProps>
public updateContents = () => {
const { SVGStringRepresentation } = this.node.attrs
while (this.dom.hasChildNodes()) {
this.dom.removeChild(this.dom.firstChild as ChildNode)
}
if (SVGStringRepresentation) {
this.dom.innerHTML = sanitize(SVGStringRepresentation, {
const fragment = sanitize(SVGStringRepresentation, {
USE_PROFILES: { svg: true },
})
this.dom.appendChild(fragment)
} else {
while (this.dom.hasChildNodes()) {
this.dom.removeChild(this.dom.firstChild as ChildNode)
}
const placeholder = document.createElement('div')
placeholder.className = 'equation-placeholder'
placeholder.textContent = '<Equation>'
......
......@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { convertTeXToSVG } from '@manuscripts/manuscript-transform'
import { NodeSelection } from 'prosemirror-state'
import { EditorProps } from '../components/Editor'
......@@ -29,7 +30,6 @@ export class EquationEditableView extends EquationView<EditorProps> {
}
const { createEditor } = await import('../lib/codemirror')
const { convertToSVG } = await import('../lib/mathjax-svg')
const placeholder = 'Enter LaTeX equation, e.g. "a^2 = \\sqrt{b^2 + c^2}"'
......@@ -43,7 +43,10 @@ export class EquationEditableView extends EquationView<EditorProps> {
input.on('changes', async () => {
const TeXRepresentation = input.getValue()
const SVGStringRepresentation = convertToSVG(TeXRepresentation, true)
const SVGStringRepresentation = await convertTeXToSVG(
TeXRepresentation,
true
)
if (!SVGStringRepresentation) {
throw new Error('No SVG output from MathJax')
......
......@@ -15,9 +15,9 @@
*/
import { ManuscriptNodeView } from '@manuscripts/manuscript-transform'
import { sanitize } from 'dompurify'
import { ViewerProps } from '../components/Viewer'
import { sanitize } from '../lib/dompurify'
import { BaseNodeView } from './base_node_view'
import { createNodeView } from './creators'
......@@ -32,15 +32,16 @@ export class InlineEquationView<PropsType extends ViewerProps>
public updateContents = () => {
const { SVGRepresentation } = this.node.attrs
while (this.dom.hasChildNodes()) {
this.dom.removeChild(this.dom.firstChild as ChildNode)
}
if (SVGRepresentation) {
this.dom.innerHTML = sanitize(SVGRepresentation, {
const fragment = sanitize(SVGRepresentation, {
USE_PROFILES: { svg: true },
})
this.dom.appendChild(fragment)
} else {
while (this.dom.hasChildNodes()) {
this.dom.removeChild(this.dom.firstChild as ChildNode)
}
const placeholder = document.createElement('div')
placeholder.className = 'equation-placeholder'
placeholder.textContent = '<Equation>'
......
......@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { convertTeXToSVG } from '@manuscripts/manuscript-transform'
import { NodeSelection } from 'prosemirror-state'
import { EditorProps } from '../components/Editor'
......@@ -29,7 +30,6 @@ export class InlineEquationEditableView extends InlineEquationView<
}
const { createEditor } = await import('../lib/codemirror')
const { convertToSVG } = await import('../lib/mathjax-svg')
const placeholder = 'Enter LaTeX equation, e.g. "E=mc^2"'
......@@ -43,7 +43,7 @@ export class InlineEquationEditableView extends InlineEquationView<
input.on('changes', async () => {
const TeXRepresentation = input.getValue()
const SVGRepresentation = convertToSVG(TeXRepresentation, true)
const SVGRepresentation = await convertTeXToSVG(TeXRepresentation, true)
if (!SVGRepresentation) {
throw new Error('No SVG output from MathJax')
......
......@@ -14,9 +14,8 @@
* limitations under the License.
*/
import { sanitize } from 'dompurify'
import { ViewerProps } from '../components/Viewer'
import { sanitize } from '../lib/dompurify'
import BlockView from './block_view'
import { createNodeView } from './creators'
......@@ -31,7 +30,9 @@ export class KeywordsElementView<
public updateContents = () => {
try {
this.element.innerHTML = sanitize(this.node.attrs.contents)
const fragment = sanitize(this.node.attrs.contents)
this.element.innerHTML = ''
this.element.appendChild(fragment)
} catch (e) {
console.error(e) // tslint:disable-line:no-console
// TODO: improve the UI for presenting offline/import errors
......
......@@ -14,9 +14,8 @@
* limitations under the License.
*/
import { sanitize } from 'dompurify'
import { ViewerProps } from '../components/Viewer'
import { sanitize } from '../lib/dompurify'
import BlockView from './block_view'
import { createNodeView } from './creators'
......@@ -31,7 +30,9 @@ export class TOCElementView<PropsType extends ViewerProps> extends BlockView<
public updateContents = () => {
try {
this.element.innerHTML = sanitize(this.node.attrs.contents)
const fragment = sanitize(this.node.attrs.contents)
this.element.innerHTML = ''
this.element.appendChild(fragment)
} catch (e) {
console.error(e) // tslint:disable-line:no-console
// TODO: improve the UI for presenting offline/import errors
......
......@@ -1416,15 +1416,16 @@
citeproc "^2.4.48"
fontoxpath "^3.14.0"
"@manuscripts/manuscript-transform@^0.38.0":
version "0.38.0"
resolved "https://registry.npmjs.org/@manuscripts/manuscript-transform/-/manuscript-transform-0.38.0.tgz#7751be101666291b46afaab3614605d772276536"
integrity sha512-ZNjZymdx69Gk9WSJiB0Rt4mz9KfyrrsVUd/vdoF5cANkY19b2lM55Jm79nNdrkafeZNo0mJdlBe3fKeVaBkUIg==
"@manuscripts/manuscript-transform@^0.38.0", "@manuscripts/manuscript-transform@^0.38.2":
version "0.38.2"
resolved "https://registry.npmjs.org/@manuscripts/manuscript-transform/-/manuscript-transform-0.38.2.tgz#29d1b7c14b46eef7cee6f52b2186c010df81413c"
integrity sha512-zh7GjttCnOGwTOkVW5QoH+TUa8K+LnrxrisG6Y0YhYMiJwNE8hs/0zD6Js/0DQRZUzR6nVKSSaEwYiKbBAxfkg==
dependencies:
"@manuscripts/data" "^0.1.3"
"@manuscripts/manuscripts-json-schema" "^1.38.0"
debug "^4.1.1"
mime-types "^2.1.27"
mathjax-full "^3.1.2"
mime "^2.4.6"
prosemirror-model "^1.11.0"
uuid "^8.2.0"
w3c-xmlserializer "^2.0.0"
......@@ -3417,9 +3418,9 @@ commander@^2.19.0, commander@^2.5.0, commander@~2.20.0:
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
commander@^6.0.0:
version "6.1.0"
resolved "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz#f8d722b78103141006b66f4c7ba1e97315ba75bc"
integrity sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==
version "6.2.0"