diff --git a/src/render/index.js b/src/render/index.js index 7ab1b20..1b2fabb 100644 --- a/src/render/index.js +++ b/src/render/index.js @@ -18,6 +18,7 @@ const RESPONSE_TYPES = { mathml: 'application/mathml+xml', png: 'image/png', svg: 'image/svg+xml', + json: 'application/json', }; /** @@ -31,9 +32,6 @@ const defaultConfiguration = { require: require, load: ['adaptors/liteDOM', 'input/mml', 'input/tex-full', 'output/svg'] }, - options: { - enableAssistiveMml: false - } } const MJAX_SETTINGS = process.env.MJAX_SETTINGS ? JSON.parse(process.env.MJAX_SETTINGS) : defaultConfiguration; MathJax = MJAX_SETTINGS; @@ -82,12 +80,12 @@ const typeset = async (data) => { if (data.svg) { return MathJax.tex2svgPromise(data.math); } - throw new Error(`Supported output formats for ${data.format} input are: MathML, SVG`); + throw new Error(`Supported output formats for ${data.format} input are: MathML, SVG, AssistiveSVG`); case 'MathML': if (data.svg) { return MathJax.mathml2svgPromise(data.math); } - throw new Error(`Supported output formats for ${data.format} input are: SVG`); + throw new Error(`Supported output formats for ${data.format} input are: SVG, AssistiveSVG`); default: throw new Error(`Unsupported input format: ${data.format}`); } @@ -109,6 +107,21 @@ const typeset = async (data) => { } }; +/** + * Render math. + * + * @param {Typesetted} Result of a typesetted input. + * @returns {svg: string, assistiveML: string} + */ +const getSvgAndAssistiveML = (typesetted) => { + const svgAndAssistiveML = /()( { { const res = await typeset({ math, format, svg: true }); - const svg = MathJax.startup.adaptor.innerHTML(res); + const { svg } = getSvgAndAssistiveML(res); const { width, height } = event; const data = await svg2png(svg, { width, height }); @@ -146,11 +159,20 @@ exports.render = async (event) => { { const res = await typeset({ math, format, svg: true }); - const svg = MathJax.startup.adaptor.innerHTML(res); + const { svg } = getSvgAndAssistiveML(res); return { contentType: RESPONSE_TYPES.svg, data: svg }; } + case 'assistiveSVG': + { + const res = await typeset({ math, format, svg: true }); + + const { svg, assistiveML } = getSvgAndAssistiveML(res); + + return { contentType: RESPONSE_TYPES.json, data: JSON.stringify({svg, assistiveML}) }; + } + default: throw new Error(`Invalid output: ${event.output || ''}`); } diff --git a/test/app.js b/test/app.js index 1a52629..be1b812 100644 --- a/test/app.js +++ b/test/app.js @@ -77,7 +77,22 @@ describe('GET /render', function () { .expect((response) => { const data = response.body.toString(); - expect(data).to.be.a('string').that.contains(''); + expect(data).to.be.a('string').that.match(//); + }); + })); + + Object.keys(TEST_INPUTS).forEach((alias) => it(`should render ${alias} as AssistiveSVG`, function () { + const search = Object.assign({ output: 'assistiveSVG' }, TEST_INPUTS[alias]); + const url = `/render?${querystring.stringify(search)}`; + + return testApp + .get(url) + .expect(200) + .expect('Content-Type', 'application/json; charset=utf-8') + .expect((response) => { + expect(response.body).to.be.an('object').with.keys('svg', 'assistiveML'); + expect(response.body.svg).to.be.a('string').that.match(//); + expect(response.body.assistiveML).to.be.a('string').that.match(//); }); })); @@ -143,7 +158,23 @@ describe('POST /render', function () { .expect((response) => { const data = response.body.toString(); - expect(data).to.be.a('string').that.contains(''); + expect(data).to.be.a('string').that.match(//); + }); + })); + + Object.keys(TEST_INPUTS).forEach((alias) => it(`should render ${alias} as SVG`, function () { + const body = Object.assign({ output: 'assistiveSVG' }, TEST_INPUTS[alias]); + + return testApp + .post('/render') + .set('Content-Type', 'application/json') + .send(body) + .expect(200) + .expect('Content-Type', 'application/json; charset=utf-8') + .expect((response) => { + expect(response.body).to.be.an('object').with.keys('svg', 'assistiveML'); + expect(response.body.svg).to.be.a('string').that.match(//); + expect(response.body.assistiveML).to.be.a('string').that.match(//); }); })); diff --git a/test/render/index.js b/test/render/index.js index e0616e4..f5e62dc 100644 --- a/test/render/index.js +++ b/test/render/index.js @@ -63,7 +63,20 @@ describe('index#render', function () { expect(actual).to.be.an('object').with.keys('contentType', 'data'); expect(actual.contentType).to.be.a('string').that.equals('image/svg+xml'); - expect(actual.data).to.be.a('string').that.contains(''); + expect(actual.data).to.be.a('string').that.match(//); + })); + + Object.keys(TEST_INPUTS).forEach((alias) => it(`should render ${alias} as AssistiveSVG`, async function () { + const event = Object.assign({ output: 'assistiveSVG' }, TEST_INPUTS[alias]); + const actual = await render(event); + + expect(actual).to.be.an('object').with.keys('contentType', 'data'); + expect(actual.contentType).to.be.a('string').that.equals('application/json'); + + const actualData = JSON.parse(actual.data); + expect(actualData).to.be.an('object').with.keys('svg', 'assistiveML'); + expect(actualData.svg).to.be.a('string').that.match(//); + expect(actualData.assistiveML).to.be.a('string').that.match(//); })); it('should throw with invalid input type', async function () {