UNPKG

monaco-editor

Version:
231 lines (230 loc) 11 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { CharacterClassifier } from '../core/characterClassifier.js'; import { Uint8Matrix } from '../core/uint.js'; var StateMachine = /** @class */ (function () { function StateMachine(edges) { var maxCharCode = 0; var maxState = 0 /* Invalid */; for (var i = 0, len = edges.length; i < len; i++) { var _a = edges[i], from = _a[0], chCode = _a[1], to = _a[2]; if (chCode > maxCharCode) { maxCharCode = chCode; } if (from > maxState) { maxState = from; } if (to > maxState) { maxState = to; } } maxCharCode++; maxState++; var states = new Uint8Matrix(maxState, maxCharCode, 0 /* Invalid */); for (var i = 0, len = edges.length; i < len; i++) { var _b = edges[i], from = _b[0], chCode = _b[1], to = _b[2]; states.set(from, chCode, to); } this._states = states; this._maxCharCode = maxCharCode; } StateMachine.prototype.nextState = function (currentState, chCode) { if (chCode < 0 || chCode >= this._maxCharCode) { return 0 /* Invalid */; } return this._states.get(currentState, chCode); }; return StateMachine; }()); // State machine for http:// or https:// or file:// var _stateMachine = null; function getStateMachine() { if (_stateMachine === null) { _stateMachine = new StateMachine([ [1 /* Start */, 104 /* h */, 2 /* H */], [1 /* Start */, 72 /* H */, 2 /* H */], [1 /* Start */, 102 /* f */, 6 /* F */], [1 /* Start */, 70 /* F */, 6 /* F */], [2 /* H */, 116 /* t */, 3 /* HT */], [2 /* H */, 84 /* T */, 3 /* HT */], [3 /* HT */, 116 /* t */, 4 /* HTT */], [3 /* HT */, 84 /* T */, 4 /* HTT */], [4 /* HTT */, 112 /* p */, 5 /* HTTP */], [4 /* HTT */, 80 /* P */, 5 /* HTTP */], [5 /* HTTP */, 115 /* s */, 9 /* BeforeColon */], [5 /* HTTP */, 83 /* S */, 9 /* BeforeColon */], [5 /* HTTP */, 58 /* Colon */, 10 /* AfterColon */], [6 /* F */, 105 /* i */, 7 /* FI */], [6 /* F */, 73 /* I */, 7 /* FI */], [7 /* FI */, 108 /* l */, 8 /* FIL */], [7 /* FI */, 76 /* L */, 8 /* FIL */], [8 /* FIL */, 101 /* e */, 9 /* BeforeColon */], [8 /* FIL */, 69 /* E */, 9 /* BeforeColon */], [9 /* BeforeColon */, 58 /* Colon */, 10 /* AfterColon */], [10 /* AfterColon */, 47 /* Slash */, 11 /* AlmostThere */], [11 /* AlmostThere */, 47 /* Slash */, 12 /* End */], ]); } return _stateMachine; } var _classifier = null; function getClassifier() { if (_classifier === null) { _classifier = new CharacterClassifier(0 /* None */); var FORCE_TERMINATION_CHARACTERS = ' \t<>\'\"、。。、,.:;?!@#$%&*‘“〈《「『【〔([{「」}])〕】』」》〉”’`~…'; for (var i = 0; i < FORCE_TERMINATION_CHARACTERS.length; i++) { _classifier.set(FORCE_TERMINATION_CHARACTERS.charCodeAt(i), 1 /* ForceTermination */); } var CANNOT_END_WITH_CHARACTERS = '.,;'; for (var i = 0; i < CANNOT_END_WITH_CHARACTERS.length; i++) { _classifier.set(CANNOT_END_WITH_CHARACTERS.charCodeAt(i), 2 /* CannotEndIn */); } } return _classifier; } var LinkComputer = /** @class */ (function () { function LinkComputer() { } LinkComputer._createLink = function (classifier, line, lineNumber, linkBeginIndex, linkEndIndex) { // Do not allow to end link in certain characters... var lastIncludedCharIndex = linkEndIndex - 1; do { var chCode = line.charCodeAt(lastIncludedCharIndex); var chClass = classifier.get(chCode); if (chClass !== 2 /* CannotEndIn */) { break; } lastIncludedCharIndex--; } while (lastIncludedCharIndex > linkBeginIndex); // Handle links enclosed in parens, square brackets and curlys. if (linkBeginIndex > 0) { var charCodeBeforeLink = line.charCodeAt(linkBeginIndex - 1); var lastCharCodeInLink = line.charCodeAt(lastIncludedCharIndex); if ((charCodeBeforeLink === 40 /* OpenParen */ && lastCharCodeInLink === 41 /* CloseParen */) || (charCodeBeforeLink === 91 /* OpenSquareBracket */ && lastCharCodeInLink === 93 /* CloseSquareBracket */) || (charCodeBeforeLink === 123 /* OpenCurlyBrace */ && lastCharCodeInLink === 125 /* CloseCurlyBrace */)) { // Do not end in ) if ( is before the link start // Do not end in ] if [ is before the link start // Do not end in } if { is before the link start lastIncludedCharIndex--; } } return { range: { startLineNumber: lineNumber, startColumn: linkBeginIndex + 1, endLineNumber: lineNumber, endColumn: lastIncludedCharIndex + 2 }, url: line.substring(linkBeginIndex, lastIncludedCharIndex + 1) }; }; LinkComputer.computeLinks = function (model) { var stateMachine = getStateMachine(); var classifier = getClassifier(); var result = []; for (var i = 1, lineCount = model.getLineCount(); i <= lineCount; i++) { var line = model.getLineContent(i); var len = line.length; var j = 0; var linkBeginIndex = 0; var linkBeginChCode = 0; var state = 1 /* Start */; var hasOpenParens = false; var hasOpenSquareBracket = false; var hasOpenCurlyBracket = false; while (j < len) { var resetStateMachine = false; var chCode = line.charCodeAt(j); if (state === 13 /* Accept */) { var chClass = void 0; switch (chCode) { case 40 /* OpenParen */: hasOpenParens = true; chClass = 0 /* None */; break; case 41 /* CloseParen */: chClass = (hasOpenParens ? 0 /* None */ : 1 /* ForceTermination */); break; case 91 /* OpenSquareBracket */: hasOpenSquareBracket = true; chClass = 0 /* None */; break; case 93 /* CloseSquareBracket */: chClass = (hasOpenSquareBracket ? 0 /* None */ : 1 /* ForceTermination */); break; case 123 /* OpenCurlyBrace */: hasOpenCurlyBracket = true; chClass = 0 /* None */; break; case 125 /* CloseCurlyBrace */: chClass = (hasOpenCurlyBracket ? 0 /* None */ : 1 /* ForceTermination */); break; /* The following three rules make it that ' or " or ` are allowed inside links if the link began with a different one */ case 39 /* SingleQuote */: chClass = (linkBeginChCode === 34 /* DoubleQuote */ || linkBeginChCode === 96 /* BackTick */) ? 0 /* None */ : 1 /* ForceTermination */; break; case 34 /* DoubleQuote */: chClass = (linkBeginChCode === 39 /* SingleQuote */ || linkBeginChCode === 96 /* BackTick */) ? 0 /* None */ : 1 /* ForceTermination */; break; case 96 /* BackTick */: chClass = (linkBeginChCode === 39 /* SingleQuote */ || linkBeginChCode === 34 /* DoubleQuote */) ? 0 /* None */ : 1 /* ForceTermination */; break; default: chClass = classifier.get(chCode); } // Check if character terminates link if (chClass === 1 /* ForceTermination */) { result.push(LinkComputer._createLink(classifier, line, i, linkBeginIndex, j)); resetStateMachine = true; } } else if (state === 12 /* End */) { var chClass = classifier.get(chCode); // Check if character terminates link if (chClass === 1 /* ForceTermination */) { resetStateMachine = true; } else { state = 13 /* Accept */; } } else { state = stateMachine.nextState(state, chCode); if (state === 0 /* Invalid */) { resetStateMachine = true; } } if (resetStateMachine) { state = 1 /* Start */; hasOpenParens = false; hasOpenSquareBracket = false; hasOpenCurlyBracket = false; // Record where the link started linkBeginIndex = j + 1; linkBeginChCode = chCode; } j++; } if (state === 13 /* Accept */) { result.push(LinkComputer._createLink(classifier, line, i, linkBeginIndex, len)); } } return result; }; return LinkComputer; }()); /** * Returns an array of all links contains in the provided * document. *Note* that this operation is computational * expensive and should not run in the UI thread. */ export function computeLinks(model) { if (!model || typeof model.getLineCount !== 'function' || typeof model.getLineContent !== 'function') { // Unknown caller! return []; } return LinkComputer.computeLinks(model); }