您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A userscript that adds a button to insert RTL text blocks in comments
您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
- // ==UserScript==
- // @name GitHub RTL Comments
- // @version 1.3.4
- // @description A userscript that adds a button to insert RTL text blocks in comments
- // @license MIT
- // @author Rob Garrison
- // @namespace https://github.com/Mottie
- // @match https://github.com/*
- // @match https://gist.github.com/*
- // @run-at document-idle
- // @grant GM_addStyle
- // @grant GM.addStyle
- // @connect github.com
- // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js?updated=20180103
- // @require https://greatest.deepsurf.us/scripts/28721-mutations/code/mutations.js?version=1108163
- // @require https://greatest.deepsurf.us/scripts/28239-rangy-inputs-mod-js/code/rangy-inputs-modjs.js?version=181769
- // @icon https://github.githubassets.com/pinned-octocat.svg
- // @supportURL https://github.com/Mottie/GitHub-userscripts/issues
- // ==/UserScript==
- (() => {
- "use strict";
- const icon = `
- <svg class="octicon" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
- <path d="M14 3v8l-4-4m-7 7V6C1 6 0 5 0 3s1-3 3-3h7v2H9v12H7V2H5v12H3z"/>
- </svg>`,
- // maybe using ⁧ RTL text ⁦ (isolates) is a better combo?
- openRTL = "‏", // https://en.wikipedia.org/wiki/Right-to-left_mark
- closeRTL = "‎", // https://en.wikipedia.org/wiki/Left-to-right_mark
- regexOpen = /\u200f/ig,
- regexClose = /\u200e/ig,
- regexSplit = /(\u200f|\u200e)/ig;
- GM.addStyle(`
- .ghu-rtl-css { direction:rtl; text-align:right; }
- /* delegated binding; ignore clicks on svg & path */
- .ghu-rtl > * { pointer-events:none; }
- /* override RTL on code blocks */
- .js-preview-body pre, .markdown-body pre,
- .js-preview-body code, .markdown-body code {
- direction:ltr;
- text-align:left;
- unicode-bidi:normal;
- }
- `);
- // Add RTL button
- function addRtlButton() {
- let el, button,
- toolbars = $$(".toolbar-commenting"),
- indx = toolbars.length;
- if (indx) {
- button = document.createElement("button");
- button.type = "button";
- button.className = "btn-octicon ghu-rtl toolbar-item tooltipped tooltipped-n";
- button.setAttribute("aria-label", "RTL");
- button.setAttribute("tabindex", "-1");
- button.innerHTML = icon;
- while (indx--) {
- el = toolbars[indx];
- if (!$(".ghu-rtl", el)) {
- el.insertBefore(button.cloneNode(true), el.childNodes[0]);
- }
- }
- }
- checkRTL();
- }
- function checkContent(el) {
- // check the contents, and wrap in either a span or div
- let indx, // useDiv,
- html = el.innerHTML,
- parts = html.split(regexSplit),
- len = parts.length;
- for (indx = 0; indx < len; indx++) {
- if (regexOpen.test(parts[indx])) {
- // check if the content contains HTML
- // useDiv = regexTestHTML.test(parts[indx + 1]);
- // parts[indx] = (useDiv ? "<div" : "<span") + " class='ghu-rtl-css'>";
- parts[indx] = "<div class='ghu-rtl-css'>";
- } else if (regexClose.test(parts[indx])) {
- // parts[indx] = useDiv ? "</div>" : "</span>";
- parts[indx] = "</div>";
- }
- }
- el.innerHTML = parts.join("");
- // remove empty paragraph wrappers (may have previously contained the mark)
- return el.innerHTML.replace(/<p><\/p>/g, "");
- }
- function checkRTL() {
- let clone,
- indx = 0,
- div = document.createElement("div"),
- containers = $$(".js-preview-body, .markdown-body"),
- len = containers.length,
- // main loop
- loop = () => {
- let el, tmp,
- max = 0;
- while (max < 10 && indx < len) {
- if (indx > len) {
- return;
- }
- el = containers[indx];
- tmp = el.innerHTML;
- if (regexOpen.test(tmp) || regexClose.test(tmp)) {
- clone = div.cloneNode();
- clone.innerHTML = tmp;
- // now we can replace all instances
- el.innerHTML = checkContent(clone);
- max++;
- }
- indx++;
- }
- if (indx < len) {
- setTimeout(() => {
- loop();
- }, 200);
- }
- };
- loop();
- }
- function addBindings() {
- window.rangyInput.init();
- $("body").addEventListener("click", event => {
- let textarea,
- target = event.target;
- if (target && target.classList.contains("ghu-rtl")) {
- textarea = closest(".previewable-comment-form", target);
- textarea = $(".comment-form-textarea", textarea);
- textarea.focus();
- // add extra white space around the tags
- window.rangyInput.surroundSelectedText(
- textarea,
- " " + openRTL + " ",
- " " + closeRTL + " "
- );
- return false;
- }
- });
- }
- function $(selector, el) {
- return (el || document).querySelector(selector);
- }
- function $$(selector, el) {
- return Array.from((el || document).querySelectorAll(selector));
- }
- function closest(selector, el) {
- while (el && el.nodeType === 1) {
- if (el.matches(selector)) {
- return el;
- }
- el = el.parentNode;
- }
- return null;
- }
- document.addEventListener("ghmo:container", addRtlButton);
- document.addEventListener("ghmo:preview", checkRTL);
- addBindings();
- addRtlButton();
- })();