- // ==UserScript==
- // @name GreasyFork Code: Syntax Highlight by highlight.js
- // @namespace Violentmonkey Scripts
- // @grant none
- // @version 0.4.2
- // @author CY Fung
- // @description To syntax highlight GreasyFork Code by highlight.js
- // @run-at document-start
- // @inject-into page
- // @unwrap
- // @license MIT
- // @match https://greatest.deepsurf.us/*
- // @match https://sleazyfork.org/*
- // @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js
- // @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/javascript.min.js
- // @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/css.min.js
- // @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/stylus.min.js
- // ==/UserScript==
-
-
- (() => {
- let byPass = true;
-
- const resoruces = {
- 'nnfx-light.css': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/nnfx-light.min.css'
- }
-
- function selectAllWithinElement(element) {
- // Clear any current selections
- window.getSelection().removeAllRanges();
-
- // Create a new range
- let range = document.createRange();
-
- // Check if the element exists
- if (element) {
- // Select all content within the element
- range.selectNodeContents(element);
-
- // Add the range to the selection
- window.getSelection().addRange(range);
- } else {
- console.error('Element not found with ID:', element);
- }
- }
- document.addEventListener('keydown', (e) => {
- if (e && e.code === 'KeyA' && e.isTrusted && (e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) {
-
- const target = e.target;
- const container = target ? target.closest('div.code-container') : null;
- const code = container ? container.querySelector('code') : null;
-
- if (container && code) {
-
- e.preventDefault();
- e.stopPropagation();
- e.stopImmediatePropagation();
-
- setTimeout(() => {
- selectAllWithinElement(code);
- }, 1)
-
- }
-
- }
- }, true)
-
-
- const Promise = (async function () { })().constructor;
-
-
- const documentReady = new Promise(resolve => {
- Promise.resolve().then(() => {
- if (document.readyState !== 'loading') {
- resolve();
- } else {
- window.addEventListener("DOMContentLoaded", resolve, false);
- }
- });
- });
-
-
- async function doAction() {
-
- await new Promise(r => setTimeout(r, 1));
-
- document.head.appendChild(document.createElement('style')).textContent = `
-
- .code-container{
- height:100vh;
- }
- .code-container .CodeMirror, .code-container textarea{
- height:100%;
- }
- `;
-
- if (window.requestIdleCallback) await new Promise(r => !!window.requestIdleCallback(r));
- else {
- await new Promise(r => !!window.requestAnimationFrame(r));
- await new Promise(r => !!window.setTimeout(r, 170));
- await new Promise(r => !!window.requestAnimationFrame(r));
- }
-
- byPass = false;
-
- }
-
-
- let mgg = 0;
- async function mTz() {
- if (mgg) return;
- mgg = 1;
- documentReady.then(doAction);
- }
-
- function getElementsByTagName(tag) {
- if (byPass) {
- if (tag === 'pre' || tag === 'code' || tag === 'xmp') {
- if (location.pathname.endsWith('/code')) {
- setTimeout(mTz, 100)
- return [];
- }
- }
- }
- return this.getElementsByTagName331(tag);
- }
-
- async function onBodyHeadReadyAsync() {
-
- if (document.body && document.head) {
-
-
- } else {
-
- const promiseBegin = new Promise(resolve => {
-
- let mo = new MutationObserver(() => {
- if (document.body && document.head) {
- mo.disconnect();
- mo.takeRecords();
- mo = null;
- resolve();
- }
-
- });
- mo.observe(document, { subtree: true, childList: true });
-
- });
-
- await promiseBegin.then();
-
- }
-
- }
-
-
- // Load CSS
- function loadCSS(href) {
- const link = document.createElement('link');
- link.rel = 'stylesheet';
- link.href = href;
- document.head.appendChild(link);
- }
-
- const global_css = `
-
- html {
- line-height: 1.5;
- -webkit-text-size-adjust: 100%;
- -moz-tab-size: 4;
- -o-tab-size: 4;
- tab-size: 4;
- font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
- font-feature-settings: normal;
- font-variation-settings: normal
- }
- /*
- body {
- margin: 0;
- line-height: inherit
- }
-
- hr {
- height: 0;
- color: inherit;
- border-top-width: 1px
- }
-
- abbr:where([title]) {
- -webkit-text-decoration: underline dotted;
- text-decoration: underline dotted
- }
-
- h1,h2,h3,h4,h5,h6 {
- font-size: inherit;
- font-weight: inherit
- }
-
-
- b,strong {
- font-weight: bolder
- }
- */
- .code-container code, .code-container kbd, .code-container pre, .code-container samp {
- font-family: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;
- font-size: 1em
- }
- /*
- small {
- font-size: 80%
- }
-
- sub,sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline
- }
-
- sub {
- bottom: -.25em
- }
-
- sup {
- top: -.5em
- }
-
- table {
- text-indent: 0;
- border-color: inherit;
- border-collapse: collapse
- }
-
- button,input,optgroup,select,textarea {
- font-family: inherit;
- font-feature-settings: inherit;
- font-variation-settings: inherit;
- font-size: 100%;
- font-weight: inherit;
- line-height: inherit;
- color: inherit;
- margin: 0;
- padding: 0
- }
-
- button,select {
- text-transform: none
- }
-
- :-moz-focusring {
- outline: auto
- }
-
- :-moz-ui-invalid {
- box-shadow: none
- }
-
- progress {
- vertical-align: baseline
- }
-
- ::-webkit-inner-spin-button,::-webkit-outer-spin-button {
- height: auto
- }
-
- [type=search] {
- -webkit-appearance: textfield;
- outline-offset: -2px
- }
-
- ::-webkit-search-decoration {
- -webkit-appearance: none
- }
-
- ::-webkit-file-upload-button {
- -webkit-appearance: button;
- font: inherit
- }
-
- summary {
- display: list-item
- }
-
- blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre {
- margin: 0
- }
-
- fieldset {
- margin: 0
- }
-
- fieldset,legend {
- padding: 0
- }
-
- menu,ol,ul {
- list-style: none;
- margin: 0;
- padding: 0
- }
- textarea {
- resize: vertical
- }
-
- input::-moz-placeholder,textarea::-moz-placeholder {
- opacity: 1;
- color: #9ca3af
- }
-
- input::placeholder,textarea::placeholder {
- opacity: 1;
- color: #9ca3af
- }
- */
-
- #script-content > .code-container[class] {
- width: 100%;
- }
-
- .code-container[class] {
- border-radius: 0;
- }
-
- .code-container[class] {
- border-radius: 0;
- }
-
- .code-container > pre:only-child{
- padding:0;
- }
-
- code.hljs[class] {
- /*
- font-family: ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace !important;
- font-size: 9pt;
- */
- font-family: monospace;
- font-size: 13px;
- font-variant-ligatures: contextual;
- line-height: 1.15rem;
- }
-
- .hljs-comment[class], .hljs-quote[class] {
- font-style: inherit;
- color: #259789;
- }
-
- .hljs-add-marker-width .marker-fixed-width[class] {
- user-select: none !important;
- width: calc(var(--hljs-marker-width, 0em) + 16px);
- background: #f4f4f4;
- padding-right: 6px;
- margin-right: 4px;
- contain: paint style;
- }
-
- `;
-
-
- const cssForCodePage = /\/scripts\/\d+[^\s\/\\]*\/code(\/|$)/.test(location.href) ? `
-
- html:not([dkkfv]) div.code-container {
- position: absolute !important;
- display: none;
- }
-
- html:not([dkkfv]) div.code-container > pre{
- display:none;
- }
-
-
- html:not([dkkfv]) code:only-child {
- display:none;
- }
-
-
- .code-container,
- .code-container pre:only-child,
- .code-container pre:only-child code:only-child {
- max-height: calc(100vh + 4px);
- max-width: calc(100vw + 4px);
- }
- ` : '';
-
-
- const cssAdd = `
-
- ${global_css}
-
- ${cssForCodePage}
-
- .code-container {
- max-width: 100%;
- display: inline-flex;
- flex-direction: column;
- overflow: auto;
- border-radius: 8px;
- max-height: 100%;
- overflow: visible;
- }
- .code-container > pre:only-child {
- max-width: 100%;
- display: inline-flex;
- flex-direction: column;
- flex-grow: 1;
- height: 0;
- }
- .code-container > pre:only-child > code:only-child {
- max-width: 100%;
- flex-grow: 1;
- height: 0;
- }
- .code-container pre code {
- padding: 0;
- font-family: Consolas;
- cursor: text;
- overflow: auto;
- }
- .code-container pre code .marker {
- display: inline-block;
- color: #636d83;
- text-align: right;
- padding-right: 20px;
- user-select: none;
- cursor: auto;
- }
-
- .code-container[contenteditable]{
- outline: 0 !important;
- contain: strict;
- }
-
- .code-container[contenteditable]>pre[contenteditable="false"]{
- contain: strict;
- }
-
- `;
-
-
-
-
- HTMLElement.prototype.getElementsByTagName331 = HTMLElement.prototype.getElementsByTagName
- Document.prototype.getElementsByTagName331 = Document.prototype.getElementsByTagName
-
- HTMLElement.prototype.getElementsByTagName = getElementsByTagName
- Document.prototype.getElementsByTagName = getElementsByTagName
-
-
- onBodyHeadReadyAsync().then(() => {
-
- loadCSS(resoruces['nnfx-light.css'])
-
- document.head.appendChild(document.createElement('style')).textContent = `${cssAdd}`;
-
-
-
- });
-
-
- /** @param {HTMLElement} pre */
- async function prepareCodeAreaAsync(pre) {
-
- for (const li of pre.querySelectorAll('li')) {
- li.append(document.createTextNode('\n'));
- }
-
- const codeElement = document.createElement('code');
- // codeElement.classList.add('language-javascript');
- codeElement.innerHTML = pre.innerHTML;
-
- // Clearing the original code container and appending the new one
- // pre.classList = '';
- pre.innerHTML = '';
- // pre.appendChild(codeElement);
-
- // if (pre.querySelector('code')) return;
- const code = codeElement;
-
- const codeContainer = pre.closest('.code-container');
- if (codeContainer && codeContainer.querySelector('.code-container>pre:only-child')) {
- // avoid selection to the outside by mouse dragging
- codeContainer.setAttribute('contenteditable', '');
- codeContainer.querySelector('.code-container>pre:only-child').setAttribute('contenteditable', 'false');
- }
-
-
- // let parentNode = code.parentNode;
- // let nextNode = code.nextSibling;
-
- // code.remove();
- let parentNode = pre;
- let nextNode = null;
- await Promise.resolve().then();
-
- // preset language
- /*
- const text = codeElement.textContent;
- if(/(^|\n)\s*\/\/\s+==UserScript==\s*\n/.test(text)){
- codeElement.classList.add('language-javascript');
- }else if(/(^|\n)\s*\/\*\s+==UserStyle==\s*\n/.test(text)){
- codeElement.classList.add('language-css');
- }
- */
- if (pre.classList.contains('lang-js')) {
- codeElement.classList.add('language-javascript');
- } else if (pre.classList.contains('lang-css')) {
-
- const text = codeElement.textContent;
- let m = /\n\@preprocessor\s+([-_a-zA-Z]{3,8})\s*\n/.exec(text);
- let className = 'language-css'
- if (m) {
- const preprocessor = m[1];
- if (preprocessor === 'stylus') {
- className = 'language-stylus';
- } else if (preprocessor === 'uso') {
- className = 'language-stylus';
- } else if (preprocessor === 'less') {
- className = 'language-less';
- } else if (preprocessor === 'default') {
- className = 'language-stylus';
- } else {
- className = 'language-stylus';
- }
- }
-
- if (className) codeElement.classList.add(className);
-
- }
-
- // Highlighting
- hljs.highlightElement(code);
-
- await Promise.resolve().then();
-
- // Adding line numbers
- const html = code.innerHTML || '';
- const htmlSplit = html ? html.split('\n') : [];
- const totalLines = htmlSplit.length;
-
- if (totalLines >= 1) {
- code.classList.add('hljs-add-marker-width');
- const len = `${totalLines}`.length * 0.5;
- code.style.setProperty('--hljs-marker-width', `${len}em`);
- code.innerHTML = htmlSplit.map((n, i) => `<span class="marker marker-fixed-width">${i + 1}</span>${n}`).join('\n');
- } else {
- code.classList.remove('hljs-add-marker-width');
- code.style.setProperty('--hljs-marker-width', '');
- }
-
- await Promise.resolve().then();
- parentNode.insertBefore(code, nextNode);
-
- }
- documentReady.then(() => {
-
- if (!location.pathname.endsWith('/code')) {
- byPass = false;
- }
-
- // Code highlighting
- const promises = [...document.querySelectorAll('.code-container pre.lang-js, .code-container pre.lang-css')].map(prepareCodeAreaAsync)
- Promise.all(promises).then(() => {
- setTimeout(() => {
- document.documentElement.setAttribute('dkkfv', '');
- }, 1);
- })
-
- });
-
-
- })();
-