├── .gitignore ├── dist ├── polyfill.d.ts ├── math.d.ts ├── mi.d.ts ├── mn.d.ts ├── mtext.d.ts ├── none.d.ts ├── merror.d.ts ├── mphantom.d.ts ├── mprescripts.d.ts ├── mrow.d.ts ├── msub.d.ts ├── msup.d.ts ├── mstyle.d.ts ├── ms.d.ts ├── msubsup.d.ts ├── mmultiscripts.d.ts ├── mtable-base.d.ts ├── styles │ ├── common-styles.d.ts │ └── common-styles.js ├── mtd.d.ts ├── mroot.d.ts ├── msqrt.d.ts ├── mglyph.d.ts ├── mlabeledtr.d.ts ├── mover.d.ts ├── mspace.d.ts ├── mpadded.d.ts ├── mtr.d.ts ├── munder.d.ts ├── menclose.d.ts ├── munderover.d.ts ├── mo.d.ts ├── mfenced.d.ts ├── mfrac.d.ts ├── mtable.d.ts ├── mathml-element.d.ts ├── all.d.ts ├── all.js ├── none.js ├── mphantom.js ├── mprescripts.js ├── mn.js ├── mi.js ├── mtext.js ├── bundled │ └── mathml.polyfill.js ├── merror.js ├── math.js ├── mstyle.js ├── mlabeledtr.js ├── mathml-element.js ├── mtd.js ├── ms.js ├── mspace.js ├── mtr.js ├── mglyph.js ├── mtable-base.js ├── msup.js ├── polyfill.js ├── msub.js ├── munder.js ├── msqrt.js ├── mover.js ├── mroot.js ├── mpadded.js ├── mrow.js ├── msubsup.js ├── munderover.js ├── mfenced.js ├── mo.js ├── mfrac.js ├── mtable.js ├── mmultiscripts.js └── menclose.js ├── src ├── none.ts ├── mprescripts.ts ├── mphantom.ts ├── mn.ts ├── mi.ts ├── mtext.ts ├── mstyle.ts ├── merror.ts ├── math.ts ├── mspace.ts ├── mlabeledtr.ts ├── mathml-element.ts ├── ms.ts ├── all.ts ├── mglyph.ts ├── styles │ └── common-styles.ts ├── mtd.ts ├── mtable-base.ts ├── munder.ts ├── mtr.ts ├── mover.ts ├── msup.ts ├── mpadded.ts ├── msub.ts ├── msqrt.ts ├── mroot.ts ├── polyfill.ts ├── mrow.ts ├── msubsup.ts ├── munderover.ts ├── mfenced.ts ├── mtable.ts ├── mo.ts ├── mmultiscripts.ts ├── mfrac.ts └── menclose.ts ├── tsconfig.json ├── rollup.config.js ├── LICENSE ├── package.json ├── tslint.json ├── examples ├── using-polyfill.html └── pythagorean-theorem.html └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | demo -------------------------------------------------------------------------------- /dist/polyfill.d.ts: -------------------------------------------------------------------------------- 1 | export declare function polyfill(mathNode: Element): Element; 2 | -------------------------------------------------------------------------------- /dist/math.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathElement extends MathMLElement { 3 | render(): TemplateResult; 4 | } 5 | -------------------------------------------------------------------------------- /dist/mi.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathIElement extends MathMLElement { 3 | render(): TemplateResult; 4 | } 5 | -------------------------------------------------------------------------------- /dist/mn.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathNElement extends MathMLElement { 3 | render(): TemplateResult; 4 | } 5 | -------------------------------------------------------------------------------- /dist/mtext.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathTextElement extends MathMLElement { 3 | render(): TemplateResult; 4 | } 5 | -------------------------------------------------------------------------------- /dist/none.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathNoneElement extends MathMLElement { 3 | render(): TemplateResult; 4 | } 5 | -------------------------------------------------------------------------------- /dist/merror.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathErrorElement extends MathMLElement { 3 | render(): TemplateResult; 4 | } 5 | -------------------------------------------------------------------------------- /dist/mphantom.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathPhantomElement extends MathMLElement { 3 | render(): TemplateResult; 4 | } 5 | -------------------------------------------------------------------------------- /dist/mprescripts.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathPreScriptsElement extends MathMLElement { 3 | render(): TemplateResult; 4 | } 5 | -------------------------------------------------------------------------------- /dist/mrow.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathRowElement extends MathMLElement { 3 | render(): TemplateResult; 4 | private onSlotChange; 5 | } 6 | -------------------------------------------------------------------------------- /dist/msub.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathSubElement extends MathMLElement { 3 | render(): TemplateResult; 4 | refreshSlot(): void; 5 | } 6 | -------------------------------------------------------------------------------- /dist/msup.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathSupElement extends MathMLElement { 3 | render(): TemplateResult; 4 | refreshSlot(): void; 5 | } 6 | -------------------------------------------------------------------------------- /dist/mstyle.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathStyleElement extends MathMLElement { 3 | displaystyle?: string; 4 | render(): TemplateResult; 5 | } 6 | -------------------------------------------------------------------------------- /dist/ms.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathSElement extends MathMLElement { 3 | lquote?: string; 4 | rquote?: string; 5 | render(): TemplateResult; 6 | } 7 | -------------------------------------------------------------------------------- /dist/msubsup.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathSubSupElement extends MathMLElement { 3 | private pendingLayout; 4 | render(): TemplateResult; 5 | refreshSlot(): void; 6 | } 7 | -------------------------------------------------------------------------------- /dist/mmultiscripts.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathMultiScriptsElement extends MathMLElement { 3 | private pendingLayout; 4 | render(): TemplateResult; 5 | private refreshSlot; 6 | } 7 | -------------------------------------------------------------------------------- /dist/mtable-base.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, MathRowAlignType } from './mathml-element.js'; 2 | export declare class MathTableBaseElement extends MathMLElement { 3 | columnalign?: string; 4 | rowalign?: MathRowAlignType; 5 | protected updateAlignment(): void; 6 | } 7 | -------------------------------------------------------------------------------- /dist/styles/common-styles.d.ts: -------------------------------------------------------------------------------- 1 | import { TemplateResult } from '../mathml-element'; 2 | export declare const AllFlex: TemplateResult; 3 | export declare const VertFlex: TemplateResult; 4 | export declare const HorizFlex: TemplateResult; 5 | export declare const HorizCenterFlex: TemplateResult; 6 | -------------------------------------------------------------------------------- /dist/mtd.d.ts: -------------------------------------------------------------------------------- 1 | import { PropertyValues, TemplateResult } from './mathml-element.js'; 2 | import { MathTableBaseElement } from './mtable-base.js'; 3 | export declare class MathTDElement extends MathTableBaseElement { 4 | render(): TemplateResult; 5 | updated(propVals: PropertyValues): void; 6 | } 7 | -------------------------------------------------------------------------------- /dist/mroot.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, TemplateResult } from './mathml-element.js'; 2 | export declare class MathRootElement extends MathMLElement { 3 | render(): TemplateResult; 4 | updated(propVals: PropertyValues): void; 5 | private onSlotCange; 6 | private drawRoot; 7 | } 8 | -------------------------------------------------------------------------------- /dist/msqrt.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, TemplateResult } from './mathml-element.js'; 2 | export declare class MathSqrtElement extends MathMLElement { 3 | render(): TemplateResult; 4 | updated(propVals: PropertyValues): void; 5 | private onSlotCange; 6 | private drawRoot; 7 | } 8 | -------------------------------------------------------------------------------- /dist/mglyph.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult } from './mathml-element.js'; 2 | export declare class MathGlyphElement extends MathMLElement { 3 | src?: string; 4 | width: string; 5 | height: string; 6 | valign: string; 7 | alt: string; 8 | render(): TemplateResult; 9 | } 10 | -------------------------------------------------------------------------------- /dist/mlabeledtr.d.ts: -------------------------------------------------------------------------------- 1 | import { TemplateResult, PropertyValues } from './mathml-element.js'; 2 | import { MathTableBaseElement } from './mtable-base.js'; 3 | export declare class MathLabeledTRElement extends MathTableBaseElement { 4 | render(): TemplateResult; 5 | updated(propVals: PropertyValues): void; 6 | } 7 | -------------------------------------------------------------------------------- /dist/mover.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, TemplateResult, MathAlignType } from './mathml-element.js'; 2 | export declare class MathOverElement extends MathMLElement { 3 | accent: boolean; 4 | align: MathAlignType; 5 | render(): TemplateResult; 6 | updated(propVals: PropertyValues): void; 7 | } 8 | -------------------------------------------------------------------------------- /dist/mspace.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, TemplateResult } from './mathml-element.js'; 2 | export declare class MathSpaceElement extends MathMLElement { 3 | width: string; 4 | height: string; 5 | depth: string; 6 | render(): TemplateResult; 7 | updated(propVals: PropertyValues): void; 8 | } 9 | -------------------------------------------------------------------------------- /dist/mpadded.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, TemplateResult } from './mathml-element.js'; 2 | export declare class MathPaddedElement extends MathMLElement { 3 | height?: string; 4 | width?: string; 5 | render(): TemplateResult; 6 | updated(propVals: PropertyValues): void; 7 | private refresh; 8 | } 9 | -------------------------------------------------------------------------------- /dist/mtr.d.ts: -------------------------------------------------------------------------------- 1 | import { PropertyValues, TemplateResult } from './mathml-element.js'; 2 | import { MathTableBaseElement } from './mtable-base.js'; 3 | export declare class MathTRElement extends MathTableBaseElement { 4 | render(): TemplateResult; 5 | updated(propVals: PropertyValues): void; 6 | private refreshSlot; 7 | } 8 | -------------------------------------------------------------------------------- /dist/munder.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, TemplateResult, MathAlignType } from './mathml-element.js'; 2 | export declare class MathUnderElement extends MathMLElement { 3 | accentunder: boolean; 4 | align: MathAlignType; 5 | render(): TemplateResult; 6 | updated(propVals: PropertyValues): void; 7 | } 8 | -------------------------------------------------------------------------------- /dist/menclose.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult, PropertyValues } from './mathml-element.js'; 2 | export declare class MathEncloseElement extends MathMLElement { 3 | notation: string; 4 | render(): TemplateResult; 5 | updated(propVals: PropertyValues): void; 6 | private refresh; 7 | private adjustPadding; 8 | private redraw; 9 | } 10 | -------------------------------------------------------------------------------- /dist/munderover.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, TemplateResult, MathAlignType } from './mathml-element.js'; 2 | export declare class MathUnderOverElement extends MathMLElement { 3 | accent: boolean; 4 | accentunder: boolean; 5 | align: MathAlignType; 6 | render(): TemplateResult; 7 | updated(propVals: PropertyValues): void; 8 | private refreshSlot; 9 | } 10 | -------------------------------------------------------------------------------- /src/none.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | 3 | @customElement('math-none') 4 | export class MathNoneElement extends MathMLElement { 5 | render(): TemplateResult { 6 | return html` 7 | 14 | `; 15 | } 16 | } -------------------------------------------------------------------------------- /src/mprescripts.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | 3 | @customElement('math-prescripts') 4 | export class MathPreScriptsElement extends MathMLElement { 5 | render(): TemplateResult { 6 | return html` 7 | 14 | `; 15 | } 16 | } -------------------------------------------------------------------------------- /src/mphantom.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | 3 | @customElement('math-phantom') 4 | export class MathPhantomElement extends MathMLElement { 5 | render(): TemplateResult { 6 | return html` 7 | 13 | 14 | `; 15 | } 16 | } -------------------------------------------------------------------------------- /dist/mo.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult, PropertyValues } from './mathml-element.js'; 2 | export declare type MathOperatorForm = 'prefix' | 'infix' | 'postfix'; 3 | export declare class MathOElement extends MathMLElement { 4 | form?: MathOperatorForm; 5 | stretchy?: string; 6 | private formStyle; 7 | render(): TemplateResult; 8 | updated(propVals: PropertyValues): void; 9 | private onSlotChange; 10 | } 11 | -------------------------------------------------------------------------------- /dist/mfenced.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult, PropertyValues } from './mathml-element.js'; 2 | import './mo.js'; 3 | export declare class MathFencedElement extends MathMLElement { 4 | close: string; 5 | open: string; 6 | separators: string; 7 | render(): TemplateResult; 8 | updated(propVals: PropertyValues): void; 9 | private isStretchyString; 10 | private nextSeparator; 11 | private refreshSlot; 12 | } 13 | -------------------------------------------------------------------------------- /src/mn.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | 3 | @customElement('math-n') 4 | export class MathNElement extends MathMLElement { 5 | render(): TemplateResult { 6 | return html` 7 | 14 | 15 | `; 16 | } 17 | } -------------------------------------------------------------------------------- /dist/mfrac.d.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, TemplateResult, MathAlignType, PropertyValues } from './mathml-element.js'; 2 | export declare class MathFracElement extends MathMLElement { 3 | bevelled: boolean; 4 | numalign: MathAlignType; 5 | denomalign: MathAlignType; 6 | linethickness?: string; 7 | render(): TemplateResult; 8 | updated(propVals: PropertyValues): void; 9 | private refreshSlot; 10 | private updateBevlled; 11 | private drawBevelledDivider; 12 | } 13 | -------------------------------------------------------------------------------- /src/mi.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | 3 | @customElement('math-i') 4 | export class MathIElement extends MathMLElement { 5 | render(): TemplateResult { 6 | return html` 7 | 15 | 16 | `; 17 | } 18 | } -------------------------------------------------------------------------------- /src/mtext.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | 3 | @customElement('math-text') 4 | export class MathTextElement extends MathMLElement { 5 | render(): TemplateResult { 6 | return html` 7 | 15 | 16 | `; 17 | } 18 | } -------------------------------------------------------------------------------- /dist/mtable.d.ts: -------------------------------------------------------------------------------- 1 | import { PropertyValues, TemplateResult, MathBorderType } from './mathml-element.js'; 2 | import { MathTableBaseElement } from './mtable-base.js'; 3 | export declare class MathTableElement extends MathTableBaseElement { 4 | columnlines?: MathBorderType; 5 | rowlines?: MathBorderType; 6 | frame?: MathBorderType; 7 | columnspacing: string; 8 | rowspacing: string; 9 | framespacing: string; 10 | width?: string; 11 | constructor(); 12 | render(): TemplateResult; 13 | updated(propVals: PropertyValues): void; 14 | } 15 | -------------------------------------------------------------------------------- /src/mstyle.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement, property } from './mathml-element.js'; 2 | 3 | @customElement('math-style') 4 | export class MathStyleElement extends MathMLElement { 5 | @property({ type: String }) displaystyle?: string; 6 | 7 | render(): TemplateResult { 8 | return html` 9 | 16 | 17 | `; 18 | } 19 | } -------------------------------------------------------------------------------- /dist/mathml-element.d.ts: -------------------------------------------------------------------------------- 1 | import { LitElement, PropertyValues } from 'lit-element'; 2 | export { html, PropertyValues, TemplateResult, property, customElement } from 'lit-element'; 3 | export declare class MathMLElement extends LitElement { 4 | mathbackground?: string; 5 | mathcolor?: string; 6 | updated(propVals: PropertyValues): void; 7 | } 8 | export declare type MathAlignType = 'left' | 'center' | 'right'; 9 | export declare type MathColumnAlignType = 'left' | 'center' | 'right'; 10 | export declare type MathRowAlignType = 'axis' | 'baseline' | 'bottom' | 'center' | 'top'; 11 | export declare type MathBorderType = 'none' | 'solid' | 'dashed'; 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "lib": [ 7 | "es2017", 8 | "dom" 9 | ], 10 | "declaration": true, 11 | "outDir": "./dist", 12 | "baseUrl": ".", 13 | "strict": true, 14 | "strictNullChecks": true, 15 | "noImplicitAny": true, 16 | "noUnusedLocals": true, 17 | "noUnusedParameters": true, 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "experimentalDecorators": true, 21 | "emitDecoratorMetadata": true 22 | }, 23 | "include": [ 24 | "src/**/*.ts" 25 | ] 26 | } -------------------------------------------------------------------------------- /src/merror.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | 3 | @customElement('math-error') 4 | export class MathErrorElement extends MathMLElement { 5 | render(): TemplateResult { 6 | return html` 7 | 19 | 20 | `; 21 | } 22 | } -------------------------------------------------------------------------------- /src/math.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | 3 | @customElement('math-ml') 4 | export class MathElement extends MathMLElement { 5 | render(): TemplateResult { 6 | return html` 7 | 23 | 24 | `; 25 | } 26 | } -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import minify from 'rollup-plugin-babel-minify'; 2 | import resolve from 'rollup-plugin-node-resolve'; 3 | 4 | function onwarn(warning) { 5 | if (warning.code === 'THIS_IS_UNDEFINED') 6 | return; 7 | console.error(warning.message); 8 | } 9 | 10 | export default [ 11 | { 12 | input: 'dist/all.js', 13 | output: { 14 | file: `dist/bundled/mathml.min.js`, 15 | format: 'iife', 16 | name: 'mathml' 17 | }, 18 | onwarn, 19 | plugins: [resolve(), minify({ comments: false })] 20 | }, 21 | { 22 | input: 'dist/polyfill.js', 23 | output: { 24 | file: `dist/bundled/mathml.polyfill.js`, 25 | format: 'iife', 26 | name: 'mathmlPolyfill' 27 | }, 28 | onwarn, 29 | plugins: [minify({ comments: false })] 30 | } 31 | ]; -------------------------------------------------------------------------------- /src/mspace.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, html, TemplateResult, customElement, property } from './mathml-element.js'; 2 | 3 | @customElement('math-space') 4 | export class MathSpaceElement extends MathMLElement { 5 | @property({ type: String }) width = '0em'; 6 | @property({ type: String }) height = '0ex'; 7 | @property({ type: String }) depth = '0ex'; 8 | 9 | render(): TemplateResult { 10 | return html` 11 | 18 | `; 19 | } 20 | 21 | updated(propVals: PropertyValues) { 22 | super.updated(propVals); 23 | this.style.width = this.width; 24 | this.style.height = this.height; 25 | this.style.marginBottom = this.depth; 26 | } 27 | } -------------------------------------------------------------------------------- /src/mlabeledtr.ts: -------------------------------------------------------------------------------- 1 | import { html, TemplateResult, customElement, PropertyValues } from './mathml-element.js'; 2 | import { MathTableBaseElement } from './mtable-base.js'; 3 | 4 | @customElement('math-labeledtr') 5 | export class MathLabeledTRElement extends MathTableBaseElement { 6 | render(): TemplateResult { 7 | return html` 8 | 21 | 22 | `; 23 | } 24 | 25 | updated(propVals: PropertyValues) { 26 | super.updated(propVals); 27 | this.updateAlignment(); 28 | } 29 | } -------------------------------------------------------------------------------- /src/mathml-element.ts: -------------------------------------------------------------------------------- 1 | import { LitElement, PropertyValues, property } from 'lit-element'; 2 | export { html, PropertyValues, TemplateResult, property, customElement } from 'lit-element'; 3 | 4 | export class MathMLElement extends LitElement { 5 | @property({ type: String }) mathbackground?: string; 6 | @property({ type: String }) mathcolor?: string; 7 | 8 | updated(propVals: PropertyValues) { 9 | if (propVals.has('mathcolor')) { 10 | this.style.setProperty('--math-color', this.mathcolor || null); 11 | } 12 | if (propVals.has('mathbackground')) { 13 | this.style.setProperty('--math-background', this.mathbackground || null); 14 | } 15 | } 16 | } 17 | 18 | export declare type MathAlignType = 'left' | 'center' | 'right'; 19 | export declare type MathColumnAlignType = 'left' | 'center' | 'right'; 20 | export declare type MathRowAlignType = 'axis' | 'baseline' | 'bottom' | 'center' | 'top'; 21 | export declare type MathBorderType = 'none' | 'solid' | 'dashed'; -------------------------------------------------------------------------------- /src/ms.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement, property } from './mathml-element.js'; 2 | 3 | @customElement('math-s') 4 | export class MathSElement extends MathMLElement { 5 | @property({ type: String, reflect: true }) lquote?: string; 6 | @property({ type: String, reflect: true }) rquote?: string; 7 | 8 | render(): TemplateResult { 9 | return html` 10 | 31 | 32 | `; 33 | } 34 | } -------------------------------------------------------------------------------- /src/all.ts: -------------------------------------------------------------------------------- 1 | export * from './math.js'; 2 | export * from './mrow.js'; 3 | export * from './mn.js'; 4 | export * from './mo.js'; 5 | export * from './mi.js'; 6 | export * from './ms.js'; 7 | export * from './mspace.js'; 8 | export * from './mtext.js'; 9 | export * from './mglyph.js'; 10 | export * from './mtd.js'; 11 | export * from './mtr.js'; 12 | export * from './mlabeledtr.js'; 13 | export * from './mtable.js'; 14 | export * from './msup.js'; 15 | export * from './msub.js'; 16 | export * from './msubsup.js'; 17 | export * from './mmultiscripts.js'; 18 | export * from './mprescripts.js'; 19 | export * from './none.js'; 20 | export * from './mover.js'; 21 | export * from './munder.js'; 22 | export * from './munderover.js'; 23 | export * from './msqrt.js'; 24 | export * from './mroot.js'; 25 | export * from './mfrac.js'; 26 | export * from './menclose.js'; 27 | export * from './mphantom.js'; 28 | export * from './merror.js'; 29 | export * from './mfenced.js'; 30 | export * from './mpadded.js'; 31 | export * from './mstyle.js'; -------------------------------------------------------------------------------- /dist/all.d.ts: -------------------------------------------------------------------------------- 1 | export * from './math.js'; 2 | export * from './mrow.js'; 3 | export * from './mn.js'; 4 | export * from './mo.js'; 5 | export * from './mi.js'; 6 | export * from './ms.js'; 7 | export * from './mspace.js'; 8 | export * from './mtext.js'; 9 | export * from './mglyph.js'; 10 | export * from './mtd.js'; 11 | export * from './mtr.js'; 12 | export * from './mlabeledtr.js'; 13 | export * from './mtable.js'; 14 | export * from './msup.js'; 15 | export * from './msub.js'; 16 | export * from './msubsup.js'; 17 | export * from './mmultiscripts.js'; 18 | export * from './mprescripts.js'; 19 | export * from './none.js'; 20 | export * from './mover.js'; 21 | export * from './munder.js'; 22 | export * from './munderover.js'; 23 | export * from './msqrt.js'; 24 | export * from './mroot.js'; 25 | export * from './mfrac.js'; 26 | export * from './menclose.js'; 27 | export * from './mphantom.js'; 28 | export * from './merror.js'; 29 | export * from './mfenced.js'; 30 | export * from './mpadded.js'; 31 | export * from './mstyle.js'; 32 | -------------------------------------------------------------------------------- /dist/all.js: -------------------------------------------------------------------------------- 1 | export * from './math.js'; 2 | export * from './mrow.js'; 3 | export * from './mn.js'; 4 | export * from './mo.js'; 5 | export * from './mi.js'; 6 | export * from './ms.js'; 7 | export * from './mspace.js'; 8 | export * from './mtext.js'; 9 | export * from './mglyph.js'; 10 | export * from './mtd.js'; 11 | export * from './mtr.js'; 12 | export * from './mlabeledtr.js'; 13 | export * from './mtable.js'; 14 | export * from './msup.js'; 15 | export * from './msub.js'; 16 | export * from './msubsup.js'; 17 | export * from './mmultiscripts.js'; 18 | export * from './mprescripts.js'; 19 | export * from './none.js'; 20 | export * from './mover.js'; 21 | export * from './munder.js'; 22 | export * from './munderover.js'; 23 | export * from './msqrt.js'; 24 | export * from './mroot.js'; 25 | export * from './mfrac.js'; 26 | export * from './menclose.js'; 27 | export * from './mphantom.js'; 28 | export * from './merror.js'; 29 | export * from './mfenced.js'; 30 | export * from './mpadded.js'; 31 | export * from './mstyle.js'; 32 | -------------------------------------------------------------------------------- /dist/none.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | let MathNoneElement = class MathNoneElement extends MathMLElement { 9 | render() { 10 | return html ` 11 | 18 | `; 19 | } 20 | }; 21 | MathNoneElement = __decorate([ 22 | customElement('math-none') 23 | ], MathNoneElement); 24 | export { MathNoneElement }; 25 | -------------------------------------------------------------------------------- /src/mglyph.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement, property } from './mathml-element.js'; 2 | 3 | @customElement('math-glyph') 4 | export class MathGlyphElement extends MathMLElement { 5 | @property({ type: String }) src?: string; 6 | @property({ type: String }) width = 'auto'; 7 | @property({ type: String }) height = 'auto'; 8 | @property({ type: String }) valign = 'auto'; 9 | @property({ type: String }) alt = ''; 10 | 11 | render(): TemplateResult { 12 | const v = this.valign ? (this.valign.indexOf('-') === 0 ? this.valign.substring(1) : `-${this.valign}`) : '0'; 13 | const style = this.src ? `width: ${this.width || 'auto'}; height: ${this.height || 'auto'}; transform: translate3d(0,${v},0);` : 'display: none;'; 14 | return html` 15 | 24 | ${this.alt} 25 | `; 26 | } 27 | } -------------------------------------------------------------------------------- /dist/mphantom.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | let MathPhantomElement = class MathPhantomElement extends MathMLElement { 9 | render() { 10 | return html ` 11 | 17 | 18 | `; 19 | } 20 | }; 21 | MathPhantomElement = __decorate([ 22 | customElement('math-phantom') 23 | ], MathPhantomElement); 24 | export { MathPhantomElement }; 25 | -------------------------------------------------------------------------------- /dist/mprescripts.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | let MathPreScriptsElement = class MathPreScriptsElement extends MathMLElement { 9 | render() { 10 | return html ` 11 | 18 | `; 19 | } 20 | }; 21 | MathPreScriptsElement = __decorate([ 22 | customElement('math-prescripts') 23 | ], MathPreScriptsElement); 24 | export { MathPreScriptsElement }; 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Preet Shihn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dist/mn.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | let MathNElement = class MathNElement extends MathMLElement { 9 | render() { 10 | return html ` 11 | 18 | 19 | `; 20 | } 21 | }; 22 | MathNElement = __decorate([ 23 | customElement('math-n') 24 | ], MathNElement); 25 | export { MathNElement }; 26 | -------------------------------------------------------------------------------- /dist/mi.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | let MathIElement = class MathIElement extends MathMLElement { 9 | render() { 10 | return html ` 11 | 19 | 20 | `; 21 | } 22 | }; 23 | MathIElement = __decorate([ 24 | customElement('math-i') 25 | ], MathIElement); 26 | export { MathIElement }; 27 | -------------------------------------------------------------------------------- /dist/mtext.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | let MathTextElement = class MathTextElement extends MathMLElement { 9 | render() { 10 | return html ` 11 | 19 | 20 | `; 21 | } 22 | }; 23 | MathTextElement = __decorate([ 24 | customElement('math-text') 25 | ], MathTextElement); 26 | export { MathTextElement }; 27 | -------------------------------------------------------------------------------- /dist/styles/common-styles.js: -------------------------------------------------------------------------------- 1 | import { html } from '../mathml-element'; 2 | const horizontal = `.layout.horizontal { 3 | display: -ms-flexbox; 4 | display: -webkit-flex; 5 | display: flex; 6 | -ms-flex-direction: row; 7 | -webkit-flex-direction: row; 8 | flex-direction: row; 9 | }`; 10 | const vertical = `.layout.vertical { 11 | display: -ms-flexbox; 12 | display: -webkit-flex; 13 | display: flex; 14 | -ms-flex-direction: column; 15 | -webkit-flex-direction: column; 16 | flex-direction: column; 17 | }`; 18 | const flex = `.flex { 19 | -ms-flex: 1 1 0.000000001px; 20 | -webkit-flex: 1; 21 | flex: 1; 22 | -webkit-flex-basis: 0.000000001px; 23 | flex-basis: 0.000000001px; 24 | }`; 25 | const center = `.center { 26 | -ms-flex-align: center; 27 | -webkit-align-items: center; 28 | align-items: center; 29 | }`; 30 | export const AllFlex = html ` 31 | ${vertical} 32 | ${horizontal} 33 | ${flex} 34 | ${center} 35 | `; 36 | export const VertFlex = html ` 37 | ${vertical} 38 | ${flex} 39 | `; 40 | export const HorizFlex = html ` 41 | ${horizontal} 42 | ${flex} 43 | `; 44 | export const HorizCenterFlex = html ` 45 | ${horizontal} 46 | ${flex} 47 | ${center} 48 | `; 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mathml-elements", 3 | "version": "0.3.0", 4 | "description": "Web components to replicate MathML", 5 | "main": "dist/bundled/mathml.min.js", 6 | "browser": "dist/bundled/mathml.min.js", 7 | "module": "dist/all.js", 8 | "types": "dist/all.d.ts", 9 | "scripts": { 10 | "build": "tsc && rollup -c", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/pshihn/math-ml.git" 16 | }, 17 | "keywords": [ 18 | "mathml", 19 | "webcomponents", 20 | "web components", 21 | "custom elements", 22 | "math", 23 | "equations" 24 | ], 25 | "author": "Preet Shihn ", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/pshihn/math-ml/issues" 29 | }, 30 | "homepage": "https://github.com/pshihn/math-ml#readme", 31 | "devDependencies": { 32 | "rollup": "^1.19.4", 33 | "rollup-plugin-babel-minify": "^9.0.0", 34 | "rollup-plugin-node-resolve": "^5.2.0", 35 | "tslint": "^5.18.0", 36 | "typescript": "^3.5.3" 37 | }, 38 | "dependencies": { 39 | "lit-element": "^2.2.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /dist/bundled/mathml.polyfill.js: -------------------------------------------------------------------------------- 1 | var mathmlPolyfill=function(a){'use strict';function b(a){const b=document.createElement(d(a));c(b,a);const e=a.parentElement;return e&&(a.insertAdjacentElement("beforebegin",b),e.removeChild(a)),b}function c(a,b){const e=b.childNodes;for(let f=0;f",document.body.appendChild(b);const c=b.firstChild&&b.firstChild.firstChild&&b.firstChild.firstChild.getBoundingClientRect();return document.body.removeChild(b),c&&1>=a(c.height-23)&&1>=a(c.width-77)}return(()=>{if(!e()){const a=document.querySelectorAll("math");if(a&&a.length)for(let c=0;c= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | let MathErrorElement = class MathErrorElement extends MathMLElement { 9 | render() { 10 | return html ` 11 | 23 | 24 | `; 25 | } 26 | }; 27 | MathErrorElement = __decorate([ 28 | customElement('math-error') 29 | ], MathErrorElement); 30 | export { MathErrorElement }; 31 | -------------------------------------------------------------------------------- /src/mtd.ts: -------------------------------------------------------------------------------- 1 | import { html, PropertyValues, TemplateResult, customElement } from './mathml-element.js'; 2 | import { MathTableBaseElement } from './mtable-base.js'; 3 | 4 | @customElement('math-td') 5 | export class MathTDElement extends MathTableBaseElement { 6 | render(): TemplateResult { 7 | return html` 8 | 27 | 28 | `; 29 | } 30 | 31 | updated(propVals: PropertyValues) { 32 | super.updated(propVals); 33 | this.updateAlignment(); 34 | } 35 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "arrow-parens": true, 4 | "class-name": true, 5 | "indent": [ 6 | true, 7 | "spaces", 8 | 2 9 | ], 10 | "prefer-const": true, 11 | "no-duplicate-variable": true, 12 | "no-eval": true, 13 | "no-internal-module": true, 14 | "no-trailing-whitespace": false, 15 | "no-var-keyword": true, 16 | "one-line": [ 17 | true, 18 | "check-open-brace", 19 | "check-whitespace" 20 | ], 21 | "quotemark": [ 22 | true, 23 | "single", 24 | "avoid-escape" 25 | ], 26 | "semicolon": [ 27 | true, 28 | "always" 29 | ], 30 | "trailing-comma": [ 31 | true, 32 | "multiline" 33 | ], 34 | "triple-equals": [ 35 | true, 36 | "allow-null-check" 37 | ], 38 | "typedef-whitespace": [ 39 | true, 40 | { 41 | "call-signature": "nospace", 42 | "index-signature": "nospace", 43 | "parameter": "nospace", 44 | "property-declaration": "nospace", 45 | "variable-declaration": "nospace" 46 | } 47 | ], 48 | "variable-name": [ 49 | true, 50 | "ban-keywords" 51 | ], 52 | "whitespace": [ 53 | true, 54 | "check-branch", 55 | "check-decl", 56 | "check-operator", 57 | "check-separator", 58 | "check-type" 59 | ] 60 | } 61 | } -------------------------------------------------------------------------------- /src/mtable-base.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, property, MathRowAlignType } from './mathml-element.js'; 2 | 3 | export class MathTableBaseElement extends MathMLElement { 4 | @property({ type: String }) columnalign?: string; 5 | @property({ type: String }) rowalign?: MathRowAlignType; 6 | 7 | protected updateAlignment() { 8 | const s = this.style; 9 | if (this.columnalign) { 10 | switch (this.columnalign) { 11 | case 'left': 12 | s.setProperty('--math-ml-columnalign', 'left'); 13 | break; 14 | case 'right': 15 | s.setProperty('--math-ml-columnalign', 'right'); 16 | break; 17 | default: 18 | case 'center': 19 | s.setProperty('--math-ml-columnalign', 'center'); 20 | break; 21 | } 22 | } 23 | if (this.rowalign) { 24 | switch (this.rowalign) { 25 | case 'baseline': 26 | s.setProperty('--math-ml-rowalign', 'baseline'); 27 | break; 28 | case 'bottom': 29 | s.setProperty('--math-ml-rowalign', 'bottom'); 30 | break; 31 | case 'axis': 32 | case 'center': 33 | s.setProperty('--math-ml-rowalign', 'middle'); 34 | break; 35 | case 'top': 36 | s.setProperty('--math-ml-rowalign', 'top'); 37 | break; 38 | default: 39 | s.removeProperty('--math-ml-rowalign'); 40 | break; 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /dist/math.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | let MathElement = class MathElement extends MathMLElement { 9 | render() { 10 | return html ` 11 | 27 | 28 | `; 29 | } 30 | }; 31 | MathElement = __decorate([ 32 | customElement('math-ml') 33 | ], MathElement); 34 | export { MathElement }; 35 | -------------------------------------------------------------------------------- /dist/mstyle.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | let MathStyleElement = class MathStyleElement extends MathMLElement { 12 | render() { 13 | return html ` 14 | 21 | 22 | `; 23 | } 24 | }; 25 | __decorate([ 26 | property({ type: String }), 27 | __metadata("design:type", String) 28 | ], MathStyleElement.prototype, "displaystyle", void 0); 29 | MathStyleElement = __decorate([ 30 | customElement('math-style') 31 | ], MathStyleElement); 32 | export { MathStyleElement }; 33 | -------------------------------------------------------------------------------- /dist/mlabeledtr.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { html, customElement } from './mathml-element.js'; 8 | import { MathTableBaseElement } from './mtable-base.js'; 9 | let MathLabeledTRElement = class MathLabeledTRElement extends MathTableBaseElement { 10 | render() { 11 | return html ` 12 | 25 | 26 | `; 27 | } 28 | updated(propVals) { 29 | super.updated(propVals); 30 | this.updateAlignment(); 31 | } 32 | }; 33 | MathLabeledTRElement = __decorate([ 34 | customElement('math-labeledtr') 35 | ], MathLabeledTRElement); 36 | export { MathLabeledTRElement }; 37 | -------------------------------------------------------------------------------- /dist/mathml-element.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { LitElement, property } from 'lit-element'; 11 | export { html, TemplateResult, property, customElement } from 'lit-element'; 12 | export class MathMLElement extends LitElement { 13 | updated(propVals) { 14 | if (propVals.has('mathcolor')) { 15 | this.style.setProperty('--math-color', this.mathcolor || null); 16 | } 17 | if (propVals.has('mathbackground')) { 18 | this.style.setProperty('--math-background', this.mathbackground || null); 19 | } 20 | } 21 | } 22 | __decorate([ 23 | property({ type: String }), 24 | __metadata("design:type", String) 25 | ], MathMLElement.prototype, "mathbackground", void 0); 26 | __decorate([ 27 | property({ type: String }), 28 | __metadata("design:type", String) 29 | ], MathMLElement.prototype, "mathcolor", void 0); 30 | -------------------------------------------------------------------------------- /examples/using-polyfill.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Math-ML: Polyfill example 8 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | i 37 | = 38 | 1 39 | 40 | n 41 | 42 | 43 | 44 | 1 45 | n 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/munder.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, html, TemplateResult, customElement, property, MathAlignType } from './mathml-element.js'; 2 | import { VertFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-under') 5 | export class MathUnderElement extends MathMLElement { 6 | @property({ type: Boolean, reflect: true }) accentunder = false; 7 | @property() align: MathAlignType = 'center'; 8 | 9 | render(): TemplateResult { 10 | return html` 11 | 29 |
30 | 31 |
32 | `; 33 | } 34 | 35 | updated(propVals: PropertyValues) { 36 | super.updated(propVals); 37 | const s = this.style; 38 | switch (this.align) { 39 | case 'right': 40 | s.setProperty('--math-under-align', 'right'); 41 | break; 42 | case 'left': 43 | s.setProperty('--math-under-align', 'left'); 44 | break; 45 | default: 46 | s.setProperty('--math-under-align', 'center'); 47 | break; 48 | } 49 | s.setProperty('--math-under-font-size', this.accentunder ? '1em' : '0.8em'); 50 | } 51 | } -------------------------------------------------------------------------------- /src/mtr.ts: -------------------------------------------------------------------------------- 1 | import { html, PropertyValues, TemplateResult, customElement } from './mathml-element.js'; 2 | import { MathTableBaseElement } from './mtable-base.js'; 3 | 4 | @customElement('math-tr') 5 | export class MathTRElement extends MathTableBaseElement { 6 | render(): TemplateResult { 7 | return html` 8 | 18 | 19 | `; 20 | } 21 | 22 | updated(propVals: PropertyValues) { 23 | super.updated(propVals); 24 | this.updateAlignment(); 25 | this.refreshSlot(); 26 | } 27 | 28 | private refreshSlot() { 29 | if (!this.shadowRoot) { 30 | return; 31 | } 32 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 33 | if (!slot) { 34 | return; 35 | } 36 | if (this.columnalign) { 37 | const split = this.columnalign.trim().split(' ').filter((d) => { 38 | if (d.trim()) { 39 | return true; 40 | } 41 | return false; 42 | }); 43 | if (split.length > 1) { 44 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE).filter((d) => { 45 | return (d as HTMLElement).tagName === 'MATH-TD'; 46 | }); 47 | for (let i = 0; i < split.length; i++) { 48 | if (i >= nodes.length) { 49 | break; 50 | } 51 | (nodes[i] as MathTableBaseElement).columnalign = split[i]; 52 | } 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/mover.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, html, TemplateResult, customElement, property, MathAlignType } from './mathml-element.js'; 2 | import { VertFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-over') 5 | export class MathOverElement extends MathMLElement { 6 | @property({ type: Boolean, reflect: true }) accent = false; 7 | @property() align: MathAlignType = 'center'; 8 | 9 | render(): TemplateResult { 10 | return html` 11 | 34 |
35 | 36 |
37 | `; 38 | } 39 | 40 | updated(propVals: PropertyValues) { 41 | super.updated(propVals); 42 | const s = this.style; 43 | switch (this.align) { 44 | case 'right': 45 | s.setProperty('--math-over-align', 'right'); 46 | break; 47 | case 'left': 48 | s.setProperty('--math-over-align', 'left'); 49 | break; 50 | default: 51 | s.setProperty('--math-over-align', 'center'); 52 | break; 53 | } 54 | s.setProperty('--math-over-font-size', this.accent ? '1em' : '0.8em'); 55 | } 56 | } -------------------------------------------------------------------------------- /src/msup.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | import { HorizFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-sup') 5 | export class MathSupElement extends MathMLElement { 6 | render(): TemplateResult { 7 | return html` 8 | 28 |
29 | 30 |
31 | `; 32 | } 33 | 34 | refreshSlot() { 35 | if (!this.shadowRoot) { 36 | return; 37 | } 38 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 39 | if (!slot) { 40 | return; 41 | } 42 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 43 | if (nodes.length > 1) { 44 | setTimeout(() => { 45 | const s1 = (nodes[0] as HTMLElement).getBoundingClientRect(); 46 | const supNode = nodes[1] as HTMLElement; 47 | const s2 = supNode.getBoundingClientRect(); 48 | supNode.style.opacity = '1'; 49 | const margins = [0, 0]; 50 | const db = s2.bottom - (s1.bottom - (s1.height / 2)); 51 | if (db > 0) { 52 | supNode.style.top = `${-db}px`; 53 | margins[0] = db; 54 | } 55 | margins[1] = s2.width + 5; 56 | this.style.margin = `${margins[0]}px ${margins[1]}px 0 0`; 57 | }, 50); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/mpadded.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, html, TemplateResult, customElement, property } from './mathml-element.js'; 2 | 3 | @customElement('math-padded') 4 | export class MathPaddedElement extends MathMLElement { 5 | @property({ type: String }) height?: string; 6 | @property({ type: String }) width?: string; 7 | 8 | render(): TemplateResult { 9 | return html` 10 | 17 |
18 | `; 19 | } 20 | 21 | updated(propVals: PropertyValues) { 22 | super.updated(propVals); 23 | this.refresh(); 24 | } 25 | 26 | private refresh() { 27 | if (!this.shadowRoot) { 28 | return; 29 | } 30 | const panel = this.shadowRoot!.querySelector('#mpaddedPanel') as HTMLElement; 31 | if (!panel) { 32 | return; 33 | } 34 | setTimeout(() => { 35 | const size = panel.getBoundingClientRect(); 36 | if (this.height) { 37 | if (this.height.charAt(0) === '+') { 38 | this.style.paddingTop = this.height.substring(1); 39 | } else if (this.height.charAt(0) === '-') { 40 | this.style.height = `calc(${size.height}px - ${this.height.substring(1)})`; 41 | this.style.paddingTop = '0'; 42 | } else { 43 | this.style.height = this.height; 44 | this.style.paddingTop = '0'; 45 | } 46 | } else { 47 | this.style.height = 'auto'; 48 | this.style.paddingTop = '0'; 49 | } 50 | if (this.width) { 51 | if (this.width.charAt(0) === '+' || this.width.charAt(0) === '-') { 52 | this.style.width = `calc(${size.width}px + ${this.width.substring(1)})`; 53 | } else { 54 | this.style.width = this.width; 55 | } 56 | } else { 57 | this.style.width = 'auto'; 58 | } 59 | }, 50); 60 | } 61 | } -------------------------------------------------------------------------------- /dist/mtd.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { html, customElement } from './mathml-element.js'; 8 | import { MathTableBaseElement } from './mtable-base.js'; 9 | let MathTDElement = class MathTDElement extends MathTableBaseElement { 10 | render() { 11 | return html ` 12 | 31 | 32 | `; 33 | } 34 | updated(propVals) { 35 | super.updated(propVals); 36 | this.updateAlignment(); 37 | } 38 | }; 39 | MathTDElement = __decorate([ 40 | customElement('math-td') 41 | ], MathTDElement); 42 | export { MathTDElement }; 43 | -------------------------------------------------------------------------------- /dist/ms.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | let MathSElement = class MathSElement extends MathMLElement { 12 | render() { 13 | return html ` 14 | 35 | 36 | `; 37 | } 38 | }; 39 | __decorate([ 40 | property({ type: String, reflect: true }), 41 | __metadata("design:type", String) 42 | ], MathSElement.prototype, "lquote", void 0); 43 | __decorate([ 44 | property({ type: String, reflect: true }), 45 | __metadata("design:type", String) 46 | ], MathSElement.prototype, "rquote", void 0); 47 | MathSElement = __decorate([ 48 | customElement('math-s') 49 | ], MathSElement); 50 | export { MathSElement }; 51 | -------------------------------------------------------------------------------- /src/msub.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | import { HorizFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-sub') 5 | export class MathSubElement extends MathMLElement { 6 | render(): TemplateResult { 7 | return html` 8 | 29 |
30 | 31 |
32 | `; 33 | } 34 | 35 | refreshSlot() { 36 | if (!this.shadowRoot) { 37 | return; 38 | } 39 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 40 | if (!slot) { 41 | return; 42 | } 43 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 44 | if (nodes.length > 1) { 45 | setTimeout(() => { 46 | const s1 = (nodes[0] as HTMLElement).getBoundingClientRect(); 47 | const subNode = nodes[1] as HTMLElement; 48 | const s2 = subNode.getBoundingClientRect(); 49 | subNode.style.opacity = '1'; 50 | const margins = [0, 0]; 51 | const hh = s1.height / 2; 52 | let db = hh; 53 | if ((hh + s2.height) < s1.height) { 54 | db = s1.height - s2.height; 55 | } else { 56 | margins[0] = (hh + s2.height) - s1.height; 57 | } 58 | subNode.style.top = `${db}px`; 59 | margins[1] = s2.width + 5; 60 | this.style.margin = `0 ${margins[1]}px ${margins[0]}px 0`; 61 | }, 50); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /dist/mspace.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | let MathSpaceElement = class MathSpaceElement extends MathMLElement { 12 | constructor() { 13 | super(...arguments); 14 | this.width = '0em'; 15 | this.height = '0ex'; 16 | this.depth = '0ex'; 17 | } 18 | render() { 19 | return html ` 20 | 27 | `; 28 | } 29 | updated(propVals) { 30 | super.updated(propVals); 31 | this.style.width = this.width; 32 | this.style.height = this.height; 33 | this.style.marginBottom = this.depth; 34 | } 35 | }; 36 | __decorate([ 37 | property({ type: String }), 38 | __metadata("design:type", Object) 39 | ], MathSpaceElement.prototype, "width", void 0); 40 | __decorate([ 41 | property({ type: String }), 42 | __metadata("design:type", Object) 43 | ], MathSpaceElement.prototype, "height", void 0); 44 | __decorate([ 45 | property({ type: String }), 46 | __metadata("design:type", Object) 47 | ], MathSpaceElement.prototype, "depth", void 0); 48 | MathSpaceElement = __decorate([ 49 | customElement('math-space') 50 | ], MathSpaceElement); 51 | export { MathSpaceElement }; 52 | -------------------------------------------------------------------------------- /src/msqrt.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, html, TemplateResult, customElement } from './mathml-element.js'; 2 | import { HorizFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-sqrt') 5 | export class MathSqrtElement extends MathMLElement { 6 | render(): TemplateResult { 7 | return html` 8 | 39 |
40 |
41 |
42 |
43 | `; 44 | } 45 | 46 | updated(propVals: PropertyValues) { 47 | super.updated(propVals); 48 | this.onSlotCange(); 49 | } 50 | 51 | private onSlotCange() { 52 | if (!this.shadowRoot) { 53 | return; 54 | } 55 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 56 | if (!slot) { 57 | return; 58 | } 59 | setTimeout(() => { 60 | this.drawRoot(); 61 | }, 10); 62 | } 63 | 64 | private drawRoot() { 65 | const span = this.shadowRoot!.querySelector('#msqrtGlyphSpan'); 66 | const path = this.shadowRoot!.querySelector('#rootPath'); 67 | if (span && path) { 68 | const size = (span as HTMLElement).getBoundingClientRect(); 69 | const width = size.width; 70 | const height = size.height; 71 | const d = `M0 ${height * 0.55} H${width * 0.13} L${width * 0.45} ${height - 2} L${width} 0`; 72 | path.setAttribute('d', d); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /dist/mtr.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { html, customElement } from './mathml-element.js'; 8 | import { MathTableBaseElement } from './mtable-base.js'; 9 | let MathTRElement = class MathTRElement extends MathTableBaseElement { 10 | render() { 11 | return html ` 12 | 22 | 23 | `; 24 | } 25 | updated(propVals) { 26 | super.updated(propVals); 27 | this.updateAlignment(); 28 | this.refreshSlot(); 29 | } 30 | refreshSlot() { 31 | if (!this.shadowRoot) { 32 | return; 33 | } 34 | const slot = this.shadowRoot.querySelector('slot'); 35 | if (!slot) { 36 | return; 37 | } 38 | if (this.columnalign) { 39 | const split = this.columnalign.trim().split(' ').filter((d) => { 40 | if (d.trim()) { 41 | return true; 42 | } 43 | return false; 44 | }); 45 | if (split.length > 1) { 46 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE).filter((d) => { 47 | return d.tagName === 'MATH-TD'; 48 | }); 49 | for (let i = 0; i < split.length; i++) { 50 | if (i >= nodes.length) { 51 | break; 52 | } 53 | nodes[i].columnalign = split[i]; 54 | } 55 | } 56 | } 57 | } 58 | }; 59 | MathTRElement = __decorate([ 60 | customElement('math-tr') 61 | ], MathTRElement); 62 | export { MathTRElement }; 63 | -------------------------------------------------------------------------------- /src/mroot.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, html, TemplateResult, customElement } from './mathml-element.js'; 2 | import { HorizFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-root') 5 | export class MathRootElement extends MathMLElement { 6 | render(): TemplateResult { 7 | return html` 8 | 45 |
46 |
47 |
48 |
49 | `; 50 | } 51 | 52 | updated(propVals: PropertyValues) { 53 | super.updated(propVals); 54 | this.onSlotCange(); 55 | } 56 | 57 | private onSlotCange() { 58 | if (!this.shadowRoot) { 59 | return; 60 | } 61 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 62 | if (!slot) { 63 | return; 64 | } 65 | setTimeout(() => { 66 | this.drawRoot(); 67 | }, 10); 68 | } 69 | 70 | private drawRoot() { 71 | const span = this.shadowRoot!.querySelector('#msqrtGlyphSpan'); 72 | const path = this.shadowRoot!.querySelector('#rootPath'); 73 | if (span && path) { 74 | const size = (span as HTMLElement).getBoundingClientRect(); 75 | const width = size.width; 76 | const height = size.height; 77 | const d = `M0 ${height * 0.55} H${width * 0.13} L${width * 0.45} ${height - 2} L${width} 0`; 78 | path.setAttribute('d', d); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /dist/mglyph.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | let MathGlyphElement = class MathGlyphElement extends MathMLElement { 12 | constructor() { 13 | super(...arguments); 14 | this.width = 'auto'; 15 | this.height = 'auto'; 16 | this.valign = 'auto'; 17 | this.alt = ''; 18 | } 19 | render() { 20 | const v = this.valign ? (this.valign.indexOf('-') === 0 ? this.valign.substring(1) : `-${this.valign}`) : '0'; 21 | const style = this.src ? `width: ${this.width || 'auto'}; height: ${this.height || 'auto'}; transform: translate3d(0,${v},0);` : 'display: none;'; 22 | return html ` 23 | 32 | ${this.alt} 33 | `; 34 | } 35 | }; 36 | __decorate([ 37 | property({ type: String }), 38 | __metadata("design:type", String) 39 | ], MathGlyphElement.prototype, "src", void 0); 40 | __decorate([ 41 | property({ type: String }), 42 | __metadata("design:type", Object) 43 | ], MathGlyphElement.prototype, "width", void 0); 44 | __decorate([ 45 | property({ type: String }), 46 | __metadata("design:type", Object) 47 | ], MathGlyphElement.prototype, "height", void 0); 48 | __decorate([ 49 | property({ type: String }), 50 | __metadata("design:type", Object) 51 | ], MathGlyphElement.prototype, "valign", void 0); 52 | __decorate([ 53 | property({ type: String }), 54 | __metadata("design:type", Object) 55 | ], MathGlyphElement.prototype, "alt", void 0); 56 | MathGlyphElement = __decorate([ 57 | customElement('math-glyph') 58 | ], MathGlyphElement); 59 | export { MathGlyphElement }; 60 | -------------------------------------------------------------------------------- /dist/mtable-base.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, property } from './mathml-element.js'; 11 | export class MathTableBaseElement extends MathMLElement { 12 | updateAlignment() { 13 | const s = this.style; 14 | if (this.columnalign) { 15 | switch (this.columnalign) { 16 | case 'left': 17 | s.setProperty('--math-ml-columnalign', 'left'); 18 | break; 19 | case 'right': 20 | s.setProperty('--math-ml-columnalign', 'right'); 21 | break; 22 | default: 23 | case 'center': 24 | s.setProperty('--math-ml-columnalign', 'center'); 25 | break; 26 | } 27 | } 28 | if (this.rowalign) { 29 | switch (this.rowalign) { 30 | case 'baseline': 31 | s.setProperty('--math-ml-rowalign', 'baseline'); 32 | break; 33 | case 'bottom': 34 | s.setProperty('--math-ml-rowalign', 'bottom'); 35 | break; 36 | case 'axis': 37 | case 'center': 38 | s.setProperty('--math-ml-rowalign', 'middle'); 39 | break; 40 | case 'top': 41 | s.setProperty('--math-ml-rowalign', 'top'); 42 | break; 43 | default: 44 | s.removeProperty('--math-ml-rowalign'); 45 | break; 46 | } 47 | } 48 | } 49 | } 50 | __decorate([ 51 | property({ type: String }), 52 | __metadata("design:type", String) 53 | ], MathTableBaseElement.prototype, "columnalign", void 0); 54 | __decorate([ 55 | property({ type: String }), 56 | __metadata("design:type", String) 57 | ], MathTableBaseElement.prototype, "rowalign", void 0); 58 | -------------------------------------------------------------------------------- /src/polyfill.ts: -------------------------------------------------------------------------------- 1 | export function polyfill(mathNode: Element): Element { 2 | const root = document.createElement(getCustomElementName(mathNode)); 3 | polyfillChildren(root, mathNode); 4 | const parent = mathNode.parentElement; 5 | if (parent) { 6 | mathNode.insertAdjacentElement('beforebegin', root); 7 | parent.removeChild(mathNode); 8 | } 9 | return root; 10 | } 11 | 12 | function polyfillChildren(target: Element, current: Element) { 13 | const children = current.childNodes; 14 | for (let i = 0; i < children.length; i++) { 15 | const child = children[i]; 16 | switch (child.nodeType) { 17 | case Node.TEXT_NODE: 18 | if (child.nodeValue) { 19 | const txt = document.createTextNode(child.nodeValue); 20 | target.appendChild(txt); 21 | } 22 | break; 23 | case Node.ELEMENT_NODE: 24 | const childElement = child as Element; 25 | const n = document.createElement(getCustomElementName(childElement)); 26 | const attrs = childElement.attributes; 27 | if (attrs && attrs.length) { 28 | for (let x = 0; x < attrs.length; x++) { 29 | const attr = attrs[x]; 30 | n.setAttribute(attr.name, attr.value); 31 | } 32 | } 33 | polyfillChildren(n, childElement); 34 | target.appendChild(n); 35 | break; 36 | default: 37 | break; 38 | } 39 | } 40 | } 41 | 42 | function getCustomElementName(node: Element): string { 43 | const name = node.tagName.toLowerCase().trim(); 44 | switch (name) { 45 | case 'math': 46 | return 'math-ml'; 47 | case 'none': 48 | return 'math-none'; 49 | default: 50 | if (name.indexOf('m') === 0) { 51 | return `math-${name.substring(1)}`; 52 | } 53 | break; 54 | } 55 | return name; 56 | } 57 | 58 | // Check adapted from https://developer.mozilla.org/en-US/docs/Web/MathML/Authoring 59 | function hasMathMLSupport() { 60 | const div = document.createElement('div'); 61 | div.innerHTML = ""; 62 | document.body.appendChild(div); 63 | const box = div.firstChild && div.firstChild.firstChild && (div.firstChild.firstChild as Element).getBoundingClientRect(); 64 | document.body.removeChild(div); 65 | return box && (Math.abs(box.height - 23) <= 1) && (Math.abs(box.width - 77) <= 1); 66 | } 67 | 68 | (() => { 69 | if (!hasMathMLSupport()) { 70 | const mathNodes = document.querySelectorAll('math'); 71 | if (mathNodes && mathNodes.length) { 72 | for (let i = 0; i < mathNodes.length; i++) { 73 | polyfill(mathNodes[i]); 74 | } 75 | } 76 | } 77 | })(); -------------------------------------------------------------------------------- /dist/msup.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | import { HorizFlex } from './styles/common-styles.js'; 9 | let MathSupElement = class MathSupElement extends MathMLElement { 10 | render() { 11 | return html ` 12 | 32 |
33 | 34 |
35 | `; 36 | } 37 | refreshSlot() { 38 | if (!this.shadowRoot) { 39 | return; 40 | } 41 | const slot = this.shadowRoot.querySelector('slot'); 42 | if (!slot) { 43 | return; 44 | } 45 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 46 | if (nodes.length > 1) { 47 | setTimeout(() => { 48 | const s1 = nodes[0].getBoundingClientRect(); 49 | const supNode = nodes[1]; 50 | const s2 = supNode.getBoundingClientRect(); 51 | supNode.style.opacity = '1'; 52 | const margins = [0, 0]; 53 | const db = s2.bottom - (s1.bottom - (s1.height / 2)); 54 | if (db > 0) { 55 | supNode.style.top = `${-db}px`; 56 | margins[0] = db; 57 | } 58 | margins[1] = s2.width + 5; 59 | this.style.margin = `${margins[0]}px ${margins[1]}px 0 0`; 60 | }, 50); 61 | } 62 | } 63 | }; 64 | MathSupElement = __decorate([ 65 | customElement('math-sup') 66 | ], MathSupElement); 67 | export { MathSupElement }; 68 | -------------------------------------------------------------------------------- /src/mrow.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | import { HorizFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-row') 5 | export class MathRowElement extends MathMLElement { 6 | render(): TemplateResult { 7 | return html` 8 | 27 |
28 | `; 29 | } 30 | 31 | private onSlotChange() { 32 | if (!this.shadowRoot) { 33 | return; 34 | } 35 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 36 | const panel = this.shadowRoot.querySelector('#mrowPanel') as HTMLElement; 37 | if (!slot || !panel) { 38 | return; 39 | } 40 | panel.classList.remove('centered'); 41 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 42 | let opCount = 0; 43 | let centeringNodeCount = 0; 44 | let center = false; 45 | for (let i = 0; i < nodes.length; i++) { 46 | const text = (nodes[i].textContent || '').trim(); 47 | if (text === '=') { 48 | center = true; 49 | break; 50 | } 51 | const tagName = (nodes[i] as HTMLElement).tagName.toLowerCase(); 52 | switch (tagName) { 53 | case 'math-underover': 54 | case 'math-under': 55 | case 'math-over': 56 | case 'math-subsup': 57 | centeringNodeCount++; 58 | break; 59 | case 'math-o': 60 | opCount++; 61 | break; 62 | case 'math-table': 63 | center = true; 64 | break; 65 | default: 66 | break; 67 | } 68 | } 69 | if (!center) { 70 | if (centeringNodeCount && (!opCount)) { 71 | center = true; 72 | } 73 | } 74 | if (center) { 75 | panel.classList.add('centered'); 76 | } 77 | panel.classList.remove('justified'); 78 | if ((getComputedStyle(this).getPropertyValue('--math-underover-align') || '').trim() === 'center' 79 | || (getComputedStyle(this).getPropertyValue('--math-under-align') || '').trim() === 'center' 80 | || (getComputedStyle(this).getPropertyValue('--math-over-align') || '').trim() === 'center' 81 | ) { 82 | panel.classList.add('justified'); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/msubsup.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | import { HorizFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-subsup') 5 | export class MathSubSupElement extends MathMLElement { 6 | private pendingLayout = false; 7 | 8 | render(): TemplateResult { 9 | return html` 10 | 30 |
31 | 32 |
33 | `; 34 | } 35 | 36 | refreshSlot() { 37 | if (this.pendingLayout) { 38 | return; 39 | } 40 | if (!this.shadowRoot) { 41 | return; 42 | } 43 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 44 | if (!slot) { 45 | return; 46 | } 47 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 48 | if (nodes.length > 2) { 49 | this.pendingLayout = true; 50 | const runnable = () => { 51 | const s1 = (nodes[0] as HTMLElement).getBoundingClientRect(); 52 | const subNode = nodes[1] as HTMLElement; 53 | const supNode = nodes[2] as HTMLElement; 54 | const subSize = subNode.getBoundingClientRect(); 55 | const supSize = supNode.getBoundingClientRect(); 56 | 57 | subNode.style.opacity = '1'; 58 | supNode.style.opacity = '1'; 59 | const margins = [0, 0, 0]; 60 | 61 | // sub 62 | const hh = s1.height / 2; 63 | let db = hh; 64 | if ((hh + subSize.height) < s1.height) { 65 | db = s1.height - subSize.height; 66 | } else { 67 | margins[2] = (hh + subSize.height) - s1.height; 68 | } 69 | subNode.style.top = `${db}px`; 70 | margins[1] = subSize.width + 5; 71 | 72 | // sup 73 | db = supSize.bottom - (s1.bottom - (s1.height / 2)); 74 | if (db > 0) { 75 | supNode.style.top = `${-db}px`; 76 | margins[0] = db; 77 | } 78 | margins[1] = Math.max(supSize.width + 5, margins[1]); 79 | this.style.margin = `${margins[0]}px ${margins[1]}px ${margins[2]}px 0`; 80 | }; 81 | setTimeout(runnable, 50); 82 | setTimeout(() => { 83 | this.pendingLayout = false; 84 | runnable(); 85 | }, 500); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /dist/polyfill.js: -------------------------------------------------------------------------------- 1 | export function polyfill(mathNode) { 2 | const root = document.createElement(getCustomElementName(mathNode)); 3 | polyfillChildren(root, mathNode); 4 | const parent = mathNode.parentElement; 5 | if (parent) { 6 | mathNode.insertAdjacentElement('beforebegin', root); 7 | parent.removeChild(mathNode); 8 | } 9 | return root; 10 | } 11 | function polyfillChildren(target, current) { 12 | const children = current.childNodes; 13 | for (let i = 0; i < children.length; i++) { 14 | const child = children[i]; 15 | switch (child.nodeType) { 16 | case Node.TEXT_NODE: 17 | if (child.nodeValue) { 18 | const txt = document.createTextNode(child.nodeValue); 19 | target.appendChild(txt); 20 | } 21 | break; 22 | case Node.ELEMENT_NODE: 23 | const childElement = child; 24 | const n = document.createElement(getCustomElementName(childElement)); 25 | const attrs = childElement.attributes; 26 | if (attrs && attrs.length) { 27 | for (let x = 0; x < attrs.length; x++) { 28 | const attr = attrs[x]; 29 | n.setAttribute(attr.name, attr.value); 30 | } 31 | } 32 | polyfillChildren(n, childElement); 33 | target.appendChild(n); 34 | break; 35 | default: 36 | break; 37 | } 38 | } 39 | } 40 | function getCustomElementName(node) { 41 | const name = node.tagName.toLowerCase().trim(); 42 | switch (name) { 43 | case 'math': 44 | return 'math-ml'; 45 | case 'none': 46 | return 'math-none'; 47 | default: 48 | if (name.indexOf('m') === 0) { 49 | return `math-${name.substring(1)}`; 50 | } 51 | break; 52 | } 53 | return name; 54 | } 55 | // Check adapted from https://developer.mozilla.org/en-US/docs/Web/MathML/Authoring 56 | function hasMathMLSupport() { 57 | const div = document.createElement('div'); 58 | div.innerHTML = ""; 59 | document.body.appendChild(div); 60 | const box = div.firstChild && div.firstChild.firstChild && div.firstChild.firstChild.getBoundingClientRect(); 61 | document.body.removeChild(div); 62 | return box && (Math.abs(box.height - 23) <= 1) && (Math.abs(box.width - 77) <= 1); 63 | } 64 | (() => { 65 | if (!hasMathMLSupport()) { 66 | const mathNodes = document.querySelectorAll('math'); 67 | if (mathNodes && mathNodes.length) { 68 | for (let i = 0; i < mathNodes.length; i++) { 69 | polyfill(mathNodes[i]); 70 | } 71 | } 72 | } 73 | })(); 74 | -------------------------------------------------------------------------------- /dist/msub.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | import { HorizFlex } from './styles/common-styles.js'; 9 | let MathSubElement = class MathSubElement extends MathMLElement { 10 | render() { 11 | return html ` 12 | 33 |
34 | 35 |
36 | `; 37 | } 38 | refreshSlot() { 39 | if (!this.shadowRoot) { 40 | return; 41 | } 42 | const slot = this.shadowRoot.querySelector('slot'); 43 | if (!slot) { 44 | return; 45 | } 46 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 47 | if (nodes.length > 1) { 48 | setTimeout(() => { 49 | const s1 = nodes[0].getBoundingClientRect(); 50 | const subNode = nodes[1]; 51 | const s2 = subNode.getBoundingClientRect(); 52 | subNode.style.opacity = '1'; 53 | const margins = [0, 0]; 54 | const hh = s1.height / 2; 55 | let db = hh; 56 | if ((hh + s2.height) < s1.height) { 57 | db = s1.height - s2.height; 58 | } 59 | else { 60 | margins[0] = (hh + s2.height) - s1.height; 61 | } 62 | subNode.style.top = `${db}px`; 63 | margins[1] = s2.width + 5; 64 | this.style.margin = `0 ${margins[1]}px ${margins[0]}px 0`; 65 | }, 50); 66 | } 67 | } 68 | }; 69 | MathSubElement = __decorate([ 70 | customElement('math-sub') 71 | ], MathSubElement); 72 | export { MathSubElement }; 73 | -------------------------------------------------------------------------------- /dist/munder.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | import { VertFlex } from './styles/common-styles.js'; 12 | let MathUnderElement = class MathUnderElement extends MathMLElement { 13 | constructor() { 14 | super(...arguments); 15 | this.accentunder = false; 16 | this.align = 'center'; 17 | } 18 | render() { 19 | return html ` 20 | 38 |
39 | 40 |
41 | `; 42 | } 43 | updated(propVals) { 44 | super.updated(propVals); 45 | const s = this.style; 46 | switch (this.align) { 47 | case 'right': 48 | s.setProperty('--math-under-align', 'right'); 49 | break; 50 | case 'left': 51 | s.setProperty('--math-under-align', 'left'); 52 | break; 53 | default: 54 | s.setProperty('--math-under-align', 'center'); 55 | break; 56 | } 57 | s.setProperty('--math-under-font-size', this.accentunder ? '1em' : '0.8em'); 58 | } 59 | }; 60 | __decorate([ 61 | property({ type: Boolean, reflect: true }), 62 | __metadata("design:type", Object) 63 | ], MathUnderElement.prototype, "accentunder", void 0); 64 | __decorate([ 65 | property(), 66 | __metadata("design:type", String) 67 | ], MathUnderElement.prototype, "align", void 0); 68 | MathUnderElement = __decorate([ 69 | customElement('math-under') 70 | ], MathUnderElement); 71 | export { MathUnderElement }; 72 | -------------------------------------------------------------------------------- /dist/msqrt.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | import { HorizFlex } from './styles/common-styles.js'; 9 | let MathSqrtElement = class MathSqrtElement extends MathMLElement { 10 | render() { 11 | return html ` 12 | 43 |
44 |
45 |
46 |
47 | `; 48 | } 49 | updated(propVals) { 50 | super.updated(propVals); 51 | this.onSlotCange(); 52 | } 53 | onSlotCange() { 54 | if (!this.shadowRoot) { 55 | return; 56 | } 57 | const slot = this.shadowRoot.querySelector('slot'); 58 | if (!slot) { 59 | return; 60 | } 61 | setTimeout(() => { 62 | this.drawRoot(); 63 | }, 10); 64 | } 65 | drawRoot() { 66 | const span = this.shadowRoot.querySelector('#msqrtGlyphSpan'); 67 | const path = this.shadowRoot.querySelector('#rootPath'); 68 | if (span && path) { 69 | const size = span.getBoundingClientRect(); 70 | const width = size.width; 71 | const height = size.height; 72 | const d = `M0 ${height * 0.55} H${width * 0.13} L${width * 0.45} ${height - 2} L${width} 0`; 73 | path.setAttribute('d', d); 74 | } 75 | } 76 | }; 77 | MathSqrtElement = __decorate([ 78 | customElement('math-sqrt') 79 | ], MathSqrtElement); 80 | export { MathSqrtElement }; 81 | -------------------------------------------------------------------------------- /dist/mover.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | import { VertFlex } from './styles/common-styles.js'; 12 | let MathOverElement = class MathOverElement extends MathMLElement { 13 | constructor() { 14 | super(...arguments); 15 | this.accent = false; 16 | this.align = 'center'; 17 | } 18 | render() { 19 | return html ` 20 | 43 |
44 | 45 |
46 | `; 47 | } 48 | updated(propVals) { 49 | super.updated(propVals); 50 | const s = this.style; 51 | switch (this.align) { 52 | case 'right': 53 | s.setProperty('--math-over-align', 'right'); 54 | break; 55 | case 'left': 56 | s.setProperty('--math-over-align', 'left'); 57 | break; 58 | default: 59 | s.setProperty('--math-over-align', 'center'); 60 | break; 61 | } 62 | s.setProperty('--math-over-font-size', this.accent ? '1em' : '0.8em'); 63 | } 64 | }; 65 | __decorate([ 66 | property({ type: Boolean, reflect: true }), 67 | __metadata("design:type", Object) 68 | ], MathOverElement.prototype, "accent", void 0); 69 | __decorate([ 70 | property(), 71 | __metadata("design:type", String) 72 | ], MathOverElement.prototype, "align", void 0); 73 | MathOverElement = __decorate([ 74 | customElement('math-over') 75 | ], MathOverElement); 76 | export { MathOverElement }; 77 | -------------------------------------------------------------------------------- /dist/mroot.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | import { HorizFlex } from './styles/common-styles.js'; 9 | let MathRootElement = class MathRootElement extends MathMLElement { 10 | render() { 11 | return html ` 12 | 49 |
50 |
51 |
52 |
53 | `; 54 | } 55 | updated(propVals) { 56 | super.updated(propVals); 57 | this.onSlotCange(); 58 | } 59 | onSlotCange() { 60 | if (!this.shadowRoot) { 61 | return; 62 | } 63 | const slot = this.shadowRoot.querySelector('slot'); 64 | if (!slot) { 65 | return; 66 | } 67 | setTimeout(() => { 68 | this.drawRoot(); 69 | }, 10); 70 | } 71 | drawRoot() { 72 | const span = this.shadowRoot.querySelector('#msqrtGlyphSpan'); 73 | const path = this.shadowRoot.querySelector('#rootPath'); 74 | if (span && path) { 75 | const size = span.getBoundingClientRect(); 76 | const width = size.width; 77 | const height = size.height; 78 | const d = `M0 ${height * 0.55} H${width * 0.13} L${width * 0.45} ${height - 2} L${width} 0`; 79 | path.setAttribute('d', d); 80 | } 81 | } 82 | }; 83 | MathRootElement = __decorate([ 84 | customElement('math-root') 85 | ], MathRootElement); 86 | export { MathRootElement }; 87 | -------------------------------------------------------------------------------- /dist/mpadded.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | let MathPaddedElement = class MathPaddedElement extends MathMLElement { 12 | render() { 13 | return html ` 14 | 21 |
22 | `; 23 | } 24 | updated(propVals) { 25 | super.updated(propVals); 26 | this.refresh(); 27 | } 28 | refresh() { 29 | if (!this.shadowRoot) { 30 | return; 31 | } 32 | const panel = this.shadowRoot.querySelector('#mpaddedPanel'); 33 | if (!panel) { 34 | return; 35 | } 36 | setTimeout(() => { 37 | const size = panel.getBoundingClientRect(); 38 | if (this.height) { 39 | if (this.height.charAt(0) === '+') { 40 | this.style.paddingTop = this.height.substring(1); 41 | } 42 | else if (this.height.charAt(0) === '-') { 43 | this.style.height = `calc(${size.height}px - ${this.height.substring(1)})`; 44 | this.style.paddingTop = '0'; 45 | } 46 | else { 47 | this.style.height = this.height; 48 | this.style.paddingTop = '0'; 49 | } 50 | } 51 | else { 52 | this.style.height = 'auto'; 53 | this.style.paddingTop = '0'; 54 | } 55 | if (this.width) { 56 | if (this.width.charAt(0) === '+' || this.width.charAt(0) === '-') { 57 | this.style.width = `calc(${size.width}px + ${this.width.substring(1)})`; 58 | } 59 | else { 60 | this.style.width = this.width; 61 | } 62 | } 63 | else { 64 | this.style.width = 'auto'; 65 | } 66 | }, 50); 67 | } 68 | }; 69 | __decorate([ 70 | property({ type: String }), 71 | __metadata("design:type", String) 72 | ], MathPaddedElement.prototype, "height", void 0); 73 | __decorate([ 74 | property({ type: String }), 75 | __metadata("design:type", String) 76 | ], MathPaddedElement.prototype, "width", void 0); 77 | MathPaddedElement = __decorate([ 78 | customElement('math-padded') 79 | ], MathPaddedElement); 80 | export { MathPaddedElement }; 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Math-ML 3 | 4 | ![MathML example](https://i.imgur.com/NZvMjWM.png) 5 | 6 | A small-ish (compared to alternatives ~ 12kb gzipped) implementation of [MathML](https://developer.mozilla.org/en-US/docs/Web/MathML) using custom-elements. 7 | 8 | MathML has been part of part of the HTML5 spec for some time now, but many browsers don't support it (Chrome, for example). This is a simple attempt to use basic javascript, CSS and some SVG to implement MathML compatible notation that works across all browsers. _(All rendering is done on the client side)._ 9 | 10 | ## Implementation 11 | 12 | Math-ML is implemented using custom elements. There's a corresponding element for every MathML node. The root `` node is replaced by ``. For all other nodes, the prefix `m` is replaces with `math-`. For example, `` becomes `` and `` becomes ``. 13 | 14 | This is available as a polyfill as well. If MathML is not detected on the browser (every browser except Firefox), the polyfill replaces all `` nodes with corresponding `` nodes. 15 | 16 | _Note: It's not feature complete with the MathML spec, but supports most complicates cases as seen in the [Torture Test](https://pshihn.github.io/math-ml/examples/torture.html)._ 17 | 18 | ## Usage 19 | 20 | Install from npm: 21 | ``` 22 | npm install --save mathml-elements 23 | ``` 24 | 25 | or simply from unpkg: 26 | 27 | ```html 28 | 29 | ``` 30 | 31 | To create the following expression: 32 | ![MathML example](https://mdn.mozillademos.org/files/3076/ex1.png) 33 | 34 | Using Math-ML components: 35 | ```html 36 | 37 | 38 | 39 | x2 40 | 41 | 42 | y2 43 | 44 | 45 | 46 | ``` 47 | 48 | Raw MathML version: 49 | ```html 50 | 51 | 52 | 53 | x2 54 | 55 | 56 | y2 57 | 58 | 59 | 60 | ``` 61 | 62 | ## As a MathML Polyfill 63 | 64 | Math-ML comes with a polyfill that will check if your browser has built in MathML support. If not, then it replaces all MathML elements with Math-ML custom elements. 65 | 66 | To use the polyfill: 67 | 68 | ```html 69 | 70 | ``` 71 | 72 | ## Examples 73 | 74 | These examples are ported versions from [Mozilla Dev Network](https://developer.mozilla.org/en-US/docs/Web/MathML/Examples). 75 | 76 | [Proving the Pythagorean theorem](https://pshihn.github.io/math-ml/examples/pythagorean-theorem.html) 77 | 78 | [Deriving the Quadratic Formula](https://pshihn.github.io/math-ml/examples/quadratic-formula.html) 79 | 80 | [Torture Test](https://pshihn.github.io/math-ml/examples/torture.html) 81 | 82 | 83 | ## Custom Element support 84 | 85 | While most browsers (Chrome, Firefox, Safari) support custom elements, incluse the web-components polyfill to enabled them in unsupported ones 86 | 87 | ```html 88 | 89 | ``` 90 | 91 | ## License 92 | [MIT License](https://github.com/pshihn/windtalk/blob/master/LICENSE) (c) [Preet Shihn](https://twitter.com/preetster) 93 | -------------------------------------------------------------------------------- /src/munderover.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, PropertyValues, html, TemplateResult, customElement, property, MathAlignType } from './mathml-element.js'; 2 | import { VertFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-underover') 5 | export class MathUnderOverElement extends MathMLElement { 6 | @property({ type: Boolean, reflect: true }) accent = false; 7 | @property({ type: Boolean, reflect: true }) accentunder = false; 8 | @property() align: MathAlignType = 'center'; 9 | 10 | render(): TemplateResult { 11 | return html` 12 | 47 |
48 |
49 | 50 |
51 | `; 52 | } 53 | 54 | updated(propVals: PropertyValues) { 55 | super.updated(propVals); 56 | const s = this.style; 57 | switch (this.align) { 58 | case 'right': 59 | s.setProperty('--math-underover-align', 'right'); 60 | break; 61 | case 'left': 62 | s.setProperty('--math-underover-align', 'left'); 63 | break; 64 | default: 65 | s.setProperty('--math-underover-align', 'center'); 66 | break; 67 | } 68 | s.setProperty('--math-under-font-size', this.accentunder ? '1em' : '0.75em'); 69 | s.setProperty('--math-over-font-size', this.accent ? '1em' : '0.75em'); 70 | this.refreshSlot(); 71 | } 72 | 73 | private refreshSlot() { 74 | if (!this.shadowRoot) { 75 | return; 76 | } 77 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 78 | if (!slot) { 79 | return; 80 | } 81 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 82 | if (nodes.length) { 83 | const panel = this.shadowRoot.querySelector('#muoPanel') as HTMLElement; 84 | while (panel.firstChild) { 85 | panel.removeChild(panel.firstChild); 86 | } 87 | if (nodes.length > 2) { 88 | (nodes[2] as HTMLElement).classList.add('over'); 89 | panel.appendChild(nodes[2]); 90 | } 91 | (nodes[0] as HTMLElement).classList.add('base'); 92 | panel.append(nodes[0]); 93 | if (nodes.length > 1) { 94 | (nodes[1] as HTMLElement).classList.add('under'); 95 | panel.appendChild(nodes[1]); 96 | } 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /src/mfenced.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement, property, PropertyValues } from './mathml-element.js'; 2 | import { HorizCenterFlex } from './styles/common-styles.js'; 3 | import { MathOElement } from './mo.js'; 4 | import './mo.js'; 5 | 6 | @customElement('math-fenced') 7 | export class MathFencedElement extends MathMLElement { 8 | @property({ type: String }) close = ')'; 9 | @property({ type: String }) open = '('; 10 | @property({ type: String }) separators = ','; 11 | 12 | render(): TemplateResult { 13 | return html` 14 | 25 |
26 |
27 | 28 |
29 | `; 30 | } 31 | 32 | updated(propVals: PropertyValues) { 33 | super.updated(propVals); 34 | this.refreshSlot(); 35 | } 36 | 37 | private isStretchyString(text: string): boolean { 38 | if (text.match(/^[0-9a-zA-Z,;\-_`'"]*$/)) { 39 | return false; 40 | } 41 | return true; 42 | } 43 | 44 | private nextSeparator(index: number): string | null { 45 | if (index >= 0) { 46 | if (this.separators.length) { 47 | if (index < this.separators.length) { 48 | return this.separators.charAt(index); 49 | } 50 | return this.separators.charAt(this.separators.length - 1); 51 | } 52 | } 53 | return null; 54 | } 55 | 56 | private refreshSlot() { 57 | if (!this.shadowRoot) { 58 | return; 59 | } 60 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 61 | const panel = this.shadowRoot.querySelector('#mfencedRow') as HTMLElement; 62 | if (!slot || !panel) { 63 | return; 64 | } 65 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 66 | if (nodes.length) { 67 | while (panel.firstChild) { 68 | panel.removeChild(panel.firstChild); 69 | } 70 | let sepIndex = 0; 71 | for (let i = 0; i < nodes.length; i++) { 72 | // opener 73 | if (i === 0 && this.open) { 74 | const mo = new MathOElement(); 75 | if (this.isStretchyString(this.open.trim())) { 76 | mo.stretchy = 'true'; 77 | } 78 | mo.textContent = this.open; 79 | panel.appendChild(mo); 80 | } 81 | // item 82 | panel.appendChild(nodes[i]); 83 | // separator 84 | if (i < (nodes.length - 1)) { 85 | const sep = this.nextSeparator(sepIndex); 86 | if (sep) { 87 | sepIndex++; 88 | const mo = new MathOElement(); 89 | if (this.isStretchyString(sep)) { 90 | mo.stretchy = 'true'; 91 | } 92 | mo.textContent = sep; 93 | panel.appendChild(mo); 94 | } 95 | } 96 | if (i === (nodes.length - 1) && this.close) { 97 | const mo = new MathOElement(); 98 | if (this.isStretchyString(this.close.trim())) { 99 | mo.stretchy = 'true'; 100 | } 101 | mo.textContent = this.close; 102 | panel.appendChild(mo); 103 | } 104 | } 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /dist/mrow.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | import { HorizFlex } from './styles/common-styles.js'; 9 | let MathRowElement = class MathRowElement extends MathMLElement { 10 | render() { 11 | return html ` 12 | 31 |
32 | `; 33 | } 34 | onSlotChange() { 35 | if (!this.shadowRoot) { 36 | return; 37 | } 38 | const slot = this.shadowRoot.querySelector('slot'); 39 | const panel = this.shadowRoot.querySelector('#mrowPanel'); 40 | if (!slot || !panel) { 41 | return; 42 | } 43 | panel.classList.remove('centered'); 44 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 45 | let opCount = 0; 46 | let centeringNodeCount = 0; 47 | let center = false; 48 | for (let i = 0; i < nodes.length; i++) { 49 | const text = (nodes[i].textContent || '').trim(); 50 | if (text === '=') { 51 | center = true; 52 | break; 53 | } 54 | const tagName = nodes[i].tagName.toLowerCase(); 55 | switch (tagName) { 56 | case 'math-underover': 57 | case 'math-under': 58 | case 'math-over': 59 | case 'math-subsup': 60 | centeringNodeCount++; 61 | break; 62 | case 'math-o': 63 | opCount++; 64 | break; 65 | case 'math-table': 66 | center = true; 67 | break; 68 | default: 69 | break; 70 | } 71 | } 72 | if (!center) { 73 | if (centeringNodeCount && (!opCount)) { 74 | center = true; 75 | } 76 | } 77 | if (center) { 78 | panel.classList.add('centered'); 79 | } 80 | panel.classList.remove('justified'); 81 | if ((getComputedStyle(this).getPropertyValue('--math-underover-align') || '').trim() === 'center' 82 | || (getComputedStyle(this).getPropertyValue('--math-under-align') || '').trim() === 'center' 83 | || (getComputedStyle(this).getPropertyValue('--math-over-align') || '').trim() === 'center') { 84 | panel.classList.add('justified'); 85 | } 86 | } 87 | }; 88 | MathRowElement = __decorate([ 89 | customElement('math-row') 90 | ], MathRowElement); 91 | export { MathRowElement }; 92 | -------------------------------------------------------------------------------- /dist/msubsup.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | import { HorizFlex } from './styles/common-styles.js'; 9 | let MathSubSupElement = class MathSubSupElement extends MathMLElement { 10 | constructor() { 11 | super(...arguments); 12 | this.pendingLayout = false; 13 | } 14 | render() { 15 | return html ` 16 | 36 |
37 | 38 |
39 | `; 40 | } 41 | refreshSlot() { 42 | if (this.pendingLayout) { 43 | return; 44 | } 45 | if (!this.shadowRoot) { 46 | return; 47 | } 48 | const slot = this.shadowRoot.querySelector('slot'); 49 | if (!slot) { 50 | return; 51 | } 52 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 53 | if (nodes.length > 2) { 54 | this.pendingLayout = true; 55 | const runnable = () => { 56 | const s1 = nodes[0].getBoundingClientRect(); 57 | const subNode = nodes[1]; 58 | const supNode = nodes[2]; 59 | const subSize = subNode.getBoundingClientRect(); 60 | const supSize = supNode.getBoundingClientRect(); 61 | subNode.style.opacity = '1'; 62 | supNode.style.opacity = '1'; 63 | const margins = [0, 0, 0]; 64 | // sub 65 | const hh = s1.height / 2; 66 | let db = hh; 67 | if ((hh + subSize.height) < s1.height) { 68 | db = s1.height - subSize.height; 69 | } 70 | else { 71 | margins[2] = (hh + subSize.height) - s1.height; 72 | } 73 | subNode.style.top = `${db}px`; 74 | margins[1] = subSize.width + 5; 75 | // sup 76 | db = supSize.bottom - (s1.bottom - (s1.height / 2)); 77 | if (db > 0) { 78 | supNode.style.top = `${-db}px`; 79 | margins[0] = db; 80 | } 81 | margins[1] = Math.max(supSize.width + 5, margins[1]); 82 | this.style.margin = `${margins[0]}px ${margins[1]}px ${margins[2]}px 0`; 83 | }; 84 | setTimeout(runnable, 50); 85 | setTimeout(() => { 86 | this.pendingLayout = false; 87 | runnable(); 88 | }, 500); 89 | } 90 | } 91 | }; 92 | MathSubSupElement = __decorate([ 93 | customElement('math-subsup') 94 | ], MathSubSupElement); 95 | export { MathSubSupElement }; 96 | -------------------------------------------------------------------------------- /src/mtable.ts: -------------------------------------------------------------------------------- 1 | import { html, PropertyValues, TemplateResult, customElement, property, MathBorderType } from './mathml-element.js'; 2 | import { MathTableBaseElement } from './mtable-base.js'; 3 | 4 | @customElement('math-table') 5 | export class MathTableElement extends MathTableBaseElement { 6 | @property({ type: String }) columnlines?: MathBorderType = 'none'; 7 | @property({ type: String }) rowlines?: MathBorderType = 'none'; 8 | @property({ type: String }) frame?: MathBorderType = 'none'; 9 | @property({ type: String }) columnspacing = '0.8em'; 10 | @property({ type: String }) rowspacing = '0.8em'; 11 | @property({ type: String }) framespacing = '0.4em 0.5ex'; 12 | @property({ type: String }) width?: string; 13 | 14 | constructor() { 15 | super(); 16 | this.columnalign = this.columnalign || 'center'; 17 | } 18 | 19 | render(): TemplateResult { 20 | return html` 21 | 34 | 35 | `; 36 | } 37 | 38 | updated(propVals: PropertyValues) { 39 | super.updated(propVals); 40 | this.updateAlignment(); 41 | const s = this.style; 42 | if (this.frame) { 43 | switch (this.frame) { 44 | case 'none': 45 | s.setProperty('--math-table-border', 'none'); 46 | break; 47 | case 'solid': 48 | s.setProperty('--math-table-border', 'solid thin'); 49 | break; 50 | case 'dashed': 51 | s.setProperty('--math-table-border', 'dashed thin'); 52 | break; 53 | default: 54 | s.removeProperty('--math-table-border'); 55 | break; 56 | } 57 | } 58 | if (this.rowlines) { 59 | switch (this.rowlines) { 60 | case 'none': 61 | s.setProperty('--math-table-row-border', 'none'); 62 | break; 63 | case 'solid': 64 | s.setProperty('--math-table-row-border', 'solid thin'); 65 | break; 66 | case 'dashed': 67 | s.setProperty('--math-table-row-border', 'dashed thin'); 68 | break; 69 | default: 70 | s.removeProperty('--math-table-row-border'); 71 | break; 72 | } 73 | } 74 | if (this.columnlines) { 75 | switch (this.columnlines) { 76 | case 'none': 77 | s.setProperty('--math-table-column-border', 'none'); 78 | break; 79 | case 'solid': 80 | s.setProperty('--math-table-column-border', 'solid thin'); 81 | break; 82 | case 'dashed': 83 | s.setProperty('--math-table-column-border', 'dashed thin'); 84 | break; 85 | default: 86 | s.removeProperty('--math-table-column-border'); 87 | break; 88 | } 89 | } 90 | 91 | if (this.framespacing) { 92 | const split = this.framespacing.split(' ').reverse(); 93 | s.setProperty('--math-table-padding', split.join(' ')); 94 | } else { 95 | s.removeProperty('--math-table-padding'); 96 | } 97 | 98 | if (this.width) { 99 | s.setProperty('--math-table-width', this.width); 100 | } else { 101 | s.removeProperty('--math-table-width'); 102 | } 103 | 104 | if (this.columnspacing) { 105 | s.setProperty('--math-table-columnspacing', this.columnspacing); 106 | } else { 107 | s.removeProperty('--math-table-columnspacing'); 108 | } 109 | 110 | if (this.rowspacing) { 111 | s.setProperty('--math-table-rowspacing', this.columnspacing); 112 | } else { 113 | s.removeProperty('--math-table-rowspacing'); 114 | } 115 | 116 | if (this.columnalign) { 117 | const split = this.columnalign.trim().split(' ').filter((d) => { 118 | if (d.trim()) { 119 | return true; 120 | } 121 | return false; 122 | }); 123 | if (split.length > 1) { 124 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 125 | if (slot) { 126 | slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE).filter((d) => { 127 | return (d as HTMLElement).tagName === 'MATH-TR' || (d as HTMLElement).tagName === 'MATH-LABELEDTR'; 128 | }).forEach((d) => { 129 | const row = (d as MathTableBaseElement); 130 | row.columnalign = row.columnalign || (this.columnalign!).trim(); 131 | }); 132 | } 133 | } 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /dist/munderover.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | import { VertFlex } from './styles/common-styles.js'; 12 | let MathUnderOverElement = class MathUnderOverElement extends MathMLElement { 13 | constructor() { 14 | super(...arguments); 15 | this.accent = false; 16 | this.accentunder = false; 17 | this.align = 'center'; 18 | } 19 | render() { 20 | return html ` 21 | 56 |
57 |
58 | 59 |
60 | `; 61 | } 62 | updated(propVals) { 63 | super.updated(propVals); 64 | const s = this.style; 65 | switch (this.align) { 66 | case 'right': 67 | s.setProperty('--math-underover-align', 'right'); 68 | break; 69 | case 'left': 70 | s.setProperty('--math-underover-align', 'left'); 71 | break; 72 | default: 73 | s.setProperty('--math-underover-align', 'center'); 74 | break; 75 | } 76 | s.setProperty('--math-under-font-size', this.accentunder ? '1em' : '0.75em'); 77 | s.setProperty('--math-over-font-size', this.accent ? '1em' : '0.75em'); 78 | this.refreshSlot(); 79 | } 80 | refreshSlot() { 81 | if (!this.shadowRoot) { 82 | return; 83 | } 84 | const slot = this.shadowRoot.querySelector('slot'); 85 | if (!slot) { 86 | return; 87 | } 88 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 89 | if (nodes.length) { 90 | const panel = this.shadowRoot.querySelector('#muoPanel'); 91 | while (panel.firstChild) { 92 | panel.removeChild(panel.firstChild); 93 | } 94 | if (nodes.length > 2) { 95 | nodes[2].classList.add('over'); 96 | panel.appendChild(nodes[2]); 97 | } 98 | nodes[0].classList.add('base'); 99 | panel.append(nodes[0]); 100 | if (nodes.length > 1) { 101 | nodes[1].classList.add('under'); 102 | panel.appendChild(nodes[1]); 103 | } 104 | } 105 | } 106 | }; 107 | __decorate([ 108 | property({ type: Boolean, reflect: true }), 109 | __metadata("design:type", Object) 110 | ], MathUnderOverElement.prototype, "accent", void 0); 111 | __decorate([ 112 | property({ type: Boolean, reflect: true }), 113 | __metadata("design:type", Object) 114 | ], MathUnderOverElement.prototype, "accentunder", void 0); 115 | __decorate([ 116 | property(), 117 | __metadata("design:type", String) 118 | ], MathUnderOverElement.prototype, "align", void 0); 119 | MathUnderOverElement = __decorate([ 120 | customElement('math-underover') 121 | ], MathUnderOverElement); 122 | export { MathUnderOverElement }; 123 | -------------------------------------------------------------------------------- /src/mo.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement, property, PropertyValues } from './mathml-element.js'; 2 | 3 | export declare type MathOperatorForm = 'prefix' | 'infix' | 'postfix'; 4 | 5 | @customElement('math-o') 6 | export class MathOElement extends MathMLElement { 7 | @property({ type: String }) form?: MathOperatorForm; 8 | @property({ type: String }) stretchy?: string; 9 | 10 | private formStyle = ''; 11 | 12 | render(): TemplateResult { 13 | return html` 14 | 63 | 64 | `; 65 | } 66 | 67 | updated(propVals: PropertyValues) { 68 | super.updated(propVals); 69 | this.onSlotChange(); 70 | } 71 | 72 | private onSlotChange() { 73 | if (!this.shadowRoot) { 74 | return; 75 | } 76 | const span = this.shadowRoot.querySelector('span'); 77 | if (!span) { 78 | return; 79 | } 80 | let specialRule = ''; 81 | const text = (this.textContent || '').trim(); 82 | if (text === ',' || text === ';') { 83 | specialRule = 'separator'; 84 | } else if (text === '.' || text === '⋅') { 85 | specialRule = 'product'; 86 | } else if (text.match(/^[\[{(]*$/)) { 87 | specialRule = 'begin-brace'; 88 | } else if (text.match(/^[\]})]*$/)) { 89 | specialRule = 'end-brace'; 90 | } else if (text.match(/^[|]*$/)) { 91 | specialRule = 'neut-brace'; 92 | } 93 | 94 | // bigger text for math ops 95 | this.classList.remove('mo-bigger'); 96 | if (text && (0x2200 <= text.charCodeAt(0)) && (text.charCodeAt(0) <= 0x2233)) { 97 | if ((getComputedStyle(this).getPropertyValue('--math-style-level') || '').trim() !== 'sub') { 98 | this.classList.add('mo-bigger'); 99 | } 100 | } 101 | 102 | const newFormStyle = specialRule || 'infix'; 103 | if (this.formStyle !== newFormStyle) { 104 | if (this.formStyle) { 105 | this.classList.remove(this.formStyle); 106 | } 107 | this.formStyle = `mo-${newFormStyle}`; 108 | this.classList.add(this.formStyle); 109 | } 110 | let effectiveStretch = this.stretchy && this.stretchy.trim().toLowerCase() === 'true'; 111 | if (!this.stretchy) { 112 | if (getComputedStyle(this).getPropertyValue('--math-style-stretchy').trim() === 'true') { 113 | effectiveStretch = true; 114 | } else { 115 | effectiveStretch = specialRule === 'begin-brace' || specialRule === 'end-brace' || specialRule === 'neut-brace'; 116 | } 117 | } 118 | span.style.width = null; 119 | if (!effectiveStretch) { 120 | span.classList.add('fullWidthSpan'); 121 | this.classList.remove('mo-stretchy'); 122 | span.style.transform = null; 123 | span.style.lineHeight = null; 124 | span.classList.remove('invisible'); 125 | } else { 126 | span.classList.remove('fullWidthSpan'); 127 | this.classList.add('mo-stretchy'); 128 | span.style.lineHeight = '1'; 129 | setTimeout(() => { 130 | if (span.style.transform) { 131 | return; 132 | } 133 | span.classList.remove('invisible'); 134 | const spanSize = span.getBoundingClientRect(); 135 | const size = this.getBoundingClientRect(); 136 | const scaleY = spanSize.height ? (size.height / spanSize.height) : 1; 137 | const scaleX = spanSize.width ? (size.width / spanSize.width) : 1; 138 | if (scaleY <= 1) { 139 | span.style.lineHeight = null; 140 | } 141 | if (scaleX !== 1) { 142 | span.style.width = '100%'; 143 | } 144 | span.style.transform = `scale(${scaleX}, ${scaleY})`; 145 | }, 50); 146 | } 147 | } 148 | } -------------------------------------------------------------------------------- /dist/mfenced.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | import { HorizCenterFlex } from './styles/common-styles.js'; 12 | import { MathOElement } from './mo.js'; 13 | import './mo.js'; 14 | let MathFencedElement = class MathFencedElement extends MathMLElement { 15 | constructor() { 16 | super(...arguments); 17 | this.close = ')'; 18 | this.open = '('; 19 | this.separators = ','; 20 | } 21 | render() { 22 | return html ` 23 | 34 |
35 |
36 | 37 |
38 | `; 39 | } 40 | updated(propVals) { 41 | super.updated(propVals); 42 | this.refreshSlot(); 43 | } 44 | isStretchyString(text) { 45 | if (text.match(/^[0-9a-zA-Z,;\-_`'"]*$/)) { 46 | return false; 47 | } 48 | return true; 49 | } 50 | nextSeparator(index) { 51 | if (index >= 0) { 52 | if (this.separators.length) { 53 | if (index < this.separators.length) { 54 | return this.separators.charAt(index); 55 | } 56 | return this.separators.charAt(this.separators.length - 1); 57 | } 58 | } 59 | return null; 60 | } 61 | refreshSlot() { 62 | if (!this.shadowRoot) { 63 | return; 64 | } 65 | const slot = this.shadowRoot.querySelector('slot'); 66 | const panel = this.shadowRoot.querySelector('#mfencedRow'); 67 | if (!slot || !panel) { 68 | return; 69 | } 70 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 71 | if (nodes.length) { 72 | while (panel.firstChild) { 73 | panel.removeChild(panel.firstChild); 74 | } 75 | let sepIndex = 0; 76 | for (let i = 0; i < nodes.length; i++) { 77 | // opener 78 | if (i === 0 && this.open) { 79 | const mo = new MathOElement(); 80 | if (this.isStretchyString(this.open.trim())) { 81 | mo.stretchy = 'true'; 82 | } 83 | mo.textContent = this.open; 84 | panel.appendChild(mo); 85 | } 86 | // item 87 | panel.appendChild(nodes[i]); 88 | // separator 89 | if (i < (nodes.length - 1)) { 90 | const sep = this.nextSeparator(sepIndex); 91 | if (sep) { 92 | sepIndex++; 93 | const mo = new MathOElement(); 94 | if (this.isStretchyString(sep)) { 95 | mo.stretchy = 'true'; 96 | } 97 | mo.textContent = sep; 98 | panel.appendChild(mo); 99 | } 100 | } 101 | if (i === (nodes.length - 1) && this.close) { 102 | const mo = new MathOElement(); 103 | if (this.isStretchyString(this.close.trim())) { 104 | mo.stretchy = 'true'; 105 | } 106 | mo.textContent = this.close; 107 | panel.appendChild(mo); 108 | } 109 | } 110 | } 111 | } 112 | }; 113 | __decorate([ 114 | property({ type: String }), 115 | __metadata("design:type", Object) 116 | ], MathFencedElement.prototype, "close", void 0); 117 | __decorate([ 118 | property({ type: String }), 119 | __metadata("design:type", Object) 120 | ], MathFencedElement.prototype, "open", void 0); 121 | __decorate([ 122 | property({ type: String }), 123 | __metadata("design:type", Object) 124 | ], MathFencedElement.prototype, "separators", void 0); 125 | MathFencedElement = __decorate([ 126 | customElement('math-fenced') 127 | ], MathFencedElement); 128 | export { MathFencedElement }; 129 | -------------------------------------------------------------------------------- /src/mmultiscripts.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement } from './mathml-element.js'; 2 | import { AllFlex } from './styles/common-styles.js'; 3 | 4 | @customElement('math-multiscripts') 5 | export class MathMultiScriptsElement extends MathMLElement { 6 | private pendingLayout = false; 7 | render(): TemplateResult { 8 | return html` 9 | 34 |
35 | 36 |
37 | `; 38 | } 39 | 40 | private refreshSlot() { 41 | if (this.pendingLayout) { 42 | return; 43 | } 44 | if (!this.shadowRoot) { 45 | return; 46 | } 47 | const slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement; 48 | if (!slot) { 49 | return; 50 | } 51 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 52 | if (nodes.length === 1 && ((nodes[0] as HTMLElement).tagName === 'math-prescripts'.toUpperCase())) { 53 | return; 54 | } 55 | 56 | if (nodes.length > 2) { 57 | this.pendingLayout = true; 58 | const runnable = () => { 59 | const postNodes: (HTMLElement | null)[] = [null, null]; 60 | const preNodes: (HTMLElement | null)[] = [null, null]; 61 | let current = postNodes; 62 | for (let i = 1; i < nodes.length; i++) { 63 | const n = nodes[i] as HTMLElement; 64 | if (n.tagName === 'math-prescripts'.toUpperCase()) { 65 | current = preNodes; 66 | } else { 67 | if (!current[0]) { 68 | current[0] = n; 69 | } else if (!current[1]) { 70 | current[1] = n; 71 | } 72 | } 73 | } 74 | const s1 = (nodes[0] as HTMLElement).getBoundingClientRect(); 75 | const margins = [0, 0, 0, 0]; 76 | // do post 77 | { 78 | // sub 79 | if (postNodes[0]) { 80 | const subNode = postNodes[0] as HTMLElement; 81 | const subSize = subNode.getBoundingClientRect(); 82 | subNode.style.opacity = '1'; 83 | subNode.classList.add('rightscript'); 84 | const hh = s1.height / 2; 85 | let db = hh; 86 | if ((hh + subSize.height) < s1.height) { 87 | db = s1.height - subSize.height; 88 | } else { 89 | margins[2] = (hh + subSize.height) - s1.height; 90 | } 91 | subNode.style.top = `${db}px`; 92 | margins[1] = subSize.width + 5; 93 | } 94 | // sup 95 | if (postNodes[1]) { 96 | const supNode = postNodes[1] as HTMLElement; 97 | supNode.style.opacity = '1'; 98 | supNode.classList.add('rightscript'); 99 | const supSize = supNode.getBoundingClientRect(); 100 | const db = supSize.bottom - (s1.bottom - (s1.height / 2)); 101 | if (db > 0) { 102 | supNode.style.top = `${-db}px`; 103 | margins[0] = db; 104 | } 105 | margins[1] = Math.max(supSize.width + 5, margins[1]); 106 | } 107 | } 108 | // do pre 109 | { 110 | // sub 111 | if (preNodes[0]) { 112 | const subNode = preNodes[0] as HTMLElement; 113 | const subSize = subNode.getBoundingClientRect(); 114 | subNode.style.opacity = '1'; 115 | subNode.classList.add('leftscript'); 116 | const hh = s1.height / 2; 117 | let db = hh; 118 | if ((hh + subSize.height) < s1.height) { 119 | db = s1.height - subSize.height; 120 | } else { 121 | margins[2] = Math.max((hh + subSize.height) - s1.height, margins[2]); 122 | } 123 | subNode.style.top = `${db}px`; 124 | margins[3] = Math.max(subSize.width + 5, margins[3]); 125 | } 126 | // sup 127 | if (preNodes[1]) { 128 | const supNode = preNodes[1] as HTMLElement; 129 | supNode.style.opacity = '1'; 130 | supNode.classList.add('leftscript'); 131 | const supSize = supNode.getBoundingClientRect(); 132 | const db = supSize.bottom - (s1.bottom - (s1.height / 2)); 133 | if (db > 0) { 134 | supNode.style.top = `${-db}px`; 135 | margins[0] = Math.max(db, margins[0]); 136 | } 137 | margins[3] = Math.max(supSize.width + 5, margins[3]); 138 | } 139 | } 140 | this.style.margin = `${margins[0]}px ${margins[1]}px ${margins[2]}px ${margins[3]}px`; 141 | }; 142 | setTimeout(runnable, 100); 143 | setTimeout(() => { 144 | this.pendingLayout = false; 145 | runnable(); 146 | }, 800); 147 | } 148 | } 149 | } -------------------------------------------------------------------------------- /src/mfrac.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement, property, MathAlignType, PropertyValues } from './mathml-element.js'; 2 | 3 | @customElement('math-frac') 4 | export class MathFracElement extends MathMLElement { 5 | @property({ type: Boolean }) bevelled = false; 6 | @property({ type: String }) numalign: MathAlignType = 'center'; 7 | @property({ type: String }) denomalign: MathAlignType = 'center'; 8 | @property({ type: String }) linethickness?: string; 9 | 10 | render(): TemplateResult { 11 | let bevelledDivStyle = 'stroke-width: 1;'; 12 | let unbevelledDivStyle = 'border-top: solid thin;'; 13 | if (this.linethickness && (this.linethickness.trim().charAt(0) === '0')) { 14 | bevelledDivStyle = 'stroke-width: 0;'; 15 | unbevelledDivStyle = ''; 16 | } 17 | return html` 18 | 81 |
82 |
83 | 84 |
85 |
86 |
87 |
88 | `; 89 | } 90 | 91 | updated(propVals: PropertyValues) { 92 | super.updated(propVals); 93 | this.refreshSlot(); 94 | } 95 | 96 | private refreshSlot() { 97 | if (!this.shadowRoot) { 98 | return; 99 | } 100 | const slot = this.shadowRoot.querySelector('slot'); 101 | if (!slot) { 102 | return; 103 | } 104 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 105 | if (nodes.length > 1) { 106 | const nu = this.shadowRoot.querySelector('#mfracN') as HTMLElement; 107 | const de = this.shadowRoot.querySelector('#mfracD') as HTMLElement; 108 | nu.appendChild(nodes[0]); 109 | de.appendChild(nodes[1]); 110 | for (let i = 2; i < nodes.length; i++) { 111 | if (nodes[i].parentElement) { 112 | nodes[i].parentElement!.removeChild(nodes[i]); 113 | } 114 | } 115 | } 116 | this.updateBevlled(); 117 | } 118 | 119 | private updateBevlled() { 120 | const panel = this.shadowRoot!.querySelector('#mfracPanel') as HTMLElement; 121 | const nu = this.shadowRoot!.querySelector('#mfracN') as HTMLElement; 122 | const de = this.shadowRoot!.querySelector('#mfracD') as HTMLElement; 123 | const bevelledDivider = this.shadowRoot!.querySelector('#bevelledDivider') as HTMLElement; 124 | const unbevelledDivider = this.shadowRoot!.querySelector('#unbevelledDivider') as HTMLElement; 125 | 126 | nu.style.textAlign = this.numalign; 127 | de.style.textAlign = this.denomalign; 128 | if (this.bevelled) { 129 | panel.classList.remove('unbevelled'); 130 | panel.classList.add('bevelled'); 131 | bevelledDivider.classList.remove('hidden'); 132 | unbevelledDivider.classList.add('hidden'); 133 | setTimeout(() => { 134 | this.drawBevelledDivider(); 135 | }, 10); 136 | } else { 137 | panel.classList.remove('bevelled'); 138 | panel.classList.add('unbevelled'); 139 | bevelledDivider.classList.add('hidden'); 140 | unbevelledDivider.classList.remove('hidden'); 141 | } 142 | } 143 | 144 | private drawBevelledDivider() { 145 | const span = this.shadowRoot!.querySelector('#bevelledDivider'); 146 | const path = this.shadowRoot!.querySelector('#bevelledPath'); 147 | if (span && path) { 148 | const size = (span as HTMLElement).getBoundingClientRect(); 149 | const width = size.width; 150 | const height = size.height; 151 | const d = `M0 ${height} L${width} 0`; 152 | path.setAttribute('d', d); 153 | } 154 | } 155 | } -------------------------------------------------------------------------------- /examples/pythagorean-theorem.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Math-ML: Proving the Pythagorean theorem 8 | 42 | 43 | 44 | 45 | 46 | 52 | 53 | 54 | 55 |
56 |

Math-ML: Proving the Pythagorean theorem

57 |

We will now prove the Pythogorian theorem:

58 | 59 |

Statement: In a right angled triangle, the square of the hypotenuse is equal to the sum of the 60 | squares of the other two sides.

61 | 62 |

i.e, If a and b are the legs and c is the hypotenuse then 63 | 64 | 65 | a 66 | 2 67 | 68 | + 69 | 70 | b 71 | 2 72 | 73 | = 74 | 75 | c 76 | 2 77 | 78 | 79 | .

80 |

Proof: We can prove the theorem algebraically by showing that the area of the big square 81 | equals the area of the inner square (hypotenuse squared) plus the area of the four triangles: 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | ( 90 | a 91 | + 92 | b 93 | ) 94 | 95 | 2 96 | 97 | 98 | 99 | = 100 | 101 | 102 | 103 | c 104 | 2 105 | 106 | + 107 | 4 108 | 109 | ( 110 | 111 | 1 112 | 2 113 | 114 | a 115 | b 116 | ) 117 | 118 | 119 | 120 | 121 | 122 | a 123 | 2 124 | 125 | + 126 | 2 127 | a 128 | b 129 | + 130 | 131 | b 132 | 2 133 | 134 | 135 | 136 | = 137 | 138 | 139 | 140 | c 141 | 2 142 | 143 | + 144 | 2 145 | a 146 | b 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | a 156 | 2 157 | 158 | + 159 | 160 | b 161 | 2 162 | 163 | 164 | 165 | = 166 | 167 | 168 | 169 | c 170 | 2 171 | 172 | 173 | 174 | 175 | 176 |

177 |
178 | 179 | 180 | -------------------------------------------------------------------------------- /dist/mo.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | let MathOElement = class MathOElement extends MathMLElement { 12 | constructor() { 13 | super(...arguments); 14 | this.formStyle = ''; 15 | } 16 | render() { 17 | return html ` 18 | 67 | 68 | `; 69 | } 70 | updated(propVals) { 71 | super.updated(propVals); 72 | this.onSlotChange(); 73 | } 74 | onSlotChange() { 75 | if (!this.shadowRoot) { 76 | return; 77 | } 78 | const span = this.shadowRoot.querySelector('span'); 79 | if (!span) { 80 | return; 81 | } 82 | let specialRule = ''; 83 | const text = (this.textContent || '').trim(); 84 | if (text === ',' || text === ';') { 85 | specialRule = 'separator'; 86 | } 87 | else if (text === '.' || text === '⋅') { 88 | specialRule = 'product'; 89 | } 90 | else if (text.match(/^[\[{(]*$/)) { 91 | specialRule = 'begin-brace'; 92 | } 93 | else if (text.match(/^[\]})]*$/)) { 94 | specialRule = 'end-brace'; 95 | } 96 | else if (text.match(/^[|]*$/)) { 97 | specialRule = 'neut-brace'; 98 | } 99 | // bigger text for math ops 100 | this.classList.remove('mo-bigger'); 101 | if (text && (0x2200 <= text.charCodeAt(0)) && (text.charCodeAt(0) <= 0x2233)) { 102 | if ((getComputedStyle(this).getPropertyValue('--math-style-level') || '').trim() !== 'sub') { 103 | this.classList.add('mo-bigger'); 104 | } 105 | } 106 | const newFormStyle = specialRule || 'infix'; 107 | if (this.formStyle !== newFormStyle) { 108 | if (this.formStyle) { 109 | this.classList.remove(this.formStyle); 110 | } 111 | this.formStyle = `mo-${newFormStyle}`; 112 | this.classList.add(this.formStyle); 113 | } 114 | let effectiveStretch = this.stretchy && this.stretchy.trim().toLowerCase() === 'true'; 115 | if (!this.stretchy) { 116 | if (getComputedStyle(this).getPropertyValue('--math-style-stretchy').trim() === 'true') { 117 | effectiveStretch = true; 118 | } 119 | else { 120 | effectiveStretch = specialRule === 'begin-brace' || specialRule === 'end-brace' || specialRule === 'neut-brace'; 121 | } 122 | } 123 | span.style.width = null; 124 | if (!effectiveStretch) { 125 | span.classList.add('fullWidthSpan'); 126 | this.classList.remove('mo-stretchy'); 127 | span.style.transform = null; 128 | span.style.lineHeight = null; 129 | span.classList.remove('invisible'); 130 | } 131 | else { 132 | span.classList.remove('fullWidthSpan'); 133 | this.classList.add('mo-stretchy'); 134 | span.style.lineHeight = '1'; 135 | setTimeout(() => { 136 | if (span.style.transform) { 137 | return; 138 | } 139 | span.classList.remove('invisible'); 140 | const spanSize = span.getBoundingClientRect(); 141 | const size = this.getBoundingClientRect(); 142 | const scaleY = spanSize.height ? (size.height / spanSize.height) : 1; 143 | const scaleX = spanSize.width ? (size.width / spanSize.width) : 1; 144 | if (scaleY <= 1) { 145 | span.style.lineHeight = null; 146 | } 147 | if (scaleX !== 1) { 148 | span.style.width = '100%'; 149 | } 150 | span.style.transform = `scale(${scaleX}, ${scaleY})`; 151 | }, 50); 152 | } 153 | } 154 | }; 155 | __decorate([ 156 | property({ type: String }), 157 | __metadata("design:type", String) 158 | ], MathOElement.prototype, "form", void 0); 159 | __decorate([ 160 | property({ type: String }), 161 | __metadata("design:type", String) 162 | ], MathOElement.prototype, "stretchy", void 0); 163 | MathOElement = __decorate([ 164 | customElement('math-o') 165 | ], MathOElement); 166 | export { MathOElement }; 167 | -------------------------------------------------------------------------------- /dist/mfrac.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | let MathFracElement = class MathFracElement extends MathMLElement { 12 | constructor() { 13 | super(...arguments); 14 | this.bevelled = false; 15 | this.numalign = 'center'; 16 | this.denomalign = 'center'; 17 | } 18 | render() { 19 | let bevelledDivStyle = 'stroke-width: 1;'; 20 | let unbevelledDivStyle = 'border-top: solid thin;'; 21 | if (this.linethickness && (this.linethickness.trim().charAt(0) === '0')) { 22 | bevelledDivStyle = 'stroke-width: 0;'; 23 | unbevelledDivStyle = ''; 24 | } 25 | return html ` 26 | 89 |
90 |
91 | 92 |
93 |
94 |
95 |
96 | `; 97 | } 98 | updated(propVals) { 99 | super.updated(propVals); 100 | this.refreshSlot(); 101 | } 102 | refreshSlot() { 103 | if (!this.shadowRoot) { 104 | return; 105 | } 106 | const slot = this.shadowRoot.querySelector('slot'); 107 | if (!slot) { 108 | return; 109 | } 110 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 111 | if (nodes.length > 1) { 112 | const nu = this.shadowRoot.querySelector('#mfracN'); 113 | const de = this.shadowRoot.querySelector('#mfracD'); 114 | nu.appendChild(nodes[0]); 115 | de.appendChild(nodes[1]); 116 | for (let i = 2; i < nodes.length; i++) { 117 | if (nodes[i].parentElement) { 118 | nodes[i].parentElement.removeChild(nodes[i]); 119 | } 120 | } 121 | } 122 | this.updateBevlled(); 123 | } 124 | updateBevlled() { 125 | const panel = this.shadowRoot.querySelector('#mfracPanel'); 126 | const nu = this.shadowRoot.querySelector('#mfracN'); 127 | const de = this.shadowRoot.querySelector('#mfracD'); 128 | const bevelledDivider = this.shadowRoot.querySelector('#bevelledDivider'); 129 | const unbevelledDivider = this.shadowRoot.querySelector('#unbevelledDivider'); 130 | nu.style.textAlign = this.numalign; 131 | de.style.textAlign = this.denomalign; 132 | if (this.bevelled) { 133 | panel.classList.remove('unbevelled'); 134 | panel.classList.add('bevelled'); 135 | bevelledDivider.classList.remove('hidden'); 136 | unbevelledDivider.classList.add('hidden'); 137 | setTimeout(() => { 138 | this.drawBevelledDivider(); 139 | }, 10); 140 | } 141 | else { 142 | panel.classList.remove('bevelled'); 143 | panel.classList.add('unbevelled'); 144 | bevelledDivider.classList.add('hidden'); 145 | unbevelledDivider.classList.remove('hidden'); 146 | } 147 | } 148 | drawBevelledDivider() { 149 | const span = this.shadowRoot.querySelector('#bevelledDivider'); 150 | const path = this.shadowRoot.querySelector('#bevelledPath'); 151 | if (span && path) { 152 | const size = span.getBoundingClientRect(); 153 | const width = size.width; 154 | const height = size.height; 155 | const d = `M0 ${height} L${width} 0`; 156 | path.setAttribute('d', d); 157 | } 158 | } 159 | }; 160 | __decorate([ 161 | property({ type: Boolean }), 162 | __metadata("design:type", Object) 163 | ], MathFracElement.prototype, "bevelled", void 0); 164 | __decorate([ 165 | property({ type: String }), 166 | __metadata("design:type", String) 167 | ], MathFracElement.prototype, "numalign", void 0); 168 | __decorate([ 169 | property({ type: String }), 170 | __metadata("design:type", String) 171 | ], MathFracElement.prototype, "denomalign", void 0); 172 | __decorate([ 173 | property({ type: String }), 174 | __metadata("design:type", String) 175 | ], MathFracElement.prototype, "linethickness", void 0); 176 | MathFracElement = __decorate([ 177 | customElement('math-frac') 178 | ], MathFracElement); 179 | export { MathFracElement }; 180 | -------------------------------------------------------------------------------- /dist/mtable.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { html, customElement, property } from './mathml-element.js'; 11 | import { MathTableBaseElement } from './mtable-base.js'; 12 | let MathTableElement = class MathTableElement extends MathTableBaseElement { 13 | constructor() { 14 | super(); 15 | this.columnlines = 'none'; 16 | this.rowlines = 'none'; 17 | this.frame = 'none'; 18 | this.columnspacing = '0.8em'; 19 | this.rowspacing = '0.8em'; 20 | this.framespacing = '0.4em 0.5ex'; 21 | this.columnalign = this.columnalign || 'center'; 22 | } 23 | render() { 24 | return html ` 25 | 38 | 39 | `; 40 | } 41 | updated(propVals) { 42 | super.updated(propVals); 43 | this.updateAlignment(); 44 | const s = this.style; 45 | if (this.frame) { 46 | switch (this.frame) { 47 | case 'none': 48 | s.setProperty('--math-table-border', 'none'); 49 | break; 50 | case 'solid': 51 | s.setProperty('--math-table-border', 'solid thin'); 52 | break; 53 | case 'dashed': 54 | s.setProperty('--math-table-border', 'dashed thin'); 55 | break; 56 | default: 57 | s.removeProperty('--math-table-border'); 58 | break; 59 | } 60 | } 61 | if (this.rowlines) { 62 | switch (this.rowlines) { 63 | case 'none': 64 | s.setProperty('--math-table-row-border', 'none'); 65 | break; 66 | case 'solid': 67 | s.setProperty('--math-table-row-border', 'solid thin'); 68 | break; 69 | case 'dashed': 70 | s.setProperty('--math-table-row-border', 'dashed thin'); 71 | break; 72 | default: 73 | s.removeProperty('--math-table-row-border'); 74 | break; 75 | } 76 | } 77 | if (this.columnlines) { 78 | switch (this.columnlines) { 79 | case 'none': 80 | s.setProperty('--math-table-column-border', 'none'); 81 | break; 82 | case 'solid': 83 | s.setProperty('--math-table-column-border', 'solid thin'); 84 | break; 85 | case 'dashed': 86 | s.setProperty('--math-table-column-border', 'dashed thin'); 87 | break; 88 | default: 89 | s.removeProperty('--math-table-column-border'); 90 | break; 91 | } 92 | } 93 | if (this.framespacing) { 94 | const split = this.framespacing.split(' ').reverse(); 95 | s.setProperty('--math-table-padding', split.join(' ')); 96 | } 97 | else { 98 | s.removeProperty('--math-table-padding'); 99 | } 100 | if (this.width) { 101 | s.setProperty('--math-table-width', this.width); 102 | } 103 | else { 104 | s.removeProperty('--math-table-width'); 105 | } 106 | if (this.columnspacing) { 107 | s.setProperty('--math-table-columnspacing', this.columnspacing); 108 | } 109 | else { 110 | s.removeProperty('--math-table-columnspacing'); 111 | } 112 | if (this.rowspacing) { 113 | s.setProperty('--math-table-rowspacing', this.columnspacing); 114 | } 115 | else { 116 | s.removeProperty('--math-table-rowspacing'); 117 | } 118 | if (this.columnalign) { 119 | const split = this.columnalign.trim().split(' ').filter((d) => { 120 | if (d.trim()) { 121 | return true; 122 | } 123 | return false; 124 | }); 125 | if (split.length > 1) { 126 | const slot = this.shadowRoot.querySelector('slot'); 127 | if (slot) { 128 | slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE).filter((d) => { 129 | return d.tagName === 'MATH-TR' || d.tagName === 'MATH-LABELEDTR'; 130 | }).forEach((d) => { 131 | const row = d; 132 | row.columnalign = row.columnalign || (this.columnalign).trim(); 133 | }); 134 | } 135 | } 136 | } 137 | } 138 | }; 139 | __decorate([ 140 | property({ type: String }), 141 | __metadata("design:type", String) 142 | ], MathTableElement.prototype, "columnlines", void 0); 143 | __decorate([ 144 | property({ type: String }), 145 | __metadata("design:type", String) 146 | ], MathTableElement.prototype, "rowlines", void 0); 147 | __decorate([ 148 | property({ type: String }), 149 | __metadata("design:type", String) 150 | ], MathTableElement.prototype, "frame", void 0); 151 | __decorate([ 152 | property({ type: String }), 153 | __metadata("design:type", Object) 154 | ], MathTableElement.prototype, "columnspacing", void 0); 155 | __decorate([ 156 | property({ type: String }), 157 | __metadata("design:type", Object) 158 | ], MathTableElement.prototype, "rowspacing", void 0); 159 | __decorate([ 160 | property({ type: String }), 161 | __metadata("design:type", Object) 162 | ], MathTableElement.prototype, "framespacing", void 0); 163 | __decorate([ 164 | property({ type: String }), 165 | __metadata("design:type", String) 166 | ], MathTableElement.prototype, "width", void 0); 167 | MathTableElement = __decorate([ 168 | customElement('math-table'), 169 | __metadata("design:paramtypes", []) 170 | ], MathTableElement); 171 | export { MathTableElement }; 172 | -------------------------------------------------------------------------------- /dist/mmultiscripts.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { MathMLElement, html, customElement } from './mathml-element.js'; 8 | import { AllFlex } from './styles/common-styles.js'; 9 | let MathMultiScriptsElement = class MathMultiScriptsElement extends MathMLElement { 10 | constructor() { 11 | super(...arguments); 12 | this.pendingLayout = false; 13 | } 14 | render() { 15 | return html ` 16 | 41 |
42 | 43 |
44 | `; 45 | } 46 | refreshSlot() { 47 | if (this.pendingLayout) { 48 | return; 49 | } 50 | if (!this.shadowRoot) { 51 | return; 52 | } 53 | const slot = this.shadowRoot.querySelector('slot'); 54 | if (!slot) { 55 | return; 56 | } 57 | const nodes = slot.assignedNodes().filter((d) => d.nodeType === Node.ELEMENT_NODE); 58 | if (nodes.length === 1 && (nodes[0].tagName === 'math-prescripts'.toUpperCase())) { 59 | return; 60 | } 61 | if (nodes.length > 2) { 62 | this.pendingLayout = true; 63 | const runnable = () => { 64 | const postNodes = [null, null]; 65 | const preNodes = [null, null]; 66 | let current = postNodes; 67 | for (let i = 1; i < nodes.length; i++) { 68 | const n = nodes[i]; 69 | if (n.tagName === 'math-prescripts'.toUpperCase()) { 70 | current = preNodes; 71 | } 72 | else { 73 | if (!current[0]) { 74 | current[0] = n; 75 | } 76 | else if (!current[1]) { 77 | current[1] = n; 78 | } 79 | } 80 | } 81 | const s1 = nodes[0].getBoundingClientRect(); 82 | const margins = [0, 0, 0, 0]; 83 | // do post 84 | { 85 | // sub 86 | if (postNodes[0]) { 87 | const subNode = postNodes[0]; 88 | const subSize = subNode.getBoundingClientRect(); 89 | subNode.style.opacity = '1'; 90 | subNode.classList.add('rightscript'); 91 | const hh = s1.height / 2; 92 | let db = hh; 93 | if ((hh + subSize.height) < s1.height) { 94 | db = s1.height - subSize.height; 95 | } 96 | else { 97 | margins[2] = (hh + subSize.height) - s1.height; 98 | } 99 | subNode.style.top = `${db}px`; 100 | margins[1] = subSize.width + 5; 101 | } 102 | // sup 103 | if (postNodes[1]) { 104 | const supNode = postNodes[1]; 105 | supNode.style.opacity = '1'; 106 | supNode.classList.add('rightscript'); 107 | const supSize = supNode.getBoundingClientRect(); 108 | const db = supSize.bottom - (s1.bottom - (s1.height / 2)); 109 | if (db > 0) { 110 | supNode.style.top = `${-db}px`; 111 | margins[0] = db; 112 | } 113 | margins[1] = Math.max(supSize.width + 5, margins[1]); 114 | } 115 | } 116 | // do pre 117 | { 118 | // sub 119 | if (preNodes[0]) { 120 | const subNode = preNodes[0]; 121 | const subSize = subNode.getBoundingClientRect(); 122 | subNode.style.opacity = '1'; 123 | subNode.classList.add('leftscript'); 124 | const hh = s1.height / 2; 125 | let db = hh; 126 | if ((hh + subSize.height) < s1.height) { 127 | db = s1.height - subSize.height; 128 | } 129 | else { 130 | margins[2] = Math.max((hh + subSize.height) - s1.height, margins[2]); 131 | } 132 | subNode.style.top = `${db}px`; 133 | margins[3] = Math.max(subSize.width + 5, margins[3]); 134 | } 135 | // sup 136 | if (preNodes[1]) { 137 | const supNode = preNodes[1]; 138 | supNode.style.opacity = '1'; 139 | supNode.classList.add('leftscript'); 140 | const supSize = supNode.getBoundingClientRect(); 141 | const db = supSize.bottom - (s1.bottom - (s1.height / 2)); 142 | if (db > 0) { 143 | supNode.style.top = `${-db}px`; 144 | margins[0] = Math.max(db, margins[0]); 145 | } 146 | margins[3] = Math.max(supSize.width + 5, margins[3]); 147 | } 148 | } 149 | this.style.margin = `${margins[0]}px ${margins[1]}px ${margins[2]}px ${margins[3]}px`; 150 | }; 151 | setTimeout(runnable, 100); 152 | setTimeout(() => { 153 | this.pendingLayout = false; 154 | runnable(); 155 | }, 800); 156 | } 157 | } 158 | }; 159 | MathMultiScriptsElement = __decorate([ 160 | customElement('math-multiscripts') 161 | ], MathMultiScriptsElement); 162 | export { MathMultiScriptsElement }; 163 | -------------------------------------------------------------------------------- /src/menclose.ts: -------------------------------------------------------------------------------- 1 | import { MathMLElement, html, TemplateResult, customElement, property, PropertyValues } from './mathml-element.js'; 2 | 3 | const SVGNS = 'http://www.w3.org/2000/svg'; 4 | 5 | @customElement('math-enclose') 6 | export class MathEncloseElement extends MathMLElement { 7 | @property({ type: String }) notation = 'longdiv'; 8 | 9 | render(): TemplateResult { 10 | return html` 11 | 30 |
31 | 32 | `; 33 | } 34 | 35 | updated(propVals: PropertyValues) { 36 | super.updated(propVals); 37 | this.refresh(); 38 | } 39 | 40 | private refresh() { 41 | if (!this.shadowRoot) { 42 | return; 43 | } 44 | if ((!this.shadowRoot.querySelector('svg')) || (!this.shadowRoot.querySelector('slot'))) { 45 | return; 46 | } 47 | setTimeout(() => this.redraw(), 100); 48 | } 49 | 50 | private adjustPadding(paddings: number[], suggestions: number[]) { 51 | for (let i = 0; i < suggestions.length; i++) { 52 | paddings[i] = Math.max(paddings[i], suggestions[i]); 53 | } 54 | } 55 | 56 | private redraw() { 57 | const svg = this.shadowRoot!.querySelector('svg') as SVGSVGElement; 58 | const panel = this.shadowRoot!.querySelector('#menclosePanel') as HTMLElement; 59 | const size = this.getBoundingClientRect(); 60 | const paddings = [0, 0, 0, 0]; 61 | const tokens = (this.notation || '').trim().split(' ').filter((d) => { return d.trim() ? true : false; }); 62 | tokens.forEach((t) => { 63 | switch (t) { 64 | case 'longdiv': 65 | this.adjustPadding(paddings, [2, 0, 0, 12]); 66 | break; 67 | case 'actuarial': 68 | this.adjustPadding(paddings, [2, 2, 0, 0]); 69 | break; 70 | case 'radical': 71 | this.adjustPadding(paddings, [2, 0, 0, 18]); 72 | break; 73 | case 'phasorangle': 74 | this.adjustPadding(paddings, [0, 0, 2, 16]); 75 | break; 76 | case 'circle': 77 | this.adjustPadding(paddings, [2, 4, 2, 4]); 78 | break; 79 | default: 80 | this.adjustPadding(paddings, [1, 1, 1, 1]); 81 | break; 82 | } 83 | }); 84 | panel.style.padding = paddings.join('px ').trim() + 'px'; 85 | const width = size.width + paddings[1] + paddings[3]; 86 | const height = size.height + paddings[0] + paddings[2]; 87 | svg.style.width = `${width}px`; 88 | svg.style.height = `${height}px`; 89 | while (svg.firstChild) { 90 | svg.removeChild(svg.firstChild); 91 | } 92 | panel.style.borderTop = null; 93 | panel.style.borderBottom = null; 94 | panel.style.borderLeft = null; 95 | panel.style.borderRight = null; 96 | panel.style.borderRadius = null; 97 | 98 | tokens.forEach((t) => { 99 | switch (t) { 100 | case 'longdiv': { 101 | const path = document.createElementNS(SVGNS, 'path'); 102 | path.setAttribute('d', `M0 1 H ${width} M0 1 C 8 ${height * 0.33} 8 ${height * 0.66} 0 ${height}`); 103 | svg.appendChild(path); 104 | break; 105 | } 106 | case 'actuarial': 107 | panel.style.borderRight = '1px solid'; 108 | panel.style.borderTop = '1px solid'; 109 | break; 110 | case 'radical': { 111 | const path = document.createElementNS(SVGNS, 'path'); 112 | path.setAttribute('d', `M0 ${height * 0.55} H${18 * 0.13} L${18 * 0.45} ${height - 2} L${18} 1 L${width} 1`); 113 | svg.appendChild(path); 114 | break; 115 | } 116 | case 'box': 117 | panel.style.borderRight = '1px solid'; 118 | panel.style.borderTop = '1px solid'; 119 | panel.style.borderLeft = '1px solid'; 120 | panel.style.borderBottom = '1px solid'; 121 | break; 122 | case 'roundedbox': 123 | panel.style.borderRight = '1px solid'; 124 | panel.style.borderTop = '1px solid'; 125 | panel.style.borderLeft = '1px solid'; 126 | panel.style.borderBottom = '1px solid'; 127 | panel.style.borderRadius = '5px'; 128 | break; 129 | case 'circle': { 130 | const ellipse = document.createElementNS(SVGNS, 'ellipse'); 131 | ellipse.setAttribute('cx', `${width / 2}`); 132 | ellipse.setAttribute('cy', `${height / 2}`); 133 | ellipse.setAttribute('rx', `${width / 2 - 2}`); 134 | ellipse.setAttribute('ry', `${height / 2 - 2}`); 135 | svg.appendChild(ellipse); 136 | break; 137 | } 138 | case 'left': 139 | panel.style.borderLeft = '1px solid'; 140 | break; 141 | case 'right': 142 | panel.style.borderRight = '1px solid'; 143 | break; 144 | case 'top': 145 | panel.style.borderTop = '1px solid'; 146 | break; 147 | case 'bottom': 148 | panel.style.borderBottom = '1px solid'; 149 | break; 150 | case 'madruwb': 151 | panel.style.borderRight = '1px solid'; 152 | panel.style.borderBottom = '1px solid'; 153 | break; 154 | case 'updiagonalstrike': { 155 | const path = document.createElementNS(SVGNS, 'path'); 156 | path.setAttribute('d', `M1 ${height - 1} L${width - 1} ${1}`); 157 | svg.appendChild(path); 158 | break; 159 | } 160 | case 'downdiagonalstrike': { 161 | const path = document.createElementNS(SVGNS, 'path'); 162 | path.setAttribute('d', `M1 1 L${width - 1} ${height - 1}`); 163 | svg.appendChild(path); 164 | break; 165 | } 166 | case 'verticalstrike': { 167 | const path = document.createElementNS(SVGNS, 'path'); 168 | path.setAttribute('d', `M${width / 2} 1 L${width / 2} ${height - 1}`); 169 | svg.appendChild(path); 170 | break; 171 | } 172 | case 'horizontalstrike': { 173 | const path = document.createElementNS(SVGNS, 'path'); 174 | path.setAttribute('d', `M1 ${height / 2} L${width - 1} ${height / 2}`); 175 | svg.appendChild(path); 176 | break; 177 | } 178 | case 'updiagonalarrow': { 179 | const path = document.createElementNS(SVGNS, 'path'); 180 | path.setAttribute('d', `M1 ${height - 1} L${width - 1} ${1}`); 181 | svg.appendChild(path); 182 | const a1 = Math.atan(height / width); 183 | const a2 = (Math.PI / 2 - a1) - (Math.PI / 6); 184 | const a3 = (Math.PI / 6) + a2; 185 | const x1 = Math.sin(a2) * 8; 186 | const y1 = Math.cos(a2) * 8; 187 | const path2 = document.createElementNS(SVGNS, 'path'); 188 | path2.setAttribute('d', `M${width - 1} ${1} L${width - 1 - x1} ${1 + y1} l${-Math.cos(a3) * 8} ${-Math.sin(a3) * 8} Z`); 189 | path2.style.fill = 'currentColor'; 190 | svg.appendChild(path2); 191 | break; 192 | } 193 | case 'phasorangle': { 194 | const path = document.createElementNS(SVGNS, 'path'); 195 | path.setAttribute('d', `M16 1 L1 ${height - 1} L${width} ${height - 1}`); 196 | svg.appendChild(path); 197 | break; 198 | } 199 | default: 200 | break; 201 | } 202 | }); 203 | } 204 | } -------------------------------------------------------------------------------- /dist/menclose.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | var __metadata = (this && this.__metadata) || function (k, v) { 8 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 9 | }; 10 | import { MathMLElement, html, customElement, property } from './mathml-element.js'; 11 | const SVGNS = 'http://www.w3.org/2000/svg'; 12 | let MathEncloseElement = class MathEncloseElement extends MathMLElement { 13 | constructor() { 14 | super(...arguments); 15 | this.notation = 'longdiv'; 16 | } 17 | render() { 18 | return html ` 19 | 38 |
39 | 40 | `; 41 | } 42 | updated(propVals) { 43 | super.updated(propVals); 44 | this.refresh(); 45 | } 46 | refresh() { 47 | if (!this.shadowRoot) { 48 | return; 49 | } 50 | if ((!this.shadowRoot.querySelector('svg')) || (!this.shadowRoot.querySelector('slot'))) { 51 | return; 52 | } 53 | setTimeout(() => this.redraw(), 100); 54 | } 55 | adjustPadding(paddings, suggestions) { 56 | for (let i = 0; i < suggestions.length; i++) { 57 | paddings[i] = Math.max(paddings[i], suggestions[i]); 58 | } 59 | } 60 | redraw() { 61 | const svg = this.shadowRoot.querySelector('svg'); 62 | const panel = this.shadowRoot.querySelector('#menclosePanel'); 63 | const size = this.getBoundingClientRect(); 64 | const paddings = [0, 0, 0, 0]; 65 | const tokens = (this.notation || '').trim().split(' ').filter((d) => { return d.trim() ? true : false; }); 66 | tokens.forEach((t) => { 67 | switch (t) { 68 | case 'longdiv': 69 | this.adjustPadding(paddings, [2, 0, 0, 12]); 70 | break; 71 | case 'actuarial': 72 | this.adjustPadding(paddings, [2, 2, 0, 0]); 73 | break; 74 | case 'radical': 75 | this.adjustPadding(paddings, [2, 0, 0, 18]); 76 | break; 77 | case 'phasorangle': 78 | this.adjustPadding(paddings, [0, 0, 2, 16]); 79 | break; 80 | case 'circle': 81 | this.adjustPadding(paddings, [2, 4, 2, 4]); 82 | break; 83 | default: 84 | this.adjustPadding(paddings, [1, 1, 1, 1]); 85 | break; 86 | } 87 | }); 88 | panel.style.padding = paddings.join('px ').trim() + 'px'; 89 | const width = size.width + paddings[1] + paddings[3]; 90 | const height = size.height + paddings[0] + paddings[2]; 91 | svg.style.width = `${width}px`; 92 | svg.style.height = `${height}px`; 93 | while (svg.firstChild) { 94 | svg.removeChild(svg.firstChild); 95 | } 96 | panel.style.borderTop = null; 97 | panel.style.borderBottom = null; 98 | panel.style.borderLeft = null; 99 | panel.style.borderRight = null; 100 | panel.style.borderRadius = null; 101 | tokens.forEach((t) => { 102 | switch (t) { 103 | case 'longdiv': { 104 | const path = document.createElementNS(SVGNS, 'path'); 105 | path.setAttribute('d', `M0 1 H ${width} M0 1 C 8 ${height * 0.33} 8 ${height * 0.66} 0 ${height}`); 106 | svg.appendChild(path); 107 | break; 108 | } 109 | case 'actuarial': 110 | panel.style.borderRight = '1px solid'; 111 | panel.style.borderTop = '1px solid'; 112 | break; 113 | case 'radical': { 114 | const path = document.createElementNS(SVGNS, 'path'); 115 | path.setAttribute('d', `M0 ${height * 0.55} H${18 * 0.13} L${18 * 0.45} ${height - 2} L${18} 1 L${width} 1`); 116 | svg.appendChild(path); 117 | break; 118 | } 119 | case 'box': 120 | panel.style.borderRight = '1px solid'; 121 | panel.style.borderTop = '1px solid'; 122 | panel.style.borderLeft = '1px solid'; 123 | panel.style.borderBottom = '1px solid'; 124 | break; 125 | case 'roundedbox': 126 | panel.style.borderRight = '1px solid'; 127 | panel.style.borderTop = '1px solid'; 128 | panel.style.borderLeft = '1px solid'; 129 | panel.style.borderBottom = '1px solid'; 130 | panel.style.borderRadius = '5px'; 131 | break; 132 | case 'circle': { 133 | const ellipse = document.createElementNS(SVGNS, 'ellipse'); 134 | ellipse.setAttribute('cx', `${width / 2}`); 135 | ellipse.setAttribute('cy', `${height / 2}`); 136 | ellipse.setAttribute('rx', `${width / 2 - 2}`); 137 | ellipse.setAttribute('ry', `${height / 2 - 2}`); 138 | svg.appendChild(ellipse); 139 | break; 140 | } 141 | case 'left': 142 | panel.style.borderLeft = '1px solid'; 143 | break; 144 | case 'right': 145 | panel.style.borderRight = '1px solid'; 146 | break; 147 | case 'top': 148 | panel.style.borderTop = '1px solid'; 149 | break; 150 | case 'bottom': 151 | panel.style.borderBottom = '1px solid'; 152 | break; 153 | case 'madruwb': 154 | panel.style.borderRight = '1px solid'; 155 | panel.style.borderBottom = '1px solid'; 156 | break; 157 | case 'updiagonalstrike': { 158 | const path = document.createElementNS(SVGNS, 'path'); 159 | path.setAttribute('d', `M1 ${height - 1} L${width - 1} ${1}`); 160 | svg.appendChild(path); 161 | break; 162 | } 163 | case 'downdiagonalstrike': { 164 | const path = document.createElementNS(SVGNS, 'path'); 165 | path.setAttribute('d', `M1 1 L${width - 1} ${height - 1}`); 166 | svg.appendChild(path); 167 | break; 168 | } 169 | case 'verticalstrike': { 170 | const path = document.createElementNS(SVGNS, 'path'); 171 | path.setAttribute('d', `M${width / 2} 1 L${width / 2} ${height - 1}`); 172 | svg.appendChild(path); 173 | break; 174 | } 175 | case 'horizontalstrike': { 176 | const path = document.createElementNS(SVGNS, 'path'); 177 | path.setAttribute('d', `M1 ${height / 2} L${width - 1} ${height / 2}`); 178 | svg.appendChild(path); 179 | break; 180 | } 181 | case 'updiagonalarrow': { 182 | const path = document.createElementNS(SVGNS, 'path'); 183 | path.setAttribute('d', `M1 ${height - 1} L${width - 1} ${1}`); 184 | svg.appendChild(path); 185 | const a1 = Math.atan(height / width); 186 | const a2 = (Math.PI / 2 - a1) - (Math.PI / 6); 187 | const a3 = (Math.PI / 6) + a2; 188 | const x1 = Math.sin(a2) * 8; 189 | const y1 = Math.cos(a2) * 8; 190 | const path2 = document.createElementNS(SVGNS, 'path'); 191 | path2.setAttribute('d', `M${width - 1} ${1} L${width - 1 - x1} ${1 + y1} l${-Math.cos(a3) * 8} ${-Math.sin(a3) * 8} Z`); 192 | path2.style.fill = 'currentColor'; 193 | svg.appendChild(path2); 194 | break; 195 | } 196 | case 'phasorangle': { 197 | const path = document.createElementNS(SVGNS, 'path'); 198 | path.setAttribute('d', `M16 1 L1 ${height - 1} L${width} ${height - 1}`); 199 | svg.appendChild(path); 200 | break; 201 | } 202 | default: 203 | break; 204 | } 205 | }); 206 | } 207 | }; 208 | __decorate([ 209 | property({ type: String }), 210 | __metadata("design:type", Object) 211 | ], MathEncloseElement.prototype, "notation", void 0); 212 | MathEncloseElement = __decorate([ 213 | customElement('math-enclose') 214 | ], MathEncloseElement); 215 | export { MathEncloseElement }; 216 | --------------------------------------------------------------------------------