import './view-markdown-source.css'; import React from 'dom-chef'; import select from 'select-dom'; import delegate from 'delegate-it'; import features from '../libs/features'; import fetchDom from '../libs/fetch-dom'; import * as icons from '../libs/icons'; import {blurAccessibly} from './comment-fields-keyboard-shortcuts'; const btnBodyMap = new WeakMap>(); async function fetchSource(): Promise { const path = location.pathname.replace(/([^/]+\/[^/]+\/)(blob)/, '$1blame'); const dom = await fetchDom(path, '.blob-wrapper'); dom.classList.add('rgh-markdown-source'); return dom; } // Hide tooltip after click, it’s shown on :focus function blurButton(button: HTMLElement): void { if (button === document.activeElement) { blurAccessibly(button); } } function dispatchEvent(element: HTMLElement, type: keyof GlobalEventHandlersEventMap): void { element.dispatchEvent(new CustomEvent(type, {bubbles: true})); } /* The dom of each version is stored on each button. This acts as an auto-discarded cache without globals, timers, etc. It should also work clicks on buttons sooner than the page loads. */ async function showSource(): Promise { const sourceButton = select('.rgh-md-source')!; const renderedButton = select('.rgh-md-rendered')!; sourceButton.disabled = true; const source = btnBodyMap.get(sourceButton) || fetchSource(); const rendered = btnBodyMap.get(renderedButton) as Element || select('.blob.instapaper_body')!; btnBodyMap.set(sourceButton, source); btnBodyMap.set(renderedButton, rendered); rendered.replaceWith(await source); sourceButton.disabled = false; sourceButton.classList.add('selected'); renderedButton.classList.remove('selected'); blurButton(sourceButton); dispatchEvent(sourceButton, 'rgh:view-markdown-source'); } async function showRendered(): Promise { const sourceButton = select('.rgh-md-source')!; const renderedButton = select('.rgh-md-rendered')!; renderedButton.disabled = true; (await btnBodyMap.get(sourceButton))!.replaceWith(btnBodyMap.get(renderedButton) as Element); renderedButton.disabled = false; sourceButton.classList.remove('selected'); renderedButton.classList.add('selected'); blurButton(renderedButton); dispatchEvent(sourceButton, 'rgh:view-markdown-rendered'); } async function init(): Promise { if (!select.exists('.blob.instapaper_body')) { return false; } delegate('.rgh-md-source:not(.selected)', 'click', showSource); delegate('.rgh-md-rendered:not(.selected)', 'click', showRendered); select('.repository-content .Box-header .d-flex')!.prepend(
); // Add support for permalinks to the code if (location.hash.startsWith('#L')) { await showSource(); // Enable selected line highlight window.dispatchEvent(new HashChangeEvent('hashchange', { oldURL: location.href, newURL: location.href })); } } features.add({ id: __featureName__, description: 'Adds a button to view the source of Markdown files.', screenshot: 'https://user-images.githubusercontent.com/1402241/54814836-7bc39c80-4ccb-11e9-8996-9ecf4f6036cb.png', include: [ features.isSingleFile ], load: features.onAjaxedPages, init });