basant307/AI_Governance_Project
048
1'use strict';2 3var view = require('@codemirror/view');4var state = require('@codemirror/state');5var elt = require('crelt');6 7class SelectedDiagnostic {8 constructor(from, to, diagnostic) {9 this.from = from;10 this.to = to;11 this.diagnostic = diagnostic;12 }13}14class LintState {15 constructor(diagnostics, panel, selected) {16 this.diagnostics = diagnostics;17 this.panel = panel;18 this.selected = selected;19 }20 static init(diagnostics, panel, state$1) {21 // Filter the list of diagnostics for which to create markers22 let diagnosticFilter = state$1.facet(lintConfig).markerFilter;23 if (diagnosticFilter)24 diagnostics = diagnosticFilter(diagnostics, state$1);25 let sorted = diagnostics.slice().sort((a, b) => a.from - b.from || a.to - b.to);26 let deco = new state.RangeSetBuilder(), active = [], pos = 0;27 let scan = state$1.doc.iter(), scanPos = 0, docLen = state$1.doc.length;28 for (let i = 0;;) {29 let next = i == sorted.length ? null : sorted[i];30 if (!next && !active.length)31 break;32 let from, to;33 if (active.length) {34 from = pos;35 to = active.reduce((p, d) => Math.min(p, d.to), next && next.from > from ? next.from : 1e8);36 }37 else {38 from = next.from;39 if (from > docLen)40 break;41 to = next.to;42 active.push(next);43 i++;44 }45 while (i < sorted.length) {46 let next = sorted[i];47 if (next.from == from && (next.to > next.from || next.to == from)) {48 active.push(next);49 i++;50 to = Math.min(next.to, to);51 }52 else {53 to = Math.min(next.from, to);54 break;55 }56 }57 to = Math.min(to, docLen);58 let widget = false;59 if (active.some(d => d.from == from && (d.to == to || to == docLen))) {60 widget = from == to;61 if (!widget && to - from < 10) {62 let behind = from - (scanPos + scan.value.length);63 if (behind > 0) {64 scan.next(behind);65 scanPos = from;66 }67 for (let check = from;;) {68 if (check >= to) {69 widget = true;70 break;71 }72 if (!scan.lineBreak && scanPos + scan.value.length > check)73 break;74 check = scanPos + scan.value.length;75 scanPos += scan.value.length;76 scan.next();77 }78 }79 }80 let sev = maxSeverity(active);81 if (widget) {82 deco.add(from, from, view.Decoration.widget({83 widget: new DiagnosticWidget(sev),84 diagnostics: active.slice()85 }));86 }87 else {88 let markClass = active.reduce((c, d) => d.markClass ? c + " " + d.markClass : c, "");89 deco.add(from, to, view.Decoration.mark({90 class: "cm-lintRange cm-lintRange-" + sev + markClass,91 diagnostics: active.slice(),92 inclusiveEnd: active.some(a => a.to > to)93 }));94 }95 pos = to;96 if (pos == docLen)97 break;98 for (let i = 0; i < active.length; i++)99 if (active[i].to <= pos)100 active.splice(i--, 1);101 }102 let set = deco.finish();103 return new LintState(set, panel, findDiagnostic(set));104 }105}106function findDiagnostic(diagnostics, diagnostic = null, after = 0) {107 let found = null;108 diagnostics.between(after, 1e9, (from, to, { spec }) => {109 if (diagnostic && spec.diagnostics.indexOf(diagnostic) < 0)110 return;111 if (!found)112 found = new SelectedDiagnostic(from, to, diagnostic || spec.diagnostics[0]);113 else if (spec.diagnostics.indexOf(found.diagnostic) < 0)114 return false;115 else116 found = new SelectedDiagnostic(found.from, to, found.diagnostic);117 });118 return found;119}120function hideTooltip(tr, tooltip) {121 let from = tooltip.pos, to = tooltip.end || from;122 let result = tr.state.facet(lintConfig).hideOn(tr, from, to);123 if (result != null)124 return result;125 let line = tr.startState.doc.lineAt(tooltip.pos);126 return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(line.from, Math.max(line.to, to)));127}128function maybeEnableLint(state$1, effects) {129 return state$1.field(lintState, false) ? effects : effects.concat(state.StateEffect.appendConfig.of(lintExtensions));130}131/**132Returns a transaction spec which updates the current set of133diagnostics, and enables the lint extension if if wasn't already134active.135*/136function setDiagnostics(state, diagnostics) {137 return {138 effects: maybeEnableLint(state, [setDiagnosticsEffect.of(diagnostics)])139 };140}141/**142The state effect that updates the set of active diagnostics. Can143be useful when writing an extension that needs to track these.144*/145const setDiagnosticsEffect = state.StateEffect.define();146const togglePanel = state.StateEffect.define();147const movePanelSelection = state.StateEffect.define();148const lintState = state.StateField.define({149 create() {150 return new LintState(view.Decoration.none, null, null);151 },152 update(value, tr) {153 if (tr.docChanged && value.diagnostics.size) {154 let mapped = value.diagnostics.map(tr.changes), selected = null, panel = value.panel;155 if (value.selected) {156 let selPos = tr.changes.mapPos(value.selected.from, 1);157 selected = findDiagnostic(mapped, value.selected.diagnostic, selPos) || findDiagnostic(mapped, null, selPos);158 }159 if (!mapped.size && panel && tr.state.facet(lintConfig).autoPanel)160 panel = null;161 value = new LintState(mapped, panel, selected);162 }163 for (let effect of tr.effects) {164 if (effect.is(setDiagnosticsEffect)) {165 let panel = !tr.state.facet(lintConfig).autoPanel ? value.panel : effect.value.length ? LintPanel.open : null;166 value = LintState.init(effect.value, panel, tr.state);167 }168 else if (effect.is(togglePanel)) {169 value = new LintState(value.diagnostics, effect.value ? LintPanel.open : null, value.selected);170 }171 else if (effect.is(movePanelSelection)) {172 value = new LintState(value.diagnostics, value.panel, effect.value);173 }174 }175 return value;176 },177 provide: f => [view.showPanel.from(f, val => val.panel),178 view.EditorView.decorations.from(f, s => s.diagnostics)]179});180/**181Returns the number of active lint diagnostics in the given state.182*/183function diagnosticCount(state) {184 let lint = state.field(lintState, false);185 return lint ? lint.diagnostics.size : 0;186}187const activeMark = view.Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });188function lintTooltip(view, pos, side) {189 let { diagnostics } = view.state.field(lintState);190 let found, start = -1, end = -1;191 diagnostics.between(pos - (side < 0 ? 1 : 0), pos + (side > 0 ? 1 : 0), (from, to, { spec }) => {192 if (pos >= from && pos <= to &&193 (from == to || ((pos > from || side > 0) && (pos < to || side < 0)))) {194 found = spec.diagnostics;195 start = from;196 end = to;197 return false;198 }199 });200 let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;201 if (found && diagnosticFilter)202 found = diagnosticFilter(found, view.state);203 if (!found)204 return null;205 return {206 pos: start,207 end: end,208 above: true,209 create() {210 return { dom: diagnosticsTooltip(view, found) };211 }212 };213}214function diagnosticsTooltip(view, diagnostics) {215 return elt("ul", { class: "cm-tooltip-lint" }, diagnostics.map(d => renderDiagnostic(view, d, false)));216}217/**218Command to open and focus the lint panel.219*/220const openLintPanel = (view$1) => {221 let field = view$1.state.field(lintState, false);222 if (!field || !field.panel)223 view$1.dispatch({ effects: maybeEnableLint(view$1.state, [togglePanel.of(true)]) });224 let panel = view.getPanel(view$1, LintPanel.open);225 if (panel)226 panel.dom.querySelector(".cm-panel-lint ul").focus();227 return true;228};229/**230Command to close the lint panel, when open.231*/232const closeLintPanel = (view) => {233 let field = view.state.field(lintState, false);234 if (!field || !field.panel)235 return false;236 view.dispatch({ effects: togglePanel.of(false) });237 return true;238};239/**240Move the selection to the next diagnostic.241*/242const nextDiagnostic = (view$1) => {243 let field = view$1.state.field(lintState, false);244 if (!field)245 return false;246 let sel = view$1.state.selection.main, next = findDiagnostic(field.diagnostics, null, sel.to + 1);247 if (!next) {248 next = findDiagnostic(field.diagnostics, null, 0);249 if (!next || next.from == sel.from && next.to == sel.to)250 return false;251 }252 view$1.dispatch({ selection: { anchor: next.from, head: next.to }, scrollIntoView: true });253 view.activateHover(view$1, next.from, 1, {254 tooltip: lintHover,255 until: tr => tr.docChanged || tr.newSelection.main.head < next.from || tr.newSelection.main.head > next.to256 });257 return true;258};259/**260Move the selection to the previous diagnostic.261*/262const previousDiagnostic = (view$1) => {263 var _a;264 let { state } = view$1, field = state.field(lintState, false);265 if (!field)266 return false;267 let sel = state.selection.main;268 let prevFrom, prevTo, lastFrom, lastTo;269 field.diagnostics.between(0, state.doc.length, (from, to) => {270 if (to < sel.to && (prevFrom == null || prevFrom < from)) {271 prevFrom = from;272 prevTo = to;273 }274 if (lastFrom == null || from > lastFrom) {275 lastFrom = from;276 lastTo = to;277 }278 });279 if (lastFrom == null || prevFrom == null && lastFrom == sel.from)280 return false;281 let from = prevFrom !== null && prevFrom !== void 0 ? prevFrom : lastFrom, to = (_a = prevTo !== null && prevTo !== void 0 ? prevTo : lastTo) !== null && _a !== void 0 ? _a : from;282 view$1.dispatch({ selection: { anchor: from, head: to }, scrollIntoView: true });283 view.activateHover(view$1, from, 1, {284 tooltip: lintHover,285 until: tr => tr.docChanged || tr.newSelection.main.head < from || tr.newSelection.main.head > to286 });287 return true;288};289/**290A set of default key bindings for the lint functionality.291 292- Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel)293- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)294*/295const lintKeymap = [296 { key: "Mod-Shift-m", run: openLintPanel, preventDefault: true },297 { key: "F8", run: nextDiagnostic }298];299const lintPlugin = view.ViewPlugin.fromClass(class {300 constructor(view) {301 this.view = view;302 this.timeout = -1;303 this.set = true;304 let { delay } = view.state.facet(lintConfig);305 this.lintTime = Date.now() + delay;306 this.run = this.run.bind(this);307 this.timeout = setTimeout(this.run, delay);308 }309 run() {310 clearTimeout(this.timeout);311 let now = Date.now();312 if (now < this.lintTime - 10) {313 this.timeout = setTimeout(this.run, this.lintTime - now);314 }315 else {316 this.set = false;317 let { state } = this.view, { sources } = state.facet(lintConfig);318 if (sources.length)319 batchResults(sources.map(s => Promise.resolve(s(this.view))), annotations => {320 if (this.view.state.doc == state.doc)321 this.view.dispatch(setDiagnostics(this.view.state, annotations.reduce((a, b) => a.concat(b))));322 }, error => { view.logException(this.view.state, error); });323 }324 }325 update(update) {326 let config = update.state.facet(lintConfig);327 if (update.docChanged || config != update.startState.facet(lintConfig) ||328 config.needsRefresh && config.needsRefresh(update)) {329 this.lintTime = Date.now() + config.delay;330 if (!this.set) {331 this.set = true;332 this.timeout = setTimeout(this.run, config.delay);333 }334 }335 }336 force() {337 if (this.set) {338 this.lintTime = Date.now();339 this.run();340 }341 }342 destroy() {343 clearTimeout(this.timeout);344 }345});346function batchResults(promises, sink, error) {347 let collected = [], timeout = -1;348 for (let p of promises)349 p.then(value => {350 collected.push(value);351 clearTimeout(timeout);352 if (collected.length == promises.length)353 sink(collected);354 else355 timeout = setTimeout(() => sink(collected), 200);356 }, error);357}358const lintConfig = state.Facet.define({359 combine(input) {360 return {361 sources: input.map(i => i.source).filter(x => x != null),362 ...state.combineConfig(input.map(i => i.config), {363 delay: 750,364 markerFilter: null,365 tooltipFilter: null,366 needsRefresh: null,367 hideOn: () => null,368 }, {369 delay: Math.max,370 markerFilter: combineFilter,371 tooltipFilter: combineFilter,372 needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u),373 hideOn: (a, b) => !a ? b : !b ? a : (t, x, y) => a(t, x, y) || b(t, x, y),374 autoPanel: (a, b) => a || b375 })376 };377 }378});379function combineFilter(a, b) {380 return !a ? b : !b ? a : (d, s) => b(a(d, s), s);381}382/**383Given a diagnostic source, this function returns an extension that384enables linting with that source. It will be called whenever the385editor is idle (after its content changed).386 387Note that settings given here will apply to all linters active in388the editor. If `null` is given as source, this only configures the389lint extension.390*/391function linter(source, config = {}) {392 return [393 lintConfig.of({ source, config }),394 lintPlugin,395 lintExtensions396 ];397}398/**399Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the400editor is idle to run right away.401*/402function forceLinting(view) {403 let plugin = view.plugin(lintPlugin);404 if (plugin)405 plugin.force();406}407function assignKeys(actions) {408 let assigned = [];409 if (actions)410 actions: for (let { name } of actions) {411 for (let i = 0; i < name.length; i++) {412 let ch = name[i];413 if (/[a-zA-Z]/.test(ch) && !assigned.some(c => c.toLowerCase() == ch.toLowerCase())) {414 assigned.push(ch);415 continue actions;416 }417 }418 assigned.push("");419 }420 return assigned;421}422function renderDiagnostic(view, diagnostic, inPanel) {423 var _a;424 let keys = inPanel ? assignKeys(diagnostic.actions) : [];425 return elt("li", { class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity }, elt("span", { class: "cm-diagnosticText" }, diagnostic.renderMessage ? diagnostic.renderMessage(view) : diagnostic.message), (_a = diagnostic.actions) === null || _a === void 0 ? void 0 : _a.map((action, i) => {426 let fired = false, click = (e) => {427 e.preventDefault();428 if (fired)429 return;430 fired = true;431 let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic);432 if (found)433 action.apply(view, found.from, found.to);434 };435 let { name } = action, keyIndex = keys[i] ? name.indexOf(keys[i]) : -1;436 let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex),437 elt("u", name.slice(keyIndex, keyIndex + 1)),438 name.slice(keyIndex + 1)];439 let markClass = action.markClass ? " " + action.markClass : "";440 return elt("button", {441 type: "button",442 class: "cm-diagnosticAction" + markClass,443 onclick: click,444 onmousedown: click,445 "aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.`446 }, nameElt);447 }), diagnostic.source && elt("div", { class: "cm-diagnosticSource" }, diagnostic.source));448}449class DiagnosticWidget extends view.WidgetType {450 constructor(sev) {451 super();452 this.sev = sev;453 }454 eq(other) { return other.sev == this.sev; }455 toDOM() {456 return elt("span", { class: "cm-lintPoint cm-lintPoint-" + this.sev });457 }458}459class PanelItem {460 constructor(view, diagnostic) {461 this.diagnostic = diagnostic;462 this.id = "item_" + Math.floor(Math.random() * 0xffffffff).toString(16);463 this.dom = renderDiagnostic(view, diagnostic, true);464 this.dom.id = this.id;465 this.dom.setAttribute("role", "option");466 }467}468class LintPanel {469 constructor(view) {470 this.view = view;471 this.items = [];472 let onkeydown = (event) => {473 if (event.ctrlKey || event.altKey || event.metaKey)474 return;475 if (event.keyCode == 27) { // Escape476 closeLintPanel(this.view);477 this.view.focus();478 }479 else if (event.keyCode == 38 || event.keyCode == 33) { // ArrowUp, PageUp480 this.moveSelection((this.selectedIndex - 1 + this.items.length) % this.items.length);481 }482 else if (event.keyCode == 40 || event.keyCode == 34) { // ArrowDown, PageDown483 this.moveSelection((this.selectedIndex + 1) % this.items.length);484 }485 else if (event.keyCode == 36) { // Home486 this.moveSelection(0);487 }488 else if (event.keyCode == 35) { // End489 this.moveSelection(this.items.length - 1);490 }491 else if (event.keyCode == 13) { // Enter492 this.view.focus();493 }494 else if (event.keyCode >= 65 && event.keyCode <= 90 && this.selectedIndex >= 0) { // A-Z495 let { diagnostic } = this.items[this.selectedIndex], keys = assignKeys(diagnostic.actions);496 for (let i = 0; i < keys.length; i++)497 if (keys[i].toUpperCase().charCodeAt(0) == event.keyCode) {498 let found = findDiagnostic(this.view.state.field(lintState).diagnostics, diagnostic);499 if (found)500 diagnostic.actions[i].apply(view, found.from, found.to);501 }502 }503 else {504 return;505 }506 event.preventDefault();507 };508 let onclick = (event) => {509 for (let i = 0; i < this.items.length; i++) {510 if (this.items[i].dom.contains(event.target))511 this.moveSelection(i);512 }513 };514 this.list = elt("ul", {515 tabIndex: 0,516 role: "listbox",517 "aria-label": this.view.state.phrase("Diagnostics"),518 onkeydown,519 onclick520 });521 this.dom = elt("div", { class: "cm-panel-lint" }, this.list, elt("button", {522 type: "button",523 name: "close",524 "aria-label": this.view.state.phrase("close"),525 onclick: () => closeLintPanel(this.view)526 }, "×"));527 this.update();528 }529 get selectedIndex() {530 let selected = this.view.state.field(lintState).selected;531 if (!selected)532 return -1;533 for (let i = 0; i < this.items.length; i++)534 if (this.items[i].diagnostic == selected.diagnostic)535 return i;536 return -1;537 }538 update() {539 let { diagnostics, selected } = this.view.state.field(lintState);540 let i = 0, needsSync = false, newSelectedItem = null;541 let seen = new Set();542 diagnostics.between(0, this.view.state.doc.length, (_start, _end, { spec }) => {543 for (let diagnostic of spec.diagnostics) {544 if (seen.has(diagnostic))545 continue;546 seen.add(diagnostic);547 let found = -1, item;548 for (let j = i; j < this.items.length; j++)549 if (this.items[j].diagnostic == diagnostic) {550 found = j;551 break;552 }553 if (found < 0) {554 item = new PanelItem(this.view, diagnostic);555 this.items.splice(i, 0, item);556 needsSync = true;557 }558 else {559 item = this.items[found];560 if (found > i) {561 this.items.splice(i, found - i);562 needsSync = true;563 }564 }565 if (selected && item.diagnostic == selected.diagnostic) {566 if (!item.dom.hasAttribute("aria-selected")) {567 item.dom.setAttribute("aria-selected", "true");568 newSelectedItem = item;569 }570 }571 else if (item.dom.hasAttribute("aria-selected")) {572 item.dom.removeAttribute("aria-selected");573 }574 i++;575 }576 });577 while (i < this.items.length && !(this.items.length == 1 && this.items[0].diagnostic.from < 0)) {578 needsSync = true;579 this.items.pop();580 }581 if (this.items.length == 0) {582 this.items.push(new PanelItem(this.view, {583 from: -1, to: -1,584 severity: "info",585 message: this.view.state.phrase("No diagnostics")586 }));587 needsSync = true;588 }589 if (newSelectedItem) {590 this.list.setAttribute("aria-activedescendant", newSelectedItem.id);591 this.view.requestMeasure({592 key: this,593 read: () => ({ sel: newSelectedItem.dom.getBoundingClientRect(), panel: this.list.getBoundingClientRect() }),594 write: ({ sel, panel }) => {595 let scaleY = panel.height / this.list.offsetHeight;596 if (sel.top < panel.top)597 this.list.scrollTop -= (panel.top - sel.top) / scaleY;598 else if (sel.bottom > panel.bottom)599 this.list.scrollTop += (sel.bottom - panel.bottom) / scaleY;600 }601 });602 }603 else if (this.selectedIndex < 0) {604 this.list.removeAttribute("aria-activedescendant");605 }606 if (needsSync)607 this.sync();608 }609 sync() {610 let domPos = this.list.firstChild;611 function rm() {612 let prev = domPos;613 domPos = prev.nextSibling;614 prev.remove();615 }616 for (let item of this.items) {617 if (item.dom.parentNode == this.list) {618 while (domPos != item.dom)619 rm();620 domPos = item.dom.nextSibling;621 }622 else {623 this.list.insertBefore(item.dom, domPos);624 }625 }626 while (domPos)627 rm();628 }629 moveSelection(selectedIndex) {630 if (this.selectedIndex < 0)631 return;632 let field = this.view.state.field(lintState);633 let selection = findDiagnostic(field.diagnostics, this.items[selectedIndex].diagnostic);634 if (!selection)635 return;636 this.view.dispatch({637 selection: { anchor: selection.from, head: selection.to },638 scrollIntoView: true,639 effects: movePanelSelection.of(selection)640 });641 }642 static open(view) { return new LintPanel(view); }643}644function svg(content, attrs = `viewBox="0 0 40 40"`) {645 return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" ${attrs}>${encodeURIComponent(content)}</svg>')`;646}647function underline(color) {648 return svg(`<path d="m0 2.5 l2 -1.5 l1 0 l2 1.5 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>`, `width="6" height="3"`);649}650const baseTheme = view.EditorView.baseTheme({651 ".cm-diagnostic": {652 padding: "3px 6px 3px 8px",653 marginLeft: "-1px",654 display: "block",655 whiteSpace: "pre-wrap"656 },657 ".cm-diagnostic-error": { borderLeft: "5px solid #d11" },658 ".cm-diagnostic-warning": { borderLeft: "5px solid orange" },659 ".cm-diagnostic-info": { borderLeft: "5px solid #999" },660 ".cm-diagnostic-hint": { borderLeft: "5px solid #66d" },661 ".cm-diagnosticAction": {662 font: "inherit",663 border: "none",664 padding: "2px 4px",665 backgroundColor: "#444",666 color: "white",667 borderRadius: "3px",668 marginLeft: "8px",669 cursor: "pointer"670 },671 ".cm-diagnosticSource": {672 fontSize: "70%",673 opacity: .7674 },675 ".cm-lintRange": {676 backgroundPosition: "left bottom",677 backgroundRepeat: "repeat-x",678 paddingBottom: "0.7px",679 },680 ".cm-lintRange-error": { backgroundImage: underline("#f11") },681 ".cm-lintRange-warning": { backgroundImage: underline("orange") },682 ".cm-lintRange-info": { backgroundImage: underline("#999") },683 ".cm-lintRange-hint": { backgroundImage: underline("#66d") },684 ".cm-lintRange-active": { backgroundColor: "#ffdd9980" },685 ".cm-tooltip-lint": {686 padding: 0,687 margin: 0688 },689 ".cm-lintPoint": {690 position: "relative",691 "&:after": {692 content: '""',693 position: "absolute",694 bottom: 0,695 left: "-2px",696 borderLeft: "3px solid transparent",697 borderRight: "3px solid transparent",698 borderBottom: "4px solid #d11"699 }700 },701 ".cm-lintPoint-warning": {702 "&:after": { borderBottomColor: "orange" }703 },704 ".cm-lintPoint-info": {705 "&:after": { borderBottomColor: "#999" }706 },707 ".cm-lintPoint-hint": {708 "&:after": { borderBottomColor: "#66d" }709 },710 ".cm-panel.cm-panel-lint": {711 position: "relative",712 "& ul": {713 maxHeight: "100px",714 overflowY: "auto",715 "& [aria-selected]": {716 backgroundColor: "#ddd",717 "& u": { textDecoration: "underline" }718 },719 "&:focus [aria-selected]": {720 background_fallback: "#bdf",721 backgroundColor: "Highlight",722 color_fallback: "white",723 color: "HighlightText"724 },725 "& u": { textDecoration: "none" },726 padding: 0,727 margin: 0728 },729 "& [name=close]": {730 position: "absolute",731 top: "0",732 right: "2px",733 background: "inherit",734 border: "none",735 font: "inherit",736 padding: 0,737 margin: 0738 }739 },740 "&dark .cm-lintRange-active": { backgroundColor: "#86714a80" },741 "&dark .cm-panel.cm-panel-lint ul": {742 "& [aria-selected]": {743 backgroundColor: "#2e343e",744 },745 }746});747function severityWeight(sev) {748 return sev == "error" ? 4 : sev == "warning" ? 3 : sev == "info" ? 2 : 1;749}750function maxSeverity(diagnostics) {751 let sev = "hint", weight = 1;752 for (let d of diagnostics) {753 let w = severityWeight(d.severity);754 if (w > weight) {755 weight = w;756 sev = d.severity;757 }758 }759 return sev;760}761class LintGutterMarker extends view.GutterMarker {762 constructor(diagnostics) {763 super();764 this.diagnostics = diagnostics;765 this.severity = maxSeverity(diagnostics);766 }767 toDOM(view) {768 let elt = document.createElement("div");769 elt.className = "cm-lint-marker cm-lint-marker-" + this.severity;770 let diagnostics = this.diagnostics;771 let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;772 if (diagnosticsFilter)773 diagnostics = diagnosticsFilter(diagnostics, view.state);774 if (diagnostics.length)775 elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);776 return elt;777 }778}779function trackHoverOn(view, marker) {780 let mousemove = (event) => {781 let rect = marker.getBoundingClientRect();782 if (event.clientX > rect.left - 10 /* Hover.Margin */ && event.clientX < rect.right + 10 /* Hover.Margin */ &&783 event.clientY > rect.top - 10 /* Hover.Margin */ && event.clientY < rect.bottom + 10 /* Hover.Margin */)784 return;785 for (let target = event.target; target; target = target.parentNode) {786 if (target.nodeType == 1 && target.classList.contains("cm-tooltip-lint"))787 return;788 }789 window.removeEventListener("mousemove", mousemove);790 if (view.state.field(lintGutterTooltip))791 view.dispatch({ effects: setLintGutterTooltip.of(null) });792 };793 window.addEventListener("mousemove", mousemove);794}795function gutterMarkerMouseOver(view, marker, diagnostics) {796 function hovered() {797 let line = view.elementAtHeight(marker.getBoundingClientRect().top + 5 - view.documentTop);798 const linePos = view.coordsAtPos(line.from);799 if (linePos) {800 view.dispatch({ effects: setLintGutterTooltip.of({801 pos: line.from,802 above: false,803 clip: false,804 create() {805 return {806 dom: diagnosticsTooltip(view, diagnostics),807 getCoords: () => marker.getBoundingClientRect()808 };809 }810 }) });811 }812 marker.onmouseout = marker.onmousemove = null;813 trackHoverOn(view, marker);814 }815 let { hoverTime } = view.state.facet(lintGutterConfig);816 let hoverTimeout = setTimeout(hovered, hoverTime);817 marker.onmouseout = () => {818 clearTimeout(hoverTimeout);819 marker.onmouseout = marker.onmousemove = null;820 };821 marker.onmousemove = () => {822 clearTimeout(hoverTimeout);823 hoverTimeout = setTimeout(hovered, hoverTime);824 };825}826function markersForDiagnostics(doc, diagnostics) {827 let byLine = Object.create(null);828 for (let diagnostic of diagnostics) {829 let line = doc.lineAt(diagnostic.from);830 (byLine[line.from] || (byLine[line.from] = [])).push(diagnostic);831 }832 let markers = [];833 for (let line in byLine) {834 markers.push(new LintGutterMarker(byLine[line]).range(+line));835 }836 return state.RangeSet.of(markers, true);837}838const lintGutterExtension = view.gutter({839 class: "cm-gutter-lint",840 markers: view => view.state.field(lintGutterMarkers),841 widgetMarker: (view, widget, block) => {842 let diagnostics = [];843 view.state.field(lintGutterMarkers).between(block.from, block.to, (from, to, value) => {844 if (from > block.from && from < block.to)845 diagnostics.push(...value.diagnostics);846 });847 return diagnostics.length ? new LintGutterMarker(diagnostics) : null;848 }849});850const lintGutterMarkers = state.StateField.define({851 create() {852 return state.RangeSet.empty;853 },854 update(markers, tr) {855 markers = markers.map(tr.changes);856 let diagnosticFilter = tr.state.facet(lintGutterConfig).markerFilter;857 for (let effect of tr.effects) {858 if (effect.is(setDiagnosticsEffect)) {859 let diagnostics = effect.value;860 if (diagnosticFilter)861 diagnostics = diagnosticFilter(diagnostics || [], tr.state);862 markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));863 }864 }865 return markers;866 }867});868const setLintGutterTooltip = state.StateEffect.define();869const lintGutterTooltip = state.StateField.define({870 create() { return null; },871 update(tooltip, tr) {872 if (tooltip && tr.docChanged)873 tooltip = hideTooltip(tr, tooltip) ? null : { ...tooltip, pos: tr.changes.mapPos(tooltip.pos) };874 return tr.effects.reduce((t, e) => e.is(setLintGutterTooltip) ? e.value : t, tooltip);875 },876 provide: field => view.showTooltip.from(field)877});878const lintGutterTheme = view.EditorView.baseTheme({879 ".cm-gutter-lint": {880 width: "1.4em",881 "& .cm-gutterElement": {882 padding: ".2em"883 }884 },885 ".cm-lint-marker": {886 width: "1em",887 height: "1em"888 },889 ".cm-lint-marker-info": {890 content: svg(`<path fill="#aaf" stroke="#77e" stroke-width="6" stroke-linejoin="round" d="M5 5L35 5L35 35L5 35Z"/>`)891 },892 ".cm-lint-marker-warning": {893 content: svg(`<path fill="#fe8" stroke="#fd7" stroke-width="6" stroke-linejoin="round" d="M20 6L37 35L3 35Z"/>`),894 },895 ".cm-lint-marker-error": {896 content: svg(`<circle cx="20" cy="20" r="15" fill="#f87" stroke="#f43" stroke-width="6"/>`)897 },898});899const lintHover = view.hoverTooltip(lintTooltip, { hideOn: hideTooltip });900const lintExtensions = [901 lintState,902 view.EditorView.decorations.compute([lintState], state => {903 let { selected, panel } = state.field(lintState);904 return !selected || !panel || selected.from == selected.to ? view.Decoration.none : view.Decoration.set([905 activeMark.range(selected.from, selected.to)906 ]);907 }),908 lintHover,909 baseTheme910];911const lintGutterConfig = state.Facet.define({912 combine(configs) {913 return state.combineConfig(configs, {914 hoverTime: 300 /* Hover.Time */,915 markerFilter: null,916 tooltipFilter: null917 });918 }919});920/**921Returns an extension that installs a gutter showing markers for922each line that has diagnostics, which can be hovered over to see923the diagnostics.924*/925function lintGutter(config = {}) {926 return [lintGutterConfig.of(config), lintGutterMarkers, lintGutterExtension, lintGutterTheme, lintGutterTooltip];927}928/**929Iterate over the marked diagnostics for the given editor state,930calling `f` for each of them. Note that, if the document changed931since the diagnostics were created, the `Diagnostic` object will932hold the original outdated position, whereas the `to` and `from`933arguments hold the diagnostic's current position.934*/935function forEachDiagnostic(state$1, f) {936 let lState = state$1.field(lintState, false);937 if (lState && lState.diagnostics.size) {938 let pending = [], pendingStart = [], lastEnd = -1;939 for (let iter = state.RangeSet.iter([lState.diagnostics]);; iter.next()) {940 for (let i = 0; i < pending.length; i++)941 if (!iter.value || iter.value.spec.diagnostics.indexOf(pending[i]) < 0) {942 f(pending[i], pendingStart[i], lastEnd);943 pending.splice(i, 1);944 pendingStart.splice(i--, 1);945 }946 if (!iter.value)947 break;948 for (let d of iter.value.spec.diagnostics)949 if (pending.indexOf(d) < 0) {950 pending.push(d);951 pendingStart.push(iter.from);952 }953 lastEnd = iter.to;954 }955 }956}957 958exports.closeLintPanel = closeLintPanel;959exports.diagnosticCount = diagnosticCount;960exports.forEachDiagnostic = forEachDiagnostic;961exports.forceLinting = forceLinting;962exports.lintGutter = lintGutter;963exports.lintKeymap = lintKeymap;964exports.linter = linter;965exports.nextDiagnostic = nextDiagnostic;966exports.openLintPanel = openLintPanel;967exports.previousDiagnostic = previousDiagnostic;968exports.setDiagnostics = setDiagnostics;969exports.setDiagnosticsEffect = setDiagnosticsEffect;970 