I'm trying to add HTMLHint into Codemirror 6 by following the lint documentation and the eslint-linter-browserify demo for Codemirror 6. Not sure what I'm doing wrong but the lints are not showing.
Can someone explain what I'm doing wrong and how can I add HTMLHint into Codemirror 6?
lang-html:
function HTMLHint(htmlhint, config) {
config = {
rules: {
"tagname-lowercase": true,
"attr-lowercase": true,
"attr-value-double-quotes": true,
"doctype-first": true,
"tag-pair": true,
"spec-char-escape": true,
"id-unique": true,
"src-not-empty": true,
"attr-no-duplication": true
}
}
return (view) => {
let { state } = view, found = [];
for (let { from, to } of htmlLanguage.findRegions(state)) {
let fromLine = state.doc.lineAt(from), offset = { line: fromLine.number - 1, col: from - fromLine.from, pos: from };
for (let d of htmlhint.verify(state.sliceDoc(from, to)))
found.push(translateDiagnostic(d, state.doc, offset));
}
return found;
};
}
function mapPos(line, col, doc, offset) {
return doc.line(line + offset.line).from + col + (line == 1 ? offset.col - 1 : -1);
}
function translateDiagnostic(input, doc, offset) {
let start = mapPos(input.line, input.column, doc, offset);
let result = {
from: start,
to: input.endLine != null && input.endColumn != 1 ? mapPos(input.endLine, input.endColumn, doc, offset) : start,
message: input.message,
source: input.ruleId ? "htmlhint:" + input.ruleId : "htmlhint",
severity: input.severity == 1 ? "warning" : "error",
};
if (input.fix) {
let { range, text } = input.fix, from = range[0] + offset.pos - start, to = range[1] + offset.pos - start;
result.actions = [{
name: "fix",
apply(view, start) {
view.dispatch({ changes: { from: start + from, to: start + to, insert: text }, scrollIntoView: true });
}
}];
}
return result;
}
export { autoCloseTags, HTMLHint, html, htmlCompletionSource, htmlCompletionSourceWith, htmlLanguage };
editor.js:
import { EditorView } from '@codemirror/view';
import { lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine, keymap } from '@codemirror/view';
import { EditorState } from '@codemirror/state';
import { foldGutter, indentOnInput, syntaxHighlighting, defaultHighlightStyle, bracketMatching, foldKeymap } from '@codemirror/language';
import { history, defaultKeymap, historyKeymap } from '@codemirror/commands';
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
import { linter, lintKeymap, lintGutter } from '@codemirror/lint';
import { javascript } from "@codemirror/lang-javascript";
import { html, HTMLHint } from "@codemirror/lang-html";
import { htmlhint } from 'htmlhint';
// ruleSets for HTMLLint
let ruleSets = {
"tagname-lowercase": true,
"attr-lowercase": true,
"attr-value-double-quotes": true,
"doctype-first": false,
"tag-pair": true,
"spec-char-escape": true,
"id-unique": true,
"src-not-empty": true,
"attr-no-duplication": true
};
const basicSetup = [
lineNumbers(),
highlightActiveLineGutter(),
highlightSpecialChars(),
history(),
foldGutter(),
drawSelection(),
dropCursor(),
EditorState.allowMultipleSelections.of(true),
indentOnInput(),
syntaxHighlighting(defaultHighlightStyle),
bracketMatching(),
closeBrackets(),
autocompletion(),
rectangularSelection(),
crosshairCursor(),
highlightActiveLine(),
highlightSelectionMatches(),
lintGutter(),
linter(HTMLHint(ruleSets)),
keymap.of([
...closeBracketsKeymap,
...defaultKeymap,
...searchKeymap,
...historyKeymap,
...foldKeymap,
...completionKeymap,
...lintKeymap,
]),
html(),
];
const editor = new EditorView({
state: EditorState.create({
doc: `<span id="hi">hello world</span>
<span id="hi">hello world</span>`,
extensions: [basicSetup],
}),
parent: document.getElementById('editor'),
});
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>CodeMirror 6 Test</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<main>
<div id="editor"></div>
</main>
<script src="editor.bundle.js"></script>
</body>
</html>
I was able to accomplish this with Codemirror v5- with....
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
// Depends on htmlhint.js from http://htmlhint.com/js/htmlhint.js
// declare global: HTMLHint
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("htmlhint"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "htmlhint"], mod);
else // Plain browser env
mod(CodeMirror, window.HTMLHint);
})(function(CodeMirror, HTMLHint) {
"use strict";
var defaultRules = {
"tagname-lowercase": true,
"attr-lowercase": true,
"attr-value-double-quotes": true,
"doctype-first": false,
"tag-pair": true,
"spec-char-escape": true,
"id-unique": true,
"src-not-empty": true,
"attr-no-duplication": true
};
CodeMirror.registerHelper("lint", "html", function(text, options) {
var found = [];
if (HTMLHint && !HTMLHint.verify) {
if(typeof HTMLHint.default !== 'undefined') {
HTMLHint = HTMLHint.default;
} else {
HTMLHint = HTMLHint.HTMLHint;
}
}
if (!HTMLHint) HTMLHint = window.HTMLHint;
if (!HTMLHint) {
if (window.console) {
window.console.error("Error: HTMLHint not found, not defined on window, or not available through define/require, CodeMirror HTML linting cannot run.");
}
return found;
}
var messages = HTMLHint.verify(text, options && options.rules || defaultRules);
for (var i = 0; i < messages.length; i++) {
var message = messages[i];
var startLine = message.line - 1, endLine = message.line - 1, startCol = message.col - 1, endCol = message.col;
found.push({
from: CodeMirror.Pos(startLine, startCol),
to: CodeMirror.Pos(endLine, endCol),
message: message.message,
severity : message.type
});
}
return found;
});
});