├── .github └── dependabot.yml ├── .gitignore ├── LICENSE ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── screencast.gif └── style.css /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | day: saturday 8 | time: "07:07" 9 | timezone: America/Los_Angeles 10 | open-pull-requests-limit: 10 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Include your project-specific ignores in this file 2 | # Read about how to use .gitignore: https://help.github.com/articles/ignoring-files 3 | /build 4 | /out 5 | /node_modules 6 | /.nyc_output 7 | 8 | 9 | # OS generated files # 10 | ###################### 11 | .DS_Store 12 | .DS_Store? 13 | ._* 14 | .Spotlight-V100 15 | .Trashes 16 | ehthumbs.db 17 | Thumbs.db 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Arno Gourdol 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Screencast](screencast.gif) 2 | 3 | The MathLive Vue wrapper provides a Vue component that implements a 4 | `` HTML tag. 5 | 6 | The component can be used to edit formulas using the MathLive library. The 7 | editor provides a rich, accessible, editing UI, including virtual keyboards for 8 | mobile, and can provide the output as LaTeX, MathML or spoken text. 9 | 10 | ## Getting Started 11 | 12 | The MathLive library must be loaded separately. This gives the option to pick a 13 | specific version of the library to be used by the wrapper. 14 | 15 | Next, the wrapper should be imported, then the two connected using `Vue.use()` 16 | 17 | Note: this repository only contains the sample. The Vue wrapper is packaged with the main MathLive library. 18 | 19 | **Caution**: If you are getting runtime errors when instantiating 20 | a mathfield component and a warning in the console from Vue about "You are 21 | using the runtime-only build of Vue..." make sure to add `runtimeCompiler: true` 22 | to your Vue configuration. 23 | 24 | ```html 25 | 31 | ``` 32 | 33 | The default tag for mathfields is `` A custom tag can be 34 | defined using: 35 | 36 | ```javascript 37 | Vue.component("custom-tag", Mathfield); 38 | ``` 39 | 40 | The component supports the `v-model` attribute. 41 | 42 | The textual content of the element is used as the initial value of the editor. 43 | 44 | The mathfield can be configured using the `:options` attribute, for example to 45 | specify the location of the fonts directory. Read more about the [available options](http://cortexjs.io/docs/mathlive/?q=MathfieldConfig). 46 | 47 | ```html 48 | 54 | f(x)= 55 | 56 | ``` 57 | 58 | ### Props 59 | 60 | | Name | Type | Description | 61 | | ------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 62 | | `value` | `string` | The content of the mathfield, represented as a LaTeX string. | 63 | | `options` | `object` | Configuration options for the mathfield. | 64 | | `onKeystroke` | `(keystroke:string, ev:Event) => boolean` | A callback invoked when a key is pressed. `keystroke` is a string describing the keystroke, `ev` is the native keyboard event. Return false to stop handling of the event | 65 | | `onMoveOutOf` | `(string) => boolean` | A callback invoked when keyboard navigation would cause the insertion point to leave the mathfield. The argument indicates the direction of the navigation, either "forward" or "backward". Return false to prevent the move, true to wrap around to the start of the field. By default, the insertion point will wrap around. | 66 | | `onTabOutOf` | `(string) => boolean` | A callback invoked when pressing tab (or shift-tab) would cause the insertion point to leave the mathfield. The argument indicates the direction of the navigation, either "forward" or "backward". Return false to prevent the move, true to wrap around to the start of the field. By default, the insertion point will wrap around. | 67 | 68 | ### Events 69 | 70 | | Name | Description | 71 | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 72 | | `focus` | The editor instance gained the input focus. | 73 | | `blur` | The editor instance lost the input focus. | 74 | | `input` | The content of the mathfield has changed. The parameter of the event is the new value as a string | 75 | | `selection-will-change` | The selection of the mathfield is about to change | 76 | | `undo-state-will-change` | The undo state is about to change | 77 | | `undo-state-did-change` | The undo state has changed | 78 | | `virtual-keyboard-toggle` | The visibility of the virtual keyboard has changed. The first argument is a boolean indicating if the keyboard is now visible. The second argument is a DOM element containing the virtual keyboard. | 79 | | `read-aloud-status` | The status of the read aloud operation has changed. The first argument is a string indicating the new status. | 80 | 81 | ### Methods 82 | 83 | | Name | Description | 84 | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 85 | | `perform(selector:string)` | Perform an action, as indicated by the selector. | 86 | | `hasFocus(): boolean` | True if the mathfield is focused | 87 | | `focus()` | Set the focus to the mathfield | 88 | | `blur()` | Remove the focus from the mathfield | 89 | | `text(format:string): string` | Return the content of the mathfield as a string in the specified format: `"latex"`, `"latex-expanded"` (all the LaTeX macros are expanded to their definition), `"spoken"`, `"mathML"` | 90 | | `selectedText(format:string): string` | Like `text()`, but only for the current selection. | 91 | | `insert(content:string, options:object)` | `options.insertionMode` = `'replaceSelection'` (default), `'replaceAll'`, `'insertBefore'`, `'insertAfter'`
`options.selectionMode` - Describes where the selection will be after the insertion: `'placeholder'`: the selection will be the first available placeholder in the item that has been inserted) (default), `'after'`: the selection will be an insertion point after the item that has been inserted, `'before'`: the selection will be an insertion point before the item that has been inserted) or 'item' (the item that was inserted will be selected).
`options.placeholder` - The placeholder string, if necessary
`options.format` - The format of the string `s`: `'auto'`: the string is interpreted as a latex fragment or command) (default), `'latex'`: the string is interpreted strictly as a latex fragment
`options.smartFence` - If true, promote plain fences, e.g. `(`, as `\left...\right` or `\mleft...\mright`
`options.suppressChangeNotifications` - If true, the handlers for the contentDidChange and selectionDidChange notifications will not be invoked. Default `false`. | 92 | | `keystroke(keys:string, evt:Event)` | Simulate a user pressing a key combination | 93 | | `typedText(text:string)` | Simulate a user typing some text. | 94 | | `selectionIsCollapsed():boolean` | True if the selection is collapsed, i.e. single insertion point | 95 | | `selectionDepth():number` | Return the depth of the selection group. If the selection is at the root level, returns 0. If the selection is a portion of the numerator of a fraction which is at the root level, return 1. Note that in that case, the numerator would be the "selection group" | 96 | | `selectionAtStart():boolean` | Return true if the selection starts at the beginning of the selection group | 97 | | `selectionAtEnd():boolean` | Return true if the selection extends to the end of the selection group | 98 | | `select()` | Select the content of the mathfield | 99 | 100 | ### Selectors 101 | 102 | Selectors can be passed to [`Mathfield.executeCommand()`]{@link 103 | Mathfield#executeCommand} to execute various commands. They can also be 104 | associated with keys in virtual keyboard. 105 | 106 | See {@tutorial SELECTORS} for a list of all the selectors. 107 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MathLive with Vue.js 6 | 7 | 8 | 9 | 53 |
54 |

MathLive with Vue.js

55 | 56 | f(x)= 65 |
{{keystroke}}
66 |
LaTeX: {{formula}}
67 |
Spoken text: {{asSpokenText()}}
68 | 69 | 70 | 71 |
\[x^2 = x*x\]
72 |
73 | 74 | 75 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-mathlive", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "vue-mathlive", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "mathlive": "latest" 13 | }, 14 | "devDependencies": { 15 | "http-server": "^0.12.3" 16 | } 17 | }, 18 | "node_modules/async": { 19 | "version": "2.6.4", 20 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", 21 | "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", 22 | "dev": true, 23 | "dependencies": { 24 | "lodash": "^4.17.14" 25 | } 26 | }, 27 | "node_modules/basic-auth": { 28 | "version": "1.1.0", 29 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", 30 | "integrity": "sha512-CtGuTyWf3ig+sgRyC7uP6DM3N+5ur/p8L+FPfsd+BbIfIs74TFfCajZTHnCw6K5dqM0bZEbRIqRy1fAdiUJhTA==", 31 | "dev": true, 32 | "engines": { 33 | "node": ">= 0.6" 34 | } 35 | }, 36 | "node_modules/call-bind": { 37 | "version": "1.0.2", 38 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 39 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 40 | "dev": true, 41 | "dependencies": { 42 | "function-bind": "^1.1.1", 43 | "get-intrinsic": "^1.0.2" 44 | }, 45 | "funding": { 46 | "url": "https://github.com/sponsors/ljharb" 47 | } 48 | }, 49 | "node_modules/colors": { 50 | "version": "1.4.0", 51 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 52 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", 53 | "dev": true, 54 | "engines": { 55 | "node": ">=0.1.90" 56 | } 57 | }, 58 | "node_modules/corser": { 59 | "version": "2.0.1", 60 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", 61 | "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", 62 | "dev": true, 63 | "engines": { 64 | "node": ">= 0.4.0" 65 | } 66 | }, 67 | "node_modules/debug": { 68 | "version": "3.2.7", 69 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 70 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 71 | "dev": true, 72 | "dependencies": { 73 | "ms": "^2.1.1" 74 | } 75 | }, 76 | "node_modules/ecstatic": { 77 | "version": "3.3.2", 78 | "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", 79 | "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", 80 | "deprecated": "This package is unmaintained and deprecated. See the GH Issue 259.", 81 | "dev": true, 82 | "dependencies": { 83 | "he": "^1.1.1", 84 | "mime": "^1.6.0", 85 | "minimist": "^1.1.0", 86 | "url-join": "^2.0.5" 87 | }, 88 | "bin": { 89 | "ecstatic": "lib/ecstatic.js" 90 | } 91 | }, 92 | "node_modules/eventemitter3": { 93 | "version": "4.0.7", 94 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", 95 | "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", 96 | "dev": true 97 | }, 98 | "node_modules/follow-redirects": { 99 | "version": "1.15.2", 100 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", 101 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", 102 | "dev": true, 103 | "funding": [ 104 | { 105 | "type": "individual", 106 | "url": "https://github.com/sponsors/RubenVerborgh" 107 | } 108 | ], 109 | "engines": { 110 | "node": ">=4.0" 111 | }, 112 | "peerDependenciesMeta": { 113 | "debug": { 114 | "optional": true 115 | } 116 | } 117 | }, 118 | "node_modules/function-bind": { 119 | "version": "1.1.1", 120 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 121 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 122 | "dev": true 123 | }, 124 | "node_modules/get-intrinsic": { 125 | "version": "1.1.3", 126 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", 127 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", 128 | "dev": true, 129 | "dependencies": { 130 | "function-bind": "^1.1.1", 131 | "has": "^1.0.3", 132 | "has-symbols": "^1.0.3" 133 | }, 134 | "funding": { 135 | "url": "https://github.com/sponsors/ljharb" 136 | } 137 | }, 138 | "node_modules/has": { 139 | "version": "1.0.3", 140 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 141 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 142 | "dev": true, 143 | "dependencies": { 144 | "function-bind": "^1.1.1" 145 | }, 146 | "engines": { 147 | "node": ">= 0.4.0" 148 | } 149 | }, 150 | "node_modules/has-symbols": { 151 | "version": "1.0.3", 152 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 153 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 154 | "dev": true, 155 | "engines": { 156 | "node": ">= 0.4" 157 | }, 158 | "funding": { 159 | "url": "https://github.com/sponsors/ljharb" 160 | } 161 | }, 162 | "node_modules/he": { 163 | "version": "1.2.0", 164 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 165 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 166 | "dev": true, 167 | "bin": { 168 | "he": "bin/he" 169 | } 170 | }, 171 | "node_modules/http-proxy": { 172 | "version": "1.18.1", 173 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", 174 | "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", 175 | "dev": true, 176 | "dependencies": { 177 | "eventemitter3": "^4.0.0", 178 | "follow-redirects": "^1.0.0", 179 | "requires-port": "^1.0.0" 180 | }, 181 | "engines": { 182 | "node": ">=8.0.0" 183 | } 184 | }, 185 | "node_modules/http-server": { 186 | "version": "0.12.3", 187 | "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", 188 | "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", 189 | "dev": true, 190 | "dependencies": { 191 | "basic-auth": "^1.0.3", 192 | "colors": "^1.4.0", 193 | "corser": "^2.0.1", 194 | "ecstatic": "^3.3.2", 195 | "http-proxy": "^1.18.0", 196 | "minimist": "^1.2.5", 197 | "opener": "^1.5.1", 198 | "portfinder": "^1.0.25", 199 | "secure-compare": "3.0.1", 200 | "union": "~0.5.0" 201 | }, 202 | "bin": { 203 | "hs": "bin/http-server", 204 | "http-server": "bin/http-server" 205 | }, 206 | "engines": { 207 | "node": ">=6" 208 | } 209 | }, 210 | "node_modules/lodash": { 211 | "version": "4.17.21", 212 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 213 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 214 | "dev": true 215 | }, 216 | "node_modules/mathlive": { 217 | "version": "0.83.0", 218 | "resolved": "https://registry.npmjs.org/mathlive/-/mathlive-0.83.0.tgz", 219 | "integrity": "sha512-bdFHuQisTEAkHShLYvobOSNYGCyRpDPSTNnsgnIPzwtsRbsTIvZpdKvryHHScotibZ8E/3T1xTr62uxdhxC+1Q==", 220 | "engines": { 221 | "node": ">=16.14.2", 222 | "npm": ">=8.5.0" 223 | }, 224 | "funding": { 225 | "type": "individual", 226 | "url": "https://paypal.me/arnogourdol" 227 | } 228 | }, 229 | "node_modules/mime": { 230 | "version": "1.6.0", 231 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 232 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 233 | "dev": true, 234 | "bin": { 235 | "mime": "cli.js" 236 | }, 237 | "engines": { 238 | "node": ">=4" 239 | } 240 | }, 241 | "node_modules/minimist": { 242 | "version": "1.2.6", 243 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", 244 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", 245 | "dev": true 246 | }, 247 | "node_modules/mkdirp": { 248 | "version": "0.5.6", 249 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 250 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 251 | "dev": true, 252 | "dependencies": { 253 | "minimist": "^1.2.6" 254 | }, 255 | "bin": { 256 | "mkdirp": "bin/cmd.js" 257 | } 258 | }, 259 | "node_modules/ms": { 260 | "version": "2.1.3", 261 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 262 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 263 | "dev": true 264 | }, 265 | "node_modules/object-inspect": { 266 | "version": "1.12.2", 267 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 268 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", 269 | "dev": true, 270 | "funding": { 271 | "url": "https://github.com/sponsors/ljharb" 272 | } 273 | }, 274 | "node_modules/opener": { 275 | "version": "1.5.2", 276 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", 277 | "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", 278 | "dev": true, 279 | "bin": { 280 | "opener": "bin/opener-bin.js" 281 | } 282 | }, 283 | "node_modules/portfinder": { 284 | "version": "1.0.32", 285 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", 286 | "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", 287 | "dev": true, 288 | "dependencies": { 289 | "async": "^2.6.4", 290 | "debug": "^3.2.7", 291 | "mkdirp": "^0.5.6" 292 | }, 293 | "engines": { 294 | "node": ">= 0.12.0" 295 | } 296 | }, 297 | "node_modules/qs": { 298 | "version": "6.11.0", 299 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 300 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 301 | "dev": true, 302 | "dependencies": { 303 | "side-channel": "^1.0.4" 304 | }, 305 | "engines": { 306 | "node": ">=0.6" 307 | }, 308 | "funding": { 309 | "url": "https://github.com/sponsors/ljharb" 310 | } 311 | }, 312 | "node_modules/requires-port": { 313 | "version": "1.0.0", 314 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 315 | "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", 316 | "dev": true 317 | }, 318 | "node_modules/secure-compare": { 319 | "version": "3.0.1", 320 | "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", 321 | "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", 322 | "dev": true 323 | }, 324 | "node_modules/side-channel": { 325 | "version": "1.0.4", 326 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 327 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 328 | "dev": true, 329 | "dependencies": { 330 | "call-bind": "^1.0.0", 331 | "get-intrinsic": "^1.0.2", 332 | "object-inspect": "^1.9.0" 333 | }, 334 | "funding": { 335 | "url": "https://github.com/sponsors/ljharb" 336 | } 337 | }, 338 | "node_modules/union": { 339 | "version": "0.5.0", 340 | "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", 341 | "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", 342 | "dev": true, 343 | "dependencies": { 344 | "qs": "^6.4.0" 345 | }, 346 | "engines": { 347 | "node": ">= 0.8.0" 348 | } 349 | }, 350 | "node_modules/url-join": { 351 | "version": "2.0.5", 352 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", 353 | "integrity": "sha512-c2H1fIgpUdwFRIru9HFno5DT73Ok8hg5oOb5AT3ayIgvCRfxgs2jyt5Slw8kEB7j3QUr6yJmMPDT/odjk7jXow==", 354 | "dev": true 355 | } 356 | }, 357 | "dependencies": { 358 | "async": { 359 | "version": "2.6.4", 360 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", 361 | "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", 362 | "dev": true, 363 | "requires": { 364 | "lodash": "^4.17.14" 365 | } 366 | }, 367 | "basic-auth": { 368 | "version": "1.1.0", 369 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", 370 | "integrity": "sha512-CtGuTyWf3ig+sgRyC7uP6DM3N+5ur/p8L+FPfsd+BbIfIs74TFfCajZTHnCw6K5dqM0bZEbRIqRy1fAdiUJhTA==", 371 | "dev": true 372 | }, 373 | "call-bind": { 374 | "version": "1.0.2", 375 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 376 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 377 | "dev": true, 378 | "requires": { 379 | "function-bind": "^1.1.1", 380 | "get-intrinsic": "^1.0.2" 381 | } 382 | }, 383 | "colors": { 384 | "version": "1.4.0", 385 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 386 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", 387 | "dev": true 388 | }, 389 | "corser": { 390 | "version": "2.0.1", 391 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", 392 | "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", 393 | "dev": true 394 | }, 395 | "debug": { 396 | "version": "3.2.7", 397 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 398 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 399 | "dev": true, 400 | "requires": { 401 | "ms": "^2.1.1" 402 | } 403 | }, 404 | "ecstatic": { 405 | "version": "3.3.2", 406 | "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", 407 | "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", 408 | "dev": true, 409 | "requires": { 410 | "he": "^1.1.1", 411 | "mime": "^1.6.0", 412 | "minimist": "^1.1.0", 413 | "url-join": "^2.0.5" 414 | } 415 | }, 416 | "eventemitter3": { 417 | "version": "4.0.7", 418 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", 419 | "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", 420 | "dev": true 421 | }, 422 | "follow-redirects": { 423 | "version": "1.15.2", 424 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", 425 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", 426 | "dev": true 427 | }, 428 | "function-bind": { 429 | "version": "1.1.1", 430 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 431 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 432 | "dev": true 433 | }, 434 | "get-intrinsic": { 435 | "version": "1.1.3", 436 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", 437 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", 438 | "dev": true, 439 | "requires": { 440 | "function-bind": "^1.1.1", 441 | "has": "^1.0.3", 442 | "has-symbols": "^1.0.3" 443 | } 444 | }, 445 | "has": { 446 | "version": "1.0.3", 447 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 448 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 449 | "dev": true, 450 | "requires": { 451 | "function-bind": "^1.1.1" 452 | } 453 | }, 454 | "has-symbols": { 455 | "version": "1.0.3", 456 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 457 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 458 | "dev": true 459 | }, 460 | "he": { 461 | "version": "1.2.0", 462 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 463 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 464 | "dev": true 465 | }, 466 | "http-proxy": { 467 | "version": "1.18.1", 468 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", 469 | "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", 470 | "dev": true, 471 | "requires": { 472 | "eventemitter3": "^4.0.0", 473 | "follow-redirects": "^1.0.0", 474 | "requires-port": "^1.0.0" 475 | } 476 | }, 477 | "http-server": { 478 | "version": "0.12.3", 479 | "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", 480 | "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", 481 | "dev": true, 482 | "requires": { 483 | "basic-auth": "^1.0.3", 484 | "colors": "^1.4.0", 485 | "corser": "^2.0.1", 486 | "ecstatic": "^3.3.2", 487 | "http-proxy": "^1.18.0", 488 | "minimist": "^1.2.5", 489 | "opener": "^1.5.1", 490 | "portfinder": "^1.0.25", 491 | "secure-compare": "3.0.1", 492 | "union": "~0.5.0" 493 | } 494 | }, 495 | "lodash": { 496 | "version": "4.17.21", 497 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 498 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 499 | "dev": true 500 | }, 501 | "mathlive": { 502 | "version": "0.83.0", 503 | "resolved": "https://registry.npmjs.org/mathlive/-/mathlive-0.83.0.tgz", 504 | "integrity": "sha512-bdFHuQisTEAkHShLYvobOSNYGCyRpDPSTNnsgnIPzwtsRbsTIvZpdKvryHHScotibZ8E/3T1xTr62uxdhxC+1Q==" 505 | }, 506 | "mime": { 507 | "version": "1.6.0", 508 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 509 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 510 | "dev": true 511 | }, 512 | "minimist": { 513 | "version": "1.2.6", 514 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", 515 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", 516 | "dev": true 517 | }, 518 | "mkdirp": { 519 | "version": "0.5.6", 520 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 521 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 522 | "dev": true, 523 | "requires": { 524 | "minimist": "^1.2.6" 525 | } 526 | }, 527 | "ms": { 528 | "version": "2.1.3", 529 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 530 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 531 | "dev": true 532 | }, 533 | "object-inspect": { 534 | "version": "1.12.2", 535 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 536 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", 537 | "dev": true 538 | }, 539 | "opener": { 540 | "version": "1.5.2", 541 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", 542 | "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", 543 | "dev": true 544 | }, 545 | "portfinder": { 546 | "version": "1.0.32", 547 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", 548 | "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", 549 | "dev": true, 550 | "requires": { 551 | "async": "^2.6.4", 552 | "debug": "^3.2.7", 553 | "mkdirp": "^0.5.6" 554 | } 555 | }, 556 | "qs": { 557 | "version": "6.11.0", 558 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 559 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 560 | "dev": true, 561 | "requires": { 562 | "side-channel": "^1.0.4" 563 | } 564 | }, 565 | "requires-port": { 566 | "version": "1.0.0", 567 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 568 | "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", 569 | "dev": true 570 | }, 571 | "secure-compare": { 572 | "version": "3.0.1", 573 | "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", 574 | "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", 575 | "dev": true 576 | }, 577 | "side-channel": { 578 | "version": "1.0.4", 579 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 580 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 581 | "dev": true, 582 | "requires": { 583 | "call-bind": "^1.0.0", 584 | "get-intrinsic": "^1.0.2", 585 | "object-inspect": "^1.9.0" 586 | } 587 | }, 588 | "union": { 589 | "version": "0.5.0", 590 | "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", 591 | "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", 592 | "dev": true, 593 | "requires": { 594 | "qs": "^6.4.0" 595 | } 596 | }, 597 | "url-join": { 598 | "version": "2.0.5", 599 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", 600 | "integrity": "sha512-c2H1fIgpUdwFRIru9HFno5DT73Ok8hg5oOb5AT3ayIgvCRfxgs2jyt5Slw8kEB7j3QUr6yJmMPDT/odjk7jXow==", 601 | "dev": true 602 | } 603 | } 604 | } 605 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-mathlive", 3 | "version": "1.0.0", 4 | "description": "Example of using the Vue wrapper for MathLive math editor", 5 | "main": "index.html", 6 | "scripts": { 7 | "start": "http-server --cors -o" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/arnog/vue-mathlive.git" 12 | }, 13 | "keywords": [ 14 | "vue", 15 | "math", 16 | "editor", 17 | "mathlive", 18 | "vuejs" 19 | ], 20 | "author": "https://github.com/arnog", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/arnog/vue-mathlive/issues" 24 | }, 25 | "homepage": "https://github.com/arnog/vue-mathlive#readme", 26 | "dependencies": { 27 | "mathlive": "latest" 28 | }, 29 | "devDependencies": { 30 | "http-server": "^0.12.3" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /screencast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arnog/vue-mathlive/a5e32aa9ab8b8689c9e4eed9f28db40a88292116/screencast.gif -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: sans-serif; 3 | color: #444; 4 | background-color: #f9f9f9; 5 | } 6 | main { 7 | max-width: 820px; 8 | margin: auto; 9 | } 10 | .mathfield { 11 | border: 1px solid #ddd; 12 | padding:5px; 13 | margin: 10px 0 10px 0; 14 | border-radius:5px; 15 | background-color: #fff; 16 | } 17 | .output { 18 | padding:5px; 19 | margin: 20px 0 20px 0; 20 | border-radius:5px; 21 | border: 1px solid #000; 22 | 23 | font-family: "Source Code Pro", Menlo, "Bitstream Vera Sans Mono", Monaco, Courier, "Andale Mono", monospace; 24 | color: #f0c674; 25 | background: #35434e; 26 | } 27 | label { 28 | font-weight: bold; 29 | } 30 | button { 31 | background: none; 32 | border: 1px solid rgba(0, 0, 0, .12); 33 | border-radius: 4px; 34 | color: #0066ce; 35 | fill: #0066ce; 36 | position: relative; 37 | height: 36px; 38 | line-height: 36px; 39 | margin: 0 18px 0 0; 40 | min-width: 64px; 41 | padding: 0 16px; 42 | display: inline-block; 43 | overflow: hidden; 44 | will-change: box-shadow; 45 | transition: box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1); 46 | outline: none; 47 | cursor: pointer; 48 | text-decoration: none; 49 | text-align: center; 50 | vertical-align: middle; 51 | user-select: none; 52 | 53 | font-size: 16px; 54 | letter-spacing: 0.08929em; 55 | text-transform: uppercase; 56 | box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.2), 57 | 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 58 | 0px 3px 1px -2px rgba(0, 0, 0, 0.12); 59 | } 60 | button:first-child { 61 | margin-left: 0; 62 | } 63 | button:hover { 64 | background-color: rgba(0,0,0,0.08); 65 | } 66 | button:active{ 67 | background-color: white; 68 | } 69 | --------------------------------------------------------------------------------