Heads up: This instance will undergo maintenance on Saturday at 12:00 CEST. The downtime is estimated to last 2 hours maximum

Commit 0ae4a3a3 authored by Yannis Barlas's avatar Yannis Barlas

basic math implementation

parent 6bf65b94
import { InlineNode } from 'substance'
class Math extends InlineNode {}
Math.define({
type: 'math',
source: { type: 'string', default: '' },
language: { type: 'string', default: 'asciimath' }
})
export default Math
import { InsertInlineNodeCommand, documentHelpers } from 'substance'
class MathCommand extends InsertInlineNodeCommand {
// constructor () {
// super({
// name: 'math',
// nodeType: 'math'
// })
// }
createNodeData (tx, args) {
// Create math node with source set to current selection
console.log(tx.document)
const text = documentHelpers.getTextForSelection(
tx._document,
args.selection
)
return {
type: 'math',
source: text
}
}
}
export default MathCommand
import { Component } from 'substance'
import math from './mathRenderer'
class MathComponent extends Component {
render ($$) {
const node = this.props.node
const el = $$('span')
.addClass('sc-math sm-' + node.language)
.ref('math')
if (this.props.isolatedNodeState) {
el.addClass('sm-'+this.props.isolatedNodeState)
}
try {
el.append(
$$('span').addClass('se-rendered-math').html(
math.render(node.source, node.language, node.display)
)
)
const blockerEl = $$('div').addClass('se-blocker')
el.append(blockerEl)
} catch (error) {
el.addClass('sm-error')
.text(error.message)
}
return el
}
}
export default MathComponent
export default {
type: 'math',
tagName: 'span',
matchElement: function (el) {
return el.is('[data-math]')
},
import: function (el, node) {
node.language = el.attr('data-math')
node.source = el.text()
},
export: function (node, el) {
el.attr('data-math', node.language)
el.text(node.source)
}
}
import InlineNodeMacro from '../../ui/InlineNodeMacro'
class MathMacro extends InlineNodeMacro {
get regex () {
// Allow for both AsciiMath pipe delimeters (|) and
// TeX dollar ($) delimiters. In both cases the start and end delimiters
// must be followed/preceded by a non-space character. For TeX, the first
// dollar must not be followed by a digit.
// 2 5
return /(\|(\S|(\S.*\S))\|)|(\$(([^0-9\s])|([^0-9\s].*\S))\$)/
}
createNodeData (match) {
var source, language, display
if (match[2]) {
source = match[2]
language = 'asciimath'
} else if (match[5]) {
source = match[5]
language = 'tex'
} else {
throw new Error('No match!')
}
return {
type: 'math',
source: source,
language: language,
display: display
}
}
}
export default MathMacro
import { Tool } from 'substance'
import Math from './Math'
import MathHTMLConverter from './MathHTMLConverter'
import MathComponent from './MathComponent'
import MathCommand from './MathCommand'
// import MathMacro from './MathMacro'
export default {
name: 'math',
configure: function (config) {
config.addNode(Math)
config.addConverter('html', MathHTMLConverter)
config.addComponent('math', MathComponent)
config.addCommand('math', MathCommand, {
nodeType: 'math'
})
// config.addMacro(new MathMacro())
config.addTool('math', Tool)
// TODO: Choose/create a better math icon (this is a random temporary)
config.addIcon('math', { 'fontawesome': 'fa-tree' })
config.addLabel('math', {
en: 'Math'
})
}
}
// import { Tool, map } from 'substance'
//
// /**
// * A tool for editing `Math` nodes
// *
// * Updates the node's `source` property on the `input` event to allow for live updating.
// *
// * @class MathTool (name)
// */
// class MathTool extends Tool {
//
// render ($$) {
// var node = this.props.node
// var language = node ? node.language : 'asciimath'
// var display = node ? node.display : 'inline'
// return super.render.call(this, $$)
// .addClass('sc-math-tool')
// .append(
// $$('div')
// .ref('details')
// .addClass('se-details')
// .append(
// $$('input')
// .ref('source')
// .addClass('se-source')
// .attr({
// placeholder: 'Math markup expression',
// title: 'Math markup'
// })
// .val(node ? node.source : null)
// .on('input', function (event) {
// var session = this.context.documentSession
// session.transaction(function (tx) {
// tx.set([node.id, 'source'], event.target.value)
// })
// }.bind(this)),
// $$('select')
// .ref('language')
// .addClass('se-language')
// .append(map([['asciimath', 'AM'], ['tex', 'TeX']], function (item) {
// var option = $$('option')
// .val(item[0])
// .html(item[1])
// if (item[0] === language) option.attr('selected', true)
// return option
// }))
// .on('change', function (event) {
// var session = this.context.documentSession
// session.transaction(function (tx) {
// tx.set([node.id, 'language'], event.target.value)
// })
// }.bind(this)),
// $$('select')
// .ref('display')
// .addClass('se-display')
// .append(map([['inline', 'Inline'], ['block', 'Block']], function (item) {
// var option = $$('option')
// .val(item[0])
// .html(item[1])
// if (item[0] === display) option.attr('selected', true)
// return option
// }))
// .on('change', function (event) {
// var session = this.context.documentSession
// session.transaction(function (tx) {
// tx.set([node.id, 'display'], event.target.value)
// })
// }.bind(this))
// )
// )
// }
//
// shouldRerender (props) {
// // Do not re-render if the node has not changed.
// // This prevents the input box being updated during live editing
// return (this.props.node === null) || (props.node !== this.props.node)
// }
// }
//
// export default MathTool
/**
CSS import of KaTeX CSS (which imports fonts too)
We be served from the `build` directory. See `make.js`.
*/
@import url('~/katex/dist/katex.min.scss');
.sc-math {
position: relative;
display: inline-block;
}
.sc-math ::-moz-selection { background: none; }
.sc-math ::selection { background: none; }
.sc-math .se-rendered-math {
display: inline-block;
}
.sc-math .katex {
display: inline-block;
}
.sc-math .katex-mathml {
display: none;
}
.sc-math > .se-blocker {
position: absolute;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
}
.sc-math.sm-selected > .se-blocker,
.sc-math.sm-co-selected > .se-blocker {
background: var(--stencila-green-transparent);
}
\ No newline at end of file
This diff is collapsed.
/**
* A module for rendering of math
*
* - uses KaTeX for rendering
*
* - uses `ASCIIMathTeXImg.js` for converting ASCIIMath to TeX
*
* - in the future may use MathJax as a fallback to any things
* that KaTex does not handle (see http://www.intmath.com/blog/mathematics/katex-with-asciimathml-input-and-mathjax-fallback-9456)
*
* @module utilities/math
*/
import katex from 'katex'
import am from './asciimath'
/**
* Translate between math markup languages
*
* @param {string} markup The markup
* @param {string} source The source language ( default 'asciimath')
* @param {string} target The target language ( default 'tex')
* @return {string} Markup translated to the target language
*/
var translate = function (markup, source, target) {
source = source || 'asciimath'
target = target || 'tex'
if (target === 'tex') {
if (source === 'tex' || source === 'latex') {
return markup
} else if (source === 'am' || source === 'asciimath') {
return am.toTeX(markup)
} else {
throw Error('Unhandled conversion from {' + source + '} to {' + target + '}')
}
} else {
throw Error('Unhandled target language {' + target + '}')
}
}
/**
* Render math markup into HTML
*
* @param {string} markup The source markup
* @param {string} language The language ('tex' (default) or 'asciimath') of the source
* @param {string} display The display mode ('inline' (default) or 'block')
* @return {string} Rendered math HTML
*/
var render = function (markup, language, display) {
language = language || 'tex'
display = display || 'inline'
var tex = translate(markup, language, 'tex')
return katex.renderToString(tex, {
displayMode: display === 'block'
})
}
export default {
translate: translate,
render: render
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment