Last active
April 4, 2022 14:49
-
-
Save patarapolw/5d47bf4823a1ca6c0396255bcd7efaa4 to your computer and use it in GitHub Desktop.
How do get Markdown-it plugins like https://github.com/lostandfound/markdown-it-ruby inside Discourse
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 markdown-it-plugin for WaniKani Community | |
// @namespace https://community.wanikani.com | |
// @version 0.1 | |
// @description markdown-it-ruby for WaniKani Community. Nothing more than necessary | |
// @author polv | |
// @match https://community.wanikani.com/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=wanikani.com | |
// @grant none | |
// ==/UserScript== | |
;(function () { | |
'use strict' | |
const plugin = (function () { | |
//... | |
function ruby_plugin(md) { | |
md.inline.ruler.before('text', 'ddmd_ruby', ddmd_ruby) | |
} | |
return ruby_plugin | |
})() | |
const markdownIt = require('pretty-text/engines/discourse-markdown-it') | |
const oldCook = markdownIt.cook | |
markdownIt.cook = function (raw, opts) { | |
opts.engine.use(plugin) | |
return oldCook.bind(this)(raw, opts) | |
} | |
})() |
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 markdown-it-ruby for WaniKani Community | |
// @namespace https://community.wanikani.com | |
// @version 0.1 | |
// @description markdown-it-ruby for WaniKani Community. Nothing more than necessary | |
// @author polv | |
// @match https://community.wanikani.com/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=wanikani.com | |
// @grant none | |
// ==/UserScript== | |
;(function () { | |
'use strict' | |
const plugin = (function () { | |
// Copied from https://github.com/lostandfound/markdown-it-ruby | |
function ddmd_ruby(state, silent) { | |
var token, | |
tokens, | |
max = state.posMax, | |
start = state.pos, | |
devPos, | |
closePos, | |
baseText, | |
rubyText, | |
baseArray, | |
rubyArray | |
if (silent) { | |
return false | |
} | |
if (state.src.charCodeAt(start) !== 0x7b /* { */) { | |
return false | |
} | |
if (start + 4 >= max) { | |
return false | |
} | |
state.pos = start + 1 | |
while (state.pos < max) { | |
if (devPos) { | |
if ( | |
state.src.charCodeAt(state.pos) === 0x7d /* } */ && | |
state.src.charCodeAt(state.pos - 1) !== 0x5c /* \ */ | |
) { | |
closePos = state.pos | |
break | |
} | |
} else if ( | |
state.src.charCodeAt(state.pos) === 0x7c /* | */ && | |
state.src.charCodeAt(state.pos - 1) !== 0x5c /* \ */ | |
) { | |
devPos = state.pos | |
} | |
state.pos++ | |
} | |
if (!closePos || start + 1 === state.pos) { | |
state.pos = start | |
return false | |
} | |
state.posMax = state.pos | |
state.pos = start + 1 | |
token = state.push('ruby_open', 'ruby', 1) | |
token.markup = '{' | |
baseText = state.src.slice(start + 1, devPos) | |
rubyText = state.src.slice(devPos + 1, closePos) | |
baseArray = baseText.split('') | |
rubyArray = rubyText.split('|') | |
if (baseArray.length === rubyArray.length) { | |
baseArray.forEach(function (content, idx) { | |
state.md.inline.parse(content, state.md, state.env, (tokens = [])) | |
tokens.forEach(function (t) { | |
state.tokens.push(t) | |
}) | |
token = state.push('rt_open', 'rt', 1) | |
state.md.inline.parse( | |
rubyArray[idx], | |
state.md, | |
state.env, | |
(tokens = []) | |
) | |
tokens.forEach(function (t) { | |
state.tokens.push(t) | |
}) | |
token = state.push('rt_close', 'rt', -1) | |
}) | |
} else { | |
state.md.inline.parse(baseText, state.md, state.env, (tokens = [])) | |
tokens.forEach(function (t) { | |
state.tokens.push(t) | |
}) | |
token = state.push('rt_open', 'rt', 1) | |
state.md.inline.parse(rubyText, state.md, state.env, (tokens = [])) | |
tokens.forEach(function (t) { | |
state.tokens.push(t) | |
}) | |
token = state.push('rt_close', 'rt', -1) | |
} | |
token = state.push('ruby_close', 'ruby', -1) | |
token.markup = '}' | |
state.pos = state.posMax + 1 | |
state.posMax = max | |
return true | |
} | |
function ruby_plugin(md) { | |
md.inline.ruler.before('text', 'ddmd_ruby', ddmd_ruby) | |
} | |
return ruby_plugin | |
})() | |
const markdownIt = require('pretty-text/engines/discourse-markdown-it') | |
const oldCook = markdownIt.cook | |
markdownIt.cook = function (raw, opts) { | |
opts.engine.use(plugin) | |
return oldCook.bind(this)(raw, opts) | |
} | |
})() |
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 Editor overlay for WaniKani Community | |
// @namespace https://community.wanikani.com | |
// @version 0.1 | |
// @description Editor overlay for WaniKani Community. | |
// @author polv | |
// @match https://community.wanikani.com/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=wanikani.com | |
// @grant none | |
// ==/UserScript== | |
;(function () { | |
'use strict' | |
/** | |
* | |
* @param {string} raw | |
* @returns | |
*/ | |
function fromVanilla(raw) { | |
return raw | |
} | |
/** | |
* | |
* @param {string} raw | |
* @returns | |
*/ | |
function toVanilla(raw) { | |
return raw | |
} | |
/** @type {HTMLTextAreaElement} */ | |
let elTextArea = null | |
const getTextArea = () => document.querySelector('textarea.d-editor-input') | |
function initTextArea() { | |
if (!(elTextArea = getTextArea())) { | |
const obs = new MutationObserver(() => { | |
if ((elTextArea = getTextArea())) { | |
obs.disconnect() | |
onNewTextArea() | |
} | |
}) | |
obs.observe(document.body, { | |
childList: true, | |
subtree: true | |
}) | |
} else { | |
onNewTextArea() | |
} | |
} | |
function onNewTextArea() { | |
elTextArea.value = fromVanilla(elTextArea.value) | |
const endObs = new MutationObserver(() => { | |
if (!getTextArea()) { | |
elTextArea = null | |
endObs.disconnect() | |
onCloseTextArea() | |
} | |
}) | |
endObs.observe(document.body, { | |
childList: true, | |
subtree: true | |
}) | |
} | |
function onCloseTextArea() { | |
initTextArea() | |
} | |
let alreadyInjected = false | |
function injectIntoDiscourse() { | |
if (alreadyInjected) return | |
alreadyInjected = true | |
// greasemonkey workaround: unsafeWindow + exportFunction | |
let w = typeof unsafeWindow === 'undefined' ? window : unsafeWindow | |
let e = typeof exportFunction === 'undefined' ? (o) => o : exportFunction | |
injectCustomCook(w, e) | |
injectCustomSave(w, e) | |
let oldCook = w.require('pretty-text/engines/discourse-markdown-it').cook | |
w.require('pretty-text/engines/discourse-markdown-it').cook = e( | |
(raw, opts) => oldCook(toVanilla(raw), opts), | |
w | |
) | |
let oldSave = w.require('discourse/controllers/composer').default.prototype | |
.save | |
w.require('discourse/controllers/composer').default.prototype.save = e( | |
function (t) { | |
tText.value = toVanilla(tText.value) | |
tText.dispatchEvent( | |
new Event('change', { bubbles: true, cancelable: true }) | |
) | |
oldSave.call(this, t) | |
}, | |
w | |
) | |
} | |
injectIntoDiscourse() | |
initTextArea() | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment