Last active
June 13, 2021 04:06
-
-
Save camilstaps/40b62910f0206ef97d50822014870884 to your computer and use it in GitHub Desktop.
Stack Exchange HTML math editor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Stack Exchange HTML math editor | |
// @author Camil Staps <info@camilstaps.nl> | |
// @namespace nl.camilstaps.htmlmath | |
// @description Adds a math bar to the Stack Exchange editor | |
// @include /^https?:\/\/(.*\.)?stackoverflow\.com/.*$/ | |
// @include /^https?:\/\/(.*\.)?serverfault\.com/.*$/ | |
// @include /^https?:\/\/(.*\.)?superuser\.com/.*$/ | |
// @include /^https?:\/\/(.*\.)?stackexchange\.com/.*$/ | |
// @include /^https?:\/\/(.*\.)?askubuntu\.com/.*$/ | |
// @include /^https?:\/\/(.*\.)?mathoverflow\.com/.*$/ | |
// @include /^https?:\/\/discuss\.area51\.stackexchange\.com/.*$/ | |
// @include /^https?:\/\/stackapps\.com/.*$/ | |
// @version 1.0.0 | |
// @grant none | |
// ==/UserScript== | |
var script = document.createElement('script'); | |
script.setAttribute('src', 'https://unpkg.com/stack-exchange-html-math-editor/math_editor.js'); | |
document.head.appendChild(script); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var insertOrSurroundWith = function(field, prefix, suffix) { | |
return function() { | |
if (document.selection) { | |
field.focus(); | |
var sel = document.selection.createRange(); | |
sel.text = prefix + sel.text + suffix; | |
} else if (field.selectionStart || field.selectionStart == '0') { | |
var start = field.selectionStart; | |
var end = field.selectionEnd; | |
field.value = field.value.substring(0, start) | |
+ prefix + field.value.substring(start, end) + suffix | |
+ field.value.substring(end, field.value.length); | |
field.selectionStart = start + prefix.length; | |
field.selectionEnd = end + prefix.length; | |
} else { | |
field.value += prefix + suffix; | |
} | |
field.onpaste(); | |
field.focus(); | |
}; | |
}; | |
var insert = function(field, text) { | |
return function() { | |
if (document.selection) { | |
field.focus(); | |
var sel = document.selection.createRange(); | |
sel.text = text; | |
} else if (field.selectionStart || field.selectionStart == '0') { | |
var start = field.selectionStart; | |
var end = field.selectionEnd; | |
field.value = field.value.substring(0, start) | |
+ text + field.value.substring(end, field.value.length); | |
field.selectionStart = start + text.length; | |
field.selectionEnd = start + text.length; | |
} else { | |
field.value += text; | |
} | |
field.onpaste(); | |
field.focus(); | |
}; | |
}; | |
var addButton = function(row, label, title, func) { | |
var button = $('<li></li>') | |
.addClass('wmd-button') | |
.attr('title', title) | |
.css('padding', '4px') | |
.css('height', 'inherit') | |
.html(label) | |
.click(func); | |
row.append(button); | |
}; | |
var addSpacer = function(row) { | |
var spacer = $('<li></li>') | |
.addClass('wmd-spacer') | |
.css('height', 'inherit'); | |
row.append(spacer); | |
}; | |
var addMathEditor = function(id) { | |
var bar = $('#wmd-button-bar' + (typeof id == 'undefined' ? '' : '-' + id)); | |
var row = bar.find('.wmd-button-row'); | |
if (row.length == 0) | |
return; | |
var bar = row.parent(); | |
var field = bar.parent().find('.wmd-input')[0]; | |
clearInterval(mathEditorTimer); | |
var button_math = $('<li></li>') | |
.attr('id', 'wmd-math-button') | |
.addClass('wmd-button') | |
.attr('title', 'Show math toolbar') | |
.css('left', '400px') | |
.html('√x') | |
.click(function(){ | |
bar.css('height', 'auto'); | |
var newRow = function() { | |
return $('<ul></ul>') | |
.addClass('wmd-button-row') | |
.css('height', 24) | |
.css('justify-content', 'flex-start') | |
.appendTo(bar); | |
} | |
var rows = [newRow(), newRow(), newRow()]; | |
addButton(rows[0], '≠', 'Not equal to', insert(field, '≠')); | |
addButton(rows[0], '≤', 'Less than or equal to', insert(field, '≤')); | |
addButton(rows[0], '≥', 'Greater than or equal to', insert(field, '≥')); | |
addSpacer(rows[0]); | |
addButton(rows[0], 'x<sup>2</sup>', 'Superscript', insertOrSurroundWith(field, '<sup>', '</sup>')); | |
addButton(rows[0], 'x<sub>2</sub>', 'Subscript', insertOrSurroundWith(field, '<sub>', '</sub>')); | |
addSpacer(rows[0]); | |
addButton(rows[0], '∑', 'Sum', insert(field, '∑')); | |
addButton(rows[0], '∏', 'Product', insert(field, '∏')); | |
addSpacer(rows[0]); | |
addButton(rows[0], 'ℕ', 'Naturals', insert(field, 'ℕ')); | |
addButton(rows[0], 'ℤ', 'Integers', insert(field, 'ℤ')); | |
addButton(rows[0], 'ℚ', 'Rationals', insert(field, 'ℚ')); | |
addButton(rows[0], 'ℝ', 'Reals', insert(field, 'ℝ')); | |
addSpacer(rows[0]); | |
addButton(rows[0], '∣', 'Divides', insert(field, '∣')); | |
addButton(rows[0], '∤', 'Does not divide', insert(field, '∤')); | |
addButton(rows[0], '√', 'Radic', insert(field, '√')); | |
addButton(rows[0], '∞', 'Infinity', insert(field, '∞')); | |
addButton(rows[1], '∅', 'Empty set', insert(field, '∅')); | |
addButton(rows[1], '∈', 'Element of', insert(field, '∈')); | |
addButton(rows[1], '∉', 'Not an element of', insert(field, '∉')); | |
addButton(rows[1], '∩', 'Intersection', insert(field, '∩')); | |
addButton(rows[1], '∪', 'Union', insert(field, '∪')); | |
addButton(rows[1], '⊆', 'Subset of', insert(field, '⊆')); | |
addButton(rows[1], '⊇', 'Superset of', insert(field, '⊇')); | |
addButton(rows[1], '⊂', 'Strict subset of', insert(field, '⊂')); | |
addButton(rows[1], '⊃', 'Strict superset of', insert(field, '⊃')); | |
addButton(rows[1], '⊈', 'Not a subset of', insert(field, '⊈')); | |
addButton(rows[1], '⊉', 'Not a superset of', insert(field, '⊉')); | |
addButton(rows[1], '⊄', 'Not a strict subset of', insert(field, '⊄')); | |
addButton(rows[1], '⊅', 'Not a strict superset of', insert(field, '⊅')); | |
addSpacer(rows[1]); | |
addButton(rows[1], '∀', 'For all', insert(field, '∀')); | |
addButton(rows[1], '∃', 'There exists', insert(field, '∃')); | |
addButton(rows[1], '∄', 'There does not exist', insert(field, '∄')); | |
addButton(rows[2], '¬', 'Negation', insert(field, '¬')); | |
addButton(rows[2], '→', 'Implication', insert(field, '→')); | |
addButton(rows[2], '↔', 'Equivalence', insert(field, '↔')); | |
addButton(rows[2], '∧', 'Conjunction', insert(field, '∧')); | |
addButton(rows[2], '∨', 'Disjunction', insert(field, '∨')); | |
addSpacer(rows[2]); | |
addButton(rows[2], '≡', 'Equivalent to', insert(field, '≡')); | |
addButton(rows[2], '≢', 'Not equivalent to', insert(field, '≢')); | |
addSpacer(rows[2]); | |
addButton(rows[2], '⊢', 'Entails', insert(field, '⊢')); | |
addButton(rows[2], '⊨', 'Tautology', insert(field, '⊨')); | |
addButton(rows[2], '⊤', 'Down tee', insert(field, '⊤')); | |
addButton(rows[2], '⊥', 'Up tee', insert(field, '⊥')); | |
addSpacer(rows[2]); | |
addButton(rows[2], '□', 'Necessarily', insert(field, '□')); | |
addButton(rows[2], '◊', 'Possibly', insert(field, '◊')); | |
var spacer = $('<li></li>').addClass('wmd-spacer wmd-spacer-max'); | |
rows[2].append(spacer); | |
var credits = $('<li></li>') | |
.addClass('wmd-button') | |
.css('padding', '0 3em 0 0'); | |
var link = $('<a></a>') | |
.attr('href', 'https://gist.github.com/camilstaps/40b62910f0206ef97d50822014870884/') | |
.attr('title', 'See source code') | |
.attr('target', '_blank') | |
.text('source'); | |
credits.append(link); | |
rows[2].append(credits); | |
$(this).remove(); | |
field.focus(); | |
}); | |
var spacer = $('<li></li>') | |
.addClass('wmd-spacer'); | |
var maxspacer = row.find('.wmd-spacer-max'); | |
spacer.insertBefore(maxspacer); | |
button_math.insertBefore(maxspacer); | |
}; | |
var bar = $('.wmd-button-bar'); | |
if (bar.length) | |
var mathEditorTimer = setInterval(addMathEditor, 100); | |
$('a.edit-post').click(function(){ | |
var id = /\/posts\/(\d+)\/edit/.exec($(this).attr('href'))[1]; | |
mathEditorTimer = setInterval(addMathEditor, 100, id); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "stack-exchange-html-math-editor", | |
"version": "1.0.0", | |
"description": "Stack Exchange HTML math editor", | |
"main": "HTML_math_editor.user.js", | |
"repository": { | |
"type": "git", | |
"url": "git+https://gist.github.com/40b62910f0206ef97d50822014870884.git" | |
}, | |
"keywords": [ | |
"StackExchange", | |
"Stack", | |
"Exchange", | |
"userscript", | |
"HTML", | |
"math", | |
"mathematics", | |
"symbols" | |
], | |
"author": "", | |
"license": "UNLICENSED", | |
"homepage": "https://gist.github.com/40b62910f0206ef97d50822014870884" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment