CodeMirror 5.24

Notable change for css mode: Expose lineComment property for LESS and SCSS dialects. Recognize vendor prefixes on pseudo-elements.
This commit is contained in:
tophf 2017-03-18 03:24:59 +03:00
parent df570dab9e
commit b2e8bf02a9
10 changed files with 113 additions and 53 deletions

View File

@ -1,3 +1,5 @@
MIT License
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@ -46,12 +46,17 @@
// Rough heuristic to try and detect lines that are part of multi-line string // Rough heuristic to try and detect lines that are part of multi-line string
function probablyInsideString(cm, pos, line) { function probablyInsideString(cm, pos, line) {
return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"`]/.test(line) return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line)
}
function getMode(cm, pos) {
var mode = cm.getMode()
return mode.useInnerComments === false || !mode.innerMode ? mode : cm.getModeAt(pos)
} }
CodeMirror.defineExtension("lineComment", function(from, to, options) { CodeMirror.defineExtension("lineComment", function(from, to, options) {
if (!options) options = noOptions; if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from); var self = this, mode = getMode(self, from);
var firstLine = self.getLine(from.line); var firstLine = self.getLine(from.line);
if (firstLine == null || probablyInsideString(self, from, firstLine)) return; if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
@ -95,7 +100,7 @@
CodeMirror.defineExtension("blockComment", function(from, to, options) { CodeMirror.defineExtension("blockComment", function(from, to, options) {
if (!options) options = noOptions; if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from); var self = this, mode = getMode(self, from);
var startString = options.blockCommentStart || mode.blockCommentStart; var startString = options.blockCommentStart || mode.blockCommentStart;
var endString = options.blockCommentEnd || mode.blockCommentEnd; var endString = options.blockCommentEnd || mode.blockCommentEnd;
if (!startString || !endString) { if (!startString || !endString) {
@ -129,7 +134,7 @@
CodeMirror.defineExtension("uncomment", function(from, to, options) { CodeMirror.defineExtension("uncomment", function(from, to, options) {
if (!options) options = noOptions; if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from); var self = this, mode = getMode(self, from);
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end); var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
// Try finding line comments // Try finding line comments
@ -171,9 +176,11 @@
endLine = self.getLine(--end); endLine = self.getLine(--end);
close = endLine.indexOf(endString); close = endLine.indexOf(endString);
} }
var insideStart = Pos(start, open + 1), insideEnd = Pos(end, close + 1)
if (close == -1 || if (close == -1 ||
!/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) || !/comment/.test(self.getTokenTypeAt(insideStart)) ||
!/comment/.test(self.getTokenTypeAt(Pos(end, close + 1)))) !/comment/.test(self.getTokenTypeAt(insideEnd)) ||
self.getRange(insideStart, insideEnd, "\n").indexOf(endString) > -1)
return false; return false;
// Avoid killing block comments completely outside the selection. // Avoid killing block comments completely outside the selection.

View File

@ -140,7 +140,11 @@
if (options.async || getAnnotations.async) { if (options.async || getAnnotations.async) {
lintAsync(cm, getAnnotations, passOptions) lintAsync(cm, getAnnotations, passOptions)
} else { } else {
updateLinting(cm, getAnnotations(cm.getValue(), passOptions, cm)); var annotations = getAnnotations(cm.getValue(), passOptions, cm);
if (annotations.then) annotations.then(function(issues) {
updateLinting(cm, issues);
});
else updateLinting(cm, annotations);
} }
} }

View File

@ -77,17 +77,21 @@
curLine = pos.line; curLine = pos.line;
curLineObj = cm.getLineHandle(curLine); curLineObj = cm.getLineHandle(curLine);
} }
if (wrapping && curLineObj.height > singleLineH) if ((curLineObj.widgets && curLineObj.widgets.length) ||
(wrapping && curLineObj.height > singleLineH))
return cm.charCoords(pos, "local")[top ? "top" : "bottom"]; return cm.charCoords(pos, "local")[top ? "top" : "bottom"];
var topY = cm.heightAtLine(curLineObj, "local"); var topY = cm.heightAtLine(curLineObj, "local");
return topY + (top ? 0 : curLineObj.height); return topY + (top ? 0 : curLineObj.height);
} }
var lastLine = cm.lastLine()
if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) { if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
var ann = anns[i]; var ann = anns[i];
if (ann.to.line > lastLine) continue;
var top = nextTop || getY(ann.from, true) * hScale; var top = nextTop || getY(ann.from, true) * hScale;
var bottom = getY(ann.to, false) * hScale; var bottom = getY(ann.to, false) * hScale;
while (i < anns.length - 1) { while (i < anns.length - 1) {
if (anns[i + 1].to.line > lastLine) break;
nextTop = getY(anns[i + 1].from, true) * hScale; nextTop = getY(anns[i + 1].from, true) * hScale;
if (nextTop > bottom + .9) break; if (nextTop > bottom + .9) break;
ann = anns[++i]; ann = anns[++i];

View File

@ -371,7 +371,9 @@
"Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
"Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace", "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace",
"Alt-/": "autocomplete", "Alt-/": "autocomplete",
"Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto", "Enter": "newlineAndIndent",
"Ctrl-J": repeated(function(cm) { cm.replaceSelection("\n", "end"); }),
"Tab": "indentAuto",
"Alt-G G": function(cm) { "Alt-G G": function(cm) {
var prefix = getPrefix(cm, true); var prefix = getPrefix(cm, true);

View File

@ -152,18 +152,25 @@
var text = cm.getRange(from, to); var text = cm.getRange(from, to);
var query = fullWord ? new RegExp("\\b" + text + "\\b") : text; var query = fullWord ? new RegExp("\\b" + text + "\\b") : text;
var cur = cm.getSearchCursor(query, to); var cur = cm.getSearchCursor(query, to);
if (cur.findNext()) { var found = cur.findNext();
cm.addSelection(cur.from(), cur.to()); if (!found) {
} else {
cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0)); cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0));
if (cur.findNext()) found = cur.findNext();
cm.addSelection(cur.from(), cur.to());
} }
if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to()))
return CodeMirror.Pass
cm.addSelection(cur.from(), cur.to());
} }
if (fullWord) if (fullWord)
cm.state.sublimeFindFullWord = cm.doc.sel; cm.state.sublimeFindFullWord = cm.doc.sel;
}; };
function isSelectedRange(ranges, from, to) {
for (var i = 0; i < ranges.length; i++)
if (ranges[i].from() == from && ranges[i].to() == to) return true
return false
}
var mirror = "(){}[]"; var mirror = "(){}[]";
function selectBetweenBrackets(cm) { function selectBetweenBrackets(cm) {
var ranges = cm.listSelections(), newRanges = [] var ranges = cm.listSelections(), newRanges = []

View File

@ -142,7 +142,7 @@
{ keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }},
{ keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
{ keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'}, { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'},
{ keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'expandToLine', motionArgs: { linewise: true }, context: 'normal'},
{ keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'}, { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'},
{ keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'},
{ keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'}, { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'},
@ -1245,11 +1245,13 @@
} }
} }
function onPromptKeyUp(e, query, close) { function onPromptKeyUp(e, query, close) {
var keyName = CodeMirror.keyName(e), up; var keyName = CodeMirror.keyName(e), up, offset;
if (keyName == 'Up' || keyName == 'Down') { if (keyName == 'Up' || keyName == 'Down') {
up = keyName == 'Up' ? true : false; up = keyName == 'Up' ? true : false;
offset = e.target ? e.target.selectionEnd : 0;
query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; query = vimGlobalState.searchHistoryController.nextMatch(query, up) || '';
close(query); close(query);
if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length);
} else { } else {
if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
vimGlobalState.searchHistoryController.reset(); vimGlobalState.searchHistoryController.reset();
@ -1281,6 +1283,8 @@
clearInputState(cm); clearInputState(cm);
close(); close();
cm.focus(); cm.focus();
} else if (keyName == 'Up' || keyName == 'Down') {
CodeMirror.e_stop(e);
} else if (keyName == 'Ctrl-U') { } else if (keyName == 'Ctrl-U') {
// Ctrl-U clears input. // Ctrl-U clears input.
CodeMirror.e_stop(e); CodeMirror.e_stop(e);
@ -1344,7 +1348,7 @@
exCommandDispatcher.processCommand(cm, input); exCommandDispatcher.processCommand(cm, input);
} }
function onPromptKeyDown(e, input, close) { function onPromptKeyDown(e, input, close) {
var keyName = CodeMirror.keyName(e), up; var keyName = CodeMirror.keyName(e), up, offset;
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' || if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
(keyName == 'Backspace' && input == '')) { (keyName == 'Backspace' && input == '')) {
vimGlobalState.exCommandHistoryController.pushInput(input); vimGlobalState.exCommandHistoryController.pushInput(input);
@ -1355,9 +1359,12 @@
cm.focus(); cm.focus();
} }
if (keyName == 'Up' || keyName == 'Down') { if (keyName == 'Up' || keyName == 'Down') {
CodeMirror.e_stop(e);
up = keyName == 'Up' ? true : false; up = keyName == 'Up' ? true : false;
offset = e.target ? e.target.selectionEnd : 0;
input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || '';
close(input); close(input);
if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length);
} else if (keyName == 'Ctrl-U') { } else if (keyName == 'Ctrl-U') {
// Ctrl-U clears input. // Ctrl-U clears input.
CodeMirror.e_stop(e); CodeMirror.e_stop(e);
@ -1620,9 +1627,8 @@
return findNext(cm, prev/** prev */, query, motionArgs.repeat); return findNext(cm, prev/** prev */, query, motionArgs.repeat);
}, },
goToMark: function(cm, _head, motionArgs, vim) { goToMark: function(cm, _head, motionArgs, vim) {
var mark = vim.marks[motionArgs.selectedCharacter]; var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter);
if (mark) { if (pos) {
var pos = mark.find();
return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos;
} }
return null; return null;
@ -3966,6 +3972,17 @@
return {top: from.line, bottom: to.line}; return {top: from.line, bottom: to.line};
} }
function getMarkPos(cm, vim, markName) {
if (markName == '\'') {
var history = cm.doc.history.done;
var event = history[history.length - 2];
return event && event.ranges && event.ranges[0].head;
}
var mark = vim.marks[markName];
return mark && mark.find();
}
var ExCommandDispatcher = function() { var ExCommandDispatcher = function() {
this.buildCommandMap_(); this.buildCommandMap_();
}; };
@ -4074,11 +4091,10 @@
case '$': case '$':
return cm.lastLine(); return cm.lastLine();
case '\'': case '\'':
var mark = cm.state.vim.marks[inputStream.next()]; var markName = inputStream.next();
if (mark && mark.find()) { var markPos = getMarkPos(cm, cm.state.vim, markName);
return mark.find().line; if (!markPos) throw new Error('Mark not set');
} return markPos.line;
throw new Error('Mark not set');
default: default:
inputStream.backUp(1); inputStream.backUp(1);
return undefined; return undefined;
@ -4147,8 +4163,8 @@
var mapping = { var mapping = {
keys: lhs, keys: lhs,
type: 'keyToEx', type: 'keyToEx',
exArgs: { input: rhs.substring(1) }, exArgs: { input: rhs.substring(1) }
user: true}; };
if (ctx) { mapping.context = ctx; } if (ctx) { mapping.context = ctx; }
defaultKeymap.unshift(mapping); defaultKeymap.unshift(mapping);
} else { } else {
@ -4156,8 +4172,7 @@
var mapping = { var mapping = {
keys: lhs, keys: lhs,
type: 'keyToKey', type: 'keyToKey',
toKeys: rhs, toKeys: rhs
user: true
}; };
if (ctx) { mapping.context = ctx; } if (ctx) { mapping.context = ctx; }
defaultKeymap.unshift(mapping); defaultKeymap.unshift(mapping);
@ -4178,8 +4193,7 @@
var keys = lhs; var keys = lhs;
for (var i = 0; i < defaultKeymap.length; i++) { for (var i = 0; i < defaultKeymap.length; i++) {
if (keys == defaultKeymap[i].keys if (keys == defaultKeymap[i].keys
&& defaultKeymap[i].context === ctx && defaultKeymap[i].context === ctx) {
&& defaultKeymap[i].user) {
defaultKeymap.splice(i, 1); defaultKeymap.splice(i, 1);
return; return;
} }
@ -4310,25 +4324,27 @@
showConfirm(cm, regInfo); showConfirm(cm, regInfo);
}, },
sort: function(cm, params) { sort: function(cm, params) {
var reverse, ignoreCase, unique, number; var reverse, ignoreCase, unique, number, pattern;
function parseArgs() { function parseArgs() {
if (params.argString) { if (params.argString) {
var args = new CodeMirror.StringStream(params.argString); var args = new CodeMirror.StringStream(params.argString);
if (args.eat('!')) { reverse = true; } if (args.eat('!')) { reverse = true; }
if (args.eol()) { return; } if (args.eol()) { return; }
if (!args.eatSpace()) { return 'Invalid arguments'; } if (!args.eatSpace()) { return 'Invalid arguments'; }
var opts = args.match(/[a-z]+/); var opts = args.match(/([dinuox]+)?\s*(\/.+\/)?\s*/);
if (opts) { if (!opts && !args.eol()) { return 'Invalid arguments'; }
opts = opts[0]; if (opts[1]) {
ignoreCase = opts.indexOf('i') != -1; ignoreCase = opts[1].indexOf('i') != -1;
unique = opts.indexOf('u') != -1; unique = opts[1].indexOf('u') != -1;
var decimal = opts.indexOf('d') != -1 && 1; var decimal = opts[1].indexOf('d') != -1 || opts[1].indexOf('n') != -1 && 1;
var hex = opts.indexOf('x') != -1 && 1; var hex = opts[1].indexOf('x') != -1 && 1;
var octal = opts.indexOf('o') != -1 && 1; var octal = opts[1].indexOf('o') != -1 && 1;
if (decimal + hex + octal > 1) { return 'Invalid arguments'; } if (decimal + hex + octal > 1) { return 'Invalid arguments'; }
number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; number = decimal && 'decimal' || hex && 'hex' || octal && 'octal';
} }
if (args.match(/\/.*\//)) { return 'patterns not supported'; } if (opts[2]) {
pattern = new RegExp(opts[2].substr(1, opts[2].length - 2), ignoreCase ? 'i' : '');
}
} }
} }
var err = parseArgs(); var err = parseArgs();
@ -4342,14 +4358,18 @@
var curStart = Pos(lineStart, 0); var curStart = Pos(lineStart, 0);
var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); var curEnd = Pos(lineEnd, lineLength(cm, lineEnd));
var text = cm.getRange(curStart, curEnd).split('\n'); var text = cm.getRange(curStart, curEnd).split('\n');
var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ : var numberRegex = pattern ? pattern :
(number == 'decimal') ? /(-?)([\d]+)/ :
(number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i :
(number == 'octal') ? /([0-7]+)/ : null; (number == 'octal') ? /([0-7]+)/ : null;
var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null;
var numPart = [], textPart = []; var numPart = [], textPart = [];
if (number) { if (number || pattern) {
for (var i = 0; i < text.length; i++) { for (var i = 0; i < text.length; i++) {
if (numberRegex.exec(text[i])) { var matchPart = pattern ? text[i].match(pattern) : null;
if (matchPart && matchPart[0] != '') {
numPart.push(matchPart);
} else if (!pattern && numberRegex.exec(text[i])) {
numPart.push(text[i]); numPart.push(text[i]);
} else { } else {
textPart.push(text[i]); textPart.push(text[i]);
@ -4368,8 +4388,17 @@
bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix);
return anum - bnum; return anum - bnum;
} }
numPart.sort(compareFn); function comparePatternFn(a, b) {
textPart.sort(compareFn); if (reverse) { var tmp; tmp = a; a = b; b = tmp; }
if (ignoreCase) { a[0] = a[0].toLowerCase(); b[0] = b[0].toLowerCase(); }
return (a[0] < b[0]) ? -1 : 1;
}
numPart.sort(pattern ? comparePatternFn : compareFn);
if (pattern) {
for (var i = 0; i < numPart.length; i++) {
numPart[i] = numPart[i].input;
}
} else if (!number) { textPart.sort(compareFn); }
text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart);
if (unique) { // Remove duplicate lines if (unique) { // Remove duplicate lines
var textOld = text; var textOld = text;

View File

@ -223,11 +223,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
cursor: default; cursor: default;
z-index: 4; z-index: 4;
} }
.CodeMirror-gutter-wrapper { .CodeMirror-gutter-wrapper ::selection { background-color: transparent }
-webkit-user-select: none; .CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
-moz-user-select: none;
user-select: none;
}
.CodeMirror-lines { .CodeMirror-lines {
cursor: text; cursor: text;
@ -272,6 +269,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-widget {} .CodeMirror-widget {}
.CodeMirror-rtl pre { direction: rtl; }
.CodeMirror-code { .CodeMirror-code {
outline: none; outline: none;
} }

View File

@ -28,6 +28,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
colorKeywords = parserConfig.colorKeywords || {}, colorKeywords = parserConfig.colorKeywords || {},
valueKeywords = parserConfig.valueKeywords || {}, valueKeywords = parserConfig.valueKeywords || {},
allowNested = parserConfig.allowNested, allowNested = parserConfig.allowNested,
lineComment = parserConfig.lineComment,
supportsAtComponent = parserConfig.supportsAtComponent === true; supportsAtComponent = parserConfig.supportsAtComponent === true;
var type, override; var type, override;
@ -253,6 +254,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
}; };
states.pseudo = function(type, stream, state) { states.pseudo = function(type, stream, state) {
if (type == "meta") return "pseudo";
if (type == "word") { if (type == "word") {
override = "variable-3"; override = "variable-3";
return state.context.type; return state.context.type;
@ -407,6 +410,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
electricChars: "}", electricChars: "}",
blockCommentStart: "/*", blockCommentStart: "/*",
blockCommentEnd: "*/", blockCommentEnd: "*/",
lineComment: lineComment,
fold: "brace" fold: "brace"
}; };
}); });
@ -663,7 +667,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali", "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square", "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
"square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
"subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table", "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
"table-caption", "table-cell", "table-column", "table-column-group", "table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group", "table-footer-group", "table-header-group", "table-row", "table-row-group",
"tamil", "tamil",
@ -730,6 +734,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
valueKeywords: valueKeywords, valueKeywords: valueKeywords,
fontProperties: fontProperties, fontProperties: fontProperties,
allowNested: true, allowNested: true,
lineComment: "//",
tokenHooks: { tokenHooks: {
"/": function(stream, state) { "/": function(stream, state) {
if (stream.eat("/")) { if (stream.eat("/")) {
@ -772,6 +777,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
valueKeywords: valueKeywords, valueKeywords: valueKeywords,
fontProperties: fontProperties, fontProperties: fontProperties,
allowNested: true, allowNested: true,
lineComment: "//",
tokenHooks: { tokenHooks: {
"/": function(stream, state) { "/": function(stream, state) {
if (stream.eat("/")) { if (stream.eat("/")) {

View File

@ -64,7 +64,7 @@ code {
</textarea></form> </textarea></form>
<script> <script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), { var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
extraKeys: {"Ctrl-Space": "autocomplete"}, extraKeys: {"Ctrl-Space": "autocomplete"}
}); });
</script> </script>