Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name forth-highlighter.js
- // @namespace fforum.winglion.ru
- // @description highlights forth code
- // @include http://fforum.winglion.ru/*
- // @require https://code.jquery.com/jquery-3.4.1.slim.min.js
- // @version 1
- // @grant none
- // ==/UserScript==
- (function($) {
- 'use strict';
- function highlight (text) {
- if (!text) return "";
- const all_source = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); // внимание!!! в исходнике заэскейплены спецсимволы HTML
- let rest_all_source = all_source;
- let source;
- let rest_source = '';
- let latest;
- let state = false;
- let dstack = [];
- let output = [];
- let currenttags; // стиль, который наследует слово
- let current = []; // сюда компилируется слово
- function compile(word) {
- if (word in words) {
- const t = words[word][words[word].length - 1].tags;
- if (t && !currenttags) currenttags = t;
- current.push('this["' + word.replace(/['"\\]/g, '\\$&') + '"][' + String(words[word].length - 1) + ']();');
- }
- }
- function notfound (word) {
- if (word.match(/^(0x)?[0-9a-f]+$/i)) return number;
- return ['', ''];
- }
- const words = {
- parse: [function() {
- let c = dstack[dstack.length - 1];
- c = c === ' ' ? '\\s' : c.replace(/[^\w\s]/g, '\\$&');
- const regex = new RegExp('^[^' + c + ']*', 'g');
- const match = regex.exec(rest_source);
- dstack.push(match[0]);
- output.push(rest_source.slice(0, regex.lastIndex + 1));
- rest_source = rest_source.slice(regex.lastIndex + 1, rest_source.length);
- }],
- word: [function() {
- let c = dstack[dstack.length - 1];
- c = c == ' ' ? '\\s' : s.replace(/[^\w\s]/g, '\\$&');
- const regex = new RegExp('^[' + c + ']*', 'g');
- const match = regex.exec(rest_source);
- rest_source = rest_source.slice(regex.lastIndex, rest_source.length);
- output.push(match[0]);
- words.parse[0]();
- }],
- name: [function() {
- dstack.push(' ');
- words.word[0]();
- }],
- interpret: [function() {
- do {
- words.name[0]();
- const word = dstack.pop().toLowerCase();
- let xt = words[word] || false;
- xt = xt && xt[xt.length - 1];
- const tags = xt.tags || (!(word in words) && notfound(word));
- const t = output.pop();
- output.push(tags[0]);
- output.push(t);
- if (xt) {
- if (xt.immediate || !state) {
- xt();
- } else {
- compile(word);
- }
- }
- output.push(tags[1]);
- } while (rest_source);
- }],
- refill: [function() {
- output.push(rest_source);
- source = rest_source = '';
- if (!rest_all_source) {
- return;
- }
- const line = /^[^\n]*\n?/g;
- const match = line.exec(rest_all_source);
- source = rest_source = match[0];
- rest_all_source = rest_all_source.slice(line.lastIndex, rest_all_source.length);
- }],
- ':': [function() {
- words.name[0]();
- latest = dstack.pop().toLowerCase();
- current = [];
- state = true;
- }],
- ';': [function() {
- if (!words[latest]) words[latest] = [];
- words[latest].push(new Function(current.join('')).bind(words));
- state = false;
- words[latest][words[latest].length - 1].tags = currenttags;
- currenttags = undefined;
- current = [];
- }],
- '[': [function() {
- state = false;
- }],
- ']': [function() {
- state = true;
- }],
- bl: [function() {
- dstack.push(' ')
- }],
- immediate: [function() {
- words[latest][words[latest].length - 1].immediate = true;
- }],
- '(': [function() {
- dstack.push(')');
- words.parse[0]();
- }],
- '\\': [function() {
- words.refill[0]();
- }],
- 'if': [function(){}],
- 'else': [function(){}],
- then: [function(){}],
- begin: [function(){}],
- 'while': [function(){}],
- repeat: [function(){}],
- until: [function(){}],
- again: [function(){}],
- 'do': [function(){}],
- loop: [function(){}],
- '?do': [function(){}],
- create: [function() {
- words.name[0]();
- latest = dstack.pop();
- if (!words[latest]) words[latest] = [];
- words[latest].push(function(){});
- }],
- 'does>': [function(){}],
- postpone: [function() {
- words.name[0]();
- compile(dstack.pop().toLowerCase());
- }],
- 'char': [function() {
- words.name[0]();
- dstack.push(dstack.pop()[0]);
- }],
- '[char]': [function() {
- words.name[0]();
- current.push('this.push[0]("' + dstack.pop()[0].replace(/[\\"]/g, "\\$&") + '");');
- }],
- push: [function(x) {
- dstack.push(x);
- }],
- };
- words[';'][0].immediate = true;
- words['('][0].immediate = true;
- words['\\'][0].immediate = true;
- words['['][0].immediate = true;
- words['does>'][0].immediate = true;
- words['if'][0].immediate = true;
- words['else'][0].immediate = true;
- words['then'][0].immediate = true;
- words.begin[0].immediate = true;
- words['while'][0].immediate = true;
- words.repeat[0].immediate = true;
- words.until[0].immediate = true;
- words.again[0].immediate = true;
- words['do'][0].immediate = true;
- words.loop[0].immediate = true;
- words['?do'][0].immediate = true;
- words.postpone[0].immediate = true;
- words['[char]'][0].immediate = true;
- // в св-ве tags хранится пара тегов: начало и конец
- const literal = ['<span style="color: green;">', '</span>'];
- const define = ['<span style="color: darkorange;">', '</span>'];
- const comment = ['<span style="color: gray;">', '</span>'];
- const control = ['<span style="color: blue;">', '</span>'];
- const number = ['<span style="color: red;">', '</span>'];
- words.parse[0].tags = literal;
- words.word[0].tags = literal;
- words.name[0].tags = literal;
- words[':'][0].tags = define;
- words[';'][0].tags = define;
- words.create[0].tags = define;
- words['does>'][0].tags = define;
- words['('][0].tags = comment;
- words['\\'][0].tags = comment;
- words['['][0].tags = ['<i>', ''];
- words[']'][0].tags = ['', '</i>'];
- words['if'][0].tags = control;
- words['else'][0].tags = control;
- words['then'][0].tags = control;
- words.begin[0].tags = control;
- words['while'][0].tags = control;
- words.repeat[0].tags = control;
- words.until[0].tags = control;
- words.again[0].tags = control;
- words['do'][0].tags = control;
- words.loop[0].tags = control;
- words['?do'][0].tags = control;
- words.postpone[0].tags = literal;
- words['[char]'][0].tags = literal;
- function e(s) {
- source = rest_source = s;
- words.interpret[0]();
- output = [];
- dstack = [];
- }
- e(": ' name ; : ['] ' ; immediate");
- e(': " [char] " parse ; immediate');
- words['."'] = words['c"'] = words['s"'] = words['"'];
- e(': .( [char] ) parse ; immediate');
- e(': constant create ; : variable create ; : value create ; : vect create ; : ->vect create ; : defer create ; : vocabulary create ;');
- e(': case postpone if ; immediate : of postpone if ; immediate : endof postpone if ; immediate : endcase postpone if ; immediate : exit postpone if ; immediate');
- e(': code : ;');
- e(': end-code postpone ; ; immediate');
- function run () {
- do {
- words.refill[0]();
- words.interpret[0]();
- } while (rest_all_source);
- }
- try {
- run();
- } catch (e) {
- console.log(e);
- }
- return output.join('').replace(/\n/g, '<br>');
- }
- $('.codecontent').each(function(){
- const code = $(this)[0];
- code.setAttribute('style', 'color: black; font-size: 12pt; font-style: bold;');
- const src = code.innerText;
- try {
- code.innerHTML = highlight(src);
- } catch (e) {
- console.log(e);
- }
- try {
- $(code).append('<div><button>оригинал</button></div>');
- const t = $(code).children('div');
- t.children('button').bind('click', () => t.children('div').css('display', 'block'))
- t.append('<div></div>');
- t.children('div').css('display', 'none')[0].innerText = src;
- } catch (e) {
- console.log(e);
- }
- });
- })($);
Add Comment
Please, Sign In to add comment