您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Use `code` for inline code. Automatically fix quotes in code tags. Link to a section of text easily.
当前为
- // ==UserScript==
- // @name Medium: Editor For Programmers
- // @namespace https://github.com/Zren/
- // @version 3
- // @description Use `code` for inline code. Automatically fix quotes in code tags. Link to a section of text easily.
- // @author Zren
- // @icon https://medium.com/favicon.ico
- // @match https://medium.com/p/*/edit
- // @grant none
- // ==/UserScript==
- (function(){
- function wrapInlineCode() {
- var tagBefore = '<code class="markup--code"><strong class="markup--strong">';
- var tagAfter = '</strong></code>';
- var sel = window.getSelection();
- if (sel.type === 'Caret' && sel.focusNode.nodeName === "#text") {
- // Note: Does not trigger if first character in text node, since the focus isn't a Text node.
- var str = sel.focusNode.nodeValue;
- var before = str.substr(0, sel.focusOffset - 1);
- var after = str.substr(sel.focusOffset);
- console.log("Before: ", before);
- console.log("After: ", after);
- var index = before.lastIndexOf('`');
- if (index >= 0) {
- // we just typed the right quote
- if (index === before.length-1) {
- // ``
- // Ignore
- } else {
- // `...`
- var range = document.createRange();
- range.setStart(sel.focusNode, index);
- range.setEnd(sel.focusNode, sel.focusOffset);
- sel.removeAllRanges();
- sel.addRange(range);
- var html = range.toString();
- html = html.substr(1, html.length-2); // trim ``
- html = tagBefore + html + tagAfter + ' ';
- document.execCommand('insertHTML', false, html);
- range.collapse(false); // move cursor to end
- return;
- }
- }
- var index = after.indexOf('`');
- if (index >= 0) {
- // we just typed the left quote
- if (index == 0) {
- // ``
- // Ignore
- } else {
- var range = document.createRange();
- range.setStart(sel.focusNode, sel.focusOffset - 1);
- range.setEnd(sel.focusNode, sel.focusOffset + index + 1);
- sel.removeAllRanges();
- sel.addRange(range);
- var html = range.toString();
- html = html.substr(1, html.length-2); // trim ``
- html = tagBefore + html + tagAfter + ' ';
- document.execCommand('insertHTML', false, html);
- range.collapse(false); // move cursor to end
- return;
- }
- }
- }
- }
- function alwaysBrInPre(e) {
- var sel = window.getSelection();
- if (sel.type === 'Caret' && sel.focusNode.nodeName === "#text") {
- console.log(sel.focusNode.nodeValue.length, sel.focusOffset, sel.focusNode.nodeValue.substr(sel.focusOffset), sel.focusNode);
- if (sel.focusOffset !== 0) return; // End of line = selecting start of next line.
- // Focused on start of line.
- var el = sel.focusNode;
- while (el) {
- if (!el.parentNode) break; // Don't run on #document element since it doesn't have el.hasAttribute
- if (el.classList && el.classList.contains('section-inner')) break; // Ignore everything outside the post itself.
- if (el != el.parentNode.firstChild) break; // Only match end of line = start of next line.
- if (el.parentNode.tagName == 'PRE') {
- // Insert linebreak <br>
- var secondPre = el.parentNode;
- var firstPre = secondPre.previousSibling;
- firstPre.appendChild(document.createElement('br')); // <br> removed during split
- var newFocusLine = document.createElement('br');
- firstPre.appendChild(newFocusLine); // The actual <br> we wanted to enter.
- // Move all elements back into the first pre.
- while (secondPre.firstChild) {
- firstPre.appendChild(secondPre.firstChild);
- }
- // Delete the second <pre>
- // We can't remove it since it will break the entire editor...
- secondPre.appendChild(document.createElement('br'));
- //secondPre.remove();
- //document.execCommand('delete');
- // Move cursor to new line.
- var range = document.createRange();
- range.setStart(newFocusLine, 0);
- range.collapse(true);
- sel.removeAllRanges();
- sel.addRange(range);
- e.preventDefault();
- }
- el = el.parentNode;
- }
- }
- }
- function onKeyDown(e) {
- if (e.key === '`') {
- setTimeout(wrapInlineCode, 100); // Wait for ` to be written so we can replace it
- } else if (e.keyCode == 9) { // Tab
- e.preventDefault();
- } else if (e.keyCode == 13) { // Enter
- alwaysBrInPre(e);
- } else if (e.key == '6' && e.ctrlKey && e.altKey) {
- console.log('CTRL+ALT+6', e);
- } else {
- console.log('Key:', e.key, e.ctrlKey, e.altKey);
- }
- }
- function fixQuotes() {
- // Fix quotes in <pre> and <code> tags.
- setInterval(function(){
- var codeTags = document.querySelectorAll('pre, code');
- for (var tag of codeTags) {
- if (tag.innerHTML.indexOf('“') >= 0 || tag.innerHTML.indexOf('”') >= 0) {
- tag.innerHTML = tag.innerHTML.replace('“', '"').replace('”', '"');
- }
- }
- }, 1000);
- }
- function showPermalink() {
- // Setup (temporary) permalink to line.
- var tag = document.createElement('a');
- tag.style.position = 'absolute';
- tag.style.display = 'block';
- tag.style.top = '-9999px';
- tag.style.left = 0;
- tag.style.color = '#888';
- tag.innerHTML = '¶'; //'[link]';
- document.body.appendChild(tag);
- function onMouseOver(e) {
- var el = e.relatedTarget || e.target;
- while (el) {
- if (!el.parentNode) break; // Don't run on #document element since it doesn't have el.hasAttribute
- if (el.classList.contains('section-inner')) break; // Ignore everything outside the post itself.
- if (el.hasAttribute('name')) {
- showTag(el)
- break;
- }
- el = el.parentNode;
- }
- }
- function showTag(el) {
- var rect = el.getBoundingClientRect();
- var url = document.querySelector('link[rel="canonical"]').href;
- url = url.substr(0, url.length - '/edit'.length);
- url += '#' + el.getAttribute('name');
- tag.href = 'javascript:window.history.replaceState({}, "", "' + url + '")';
- var tagGuide = document.querySelector('.section-inner');
- var tagGuideRect = tagGuide.getBoundingClientRect();
- var tagRect = tag.getBoundingClientRect();
- tag.style.left = '' + (tagGuideRect.left + window.scrollX - tagRect.width - 60) + 'px';
- tag.style.top = '' + (rect.top + window.scrollY) + 'px';
- }
- var taggedElements = document.querySelectorAll('.postArticle-content');
- for (var el of taggedElements) {
- //el.addEventListener('mouseover', onMouseOver, true);
- el.addEventListener('click', onMouseOver, true);
- }
- }
- function onLoad() {
- // Bind keys
- var main = document.querySelector('main[contenteditable="true"]');
- main.addEventListener('keydown', onKeyDown, true);
- fixQuotes();
- showPermalink();
- }
- function waitForLoad() {
- var main = document.querySelector('main[contenteditable="true"]');
- if (main) {
- onLoad();
- console.log('[Medium: Markdown] Loaded');
- } else {
- setTimeout(waitForLoad, 100);
- }
- }
- setTimeout(waitForLoad, 100);
- })();