Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

codemirror

Package Overview
Dependencies
Maintainers
1
Versions
151
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

codemirror - npm Package Compare versions

Comparing version 2.33.0 to 3.11.1

.gitattributes

3

keymap/emacs.js

@@ -21,3 +21,4 @@ // TODO number prefixes

"Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace",
"Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete",
"Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete", "Alt-V": "goPageUp",
"Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
fallthrough: ["basic", "emacsy"]

@@ -24,0 +25,0 @@ };

CodeMirror.defineMode("clike", function(config, parserConfig) {
var indentUnit = config.indentUnit,
statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
dontAlignCalls = parserConfig.dontAlignCalls,
keywords = parserConfig.keywords || {},

@@ -92,3 +94,6 @@ builtin = parserConfig.builtin || {},

function pushContext(state, col, type) {
return state.context = new Context(state.indented, col, type, null, state.context);
var indent = state.indented;
if (state.context && state.context.type == "statement")
indent = state.context.indented;
return state.context = new Context(indent, col, type, null, state.context);
}

@@ -127,3 +132,3 @@ function popContext(state) {

if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
else if (curPunc == "{") pushContext(state, stream.column(), "}");

@@ -138,3 +143,3 @@ else if (curPunc == "[") pushContext(state, stream.column(), "]");

else if (curPunc == ctx.type) popContext(state);
else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
pushContext(state, stream.column(), "statement");

@@ -146,7 +151,8 @@ state.startOfLine = false;

indent: function(state, textAfter) {
if (state.tokenize != tokenBase && state.tokenize != null) return 0;
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
var closing = firstChar == ctx.type;
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
else if (dontAlignCalls && ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
else if (ctx.align) return ctx.column + (closing ? 0 : 1);

@@ -172,3 +178,15 @@ else return ctx.indented + (closing ? 0 : indentUnit);

if (!state.startOfLine) return false;
stream.skipToEnd();
for (;;) {
if (stream.skipTo("\\")) {
stream.next();
if (stream.eol()) {
state.tokenize = cppHook;
break;
}
} else {
stream.skipToEnd();
state.tokenize = null;
break;
}
}
return "meta";

@@ -220,3 +238,3 @@ }

hooks: {
"@": function(stream, state) {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);

@@ -284,3 +302,3 @@ return "meta";

hooks: {
"@": function(stream, state) {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);

@@ -287,0 +305,0 @@ return "meta";

@@ -5,6 +5,6 @@ /**

*/
CodeMirror.defineMode("clojure", function (config, mode) {
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", TAG = "tag",
CodeMirror.defineMode("clojure", function () {
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2",
ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword";
var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
var INDENT_WORD_SKIP = 2;

@@ -23,3 +23,3 @@ function makeKeywords(str) {

var builtins = makeKeywords(
"* *1 *2 *3 *agent* *allow-unresolved-vars* *assert *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - / < <= = == > >= accessor aclone agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? extend extend-protocol extend-type extends? extenders false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reify reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq");
"* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> ->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? declare default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int rand-nth range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap *default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! set-agent-send-off-executor! some-> some->>");

@@ -100,2 +100,16 @@ var indentKeys = makeKeywords(

// Eat character that starts after backslash \
function eatCharacter(stream) {
var first = stream.next();
// Read special literals: backspace, newline, space, return.
// Just read all lowercase letters.
if (first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {
return;
}
// Read unicode character: \u1000 \uA0a1
if (first === "u") {
stream.match(/[0-9a-z]{4}/i, true);
}
}
return {

@@ -141,2 +155,5 @@ startState: function () {

returnType = STRING;
} else if (ch == "\\") {
eatCharacter(stream);
returnType = CHARACTER;
} else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {

@@ -149,3 +166,3 @@ returnType = ATOM;

returnType = NUMBER;
} else if (ch == "(" || ch == "[") {
} else if (ch == "(" || ch == "[" || ch == "{" ) {
var keyWord = '', indentTemp = stream.column(), letter;

@@ -180,5 +197,5 @@ /**

returnType = BRACKET;
} else if (ch == ")" || ch == "]") {
} else if (ch == ")" || ch == "]" || ch == "}") {
returnType = BRACKET;
if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) {
if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : (ch == "]" ? "[" :"{"))) {
popStack(state);

@@ -205,3 +222,3 @@ }

indent: function (state, textAfter) {
indent: function (state) {
if (state.indentStack == null) return state.indentation;

@@ -208,0 +225,0 @@ return state.indentStack.indent;

@@ -173,3 +173,3 @@ /**

var singleline = delimiter.length == 1;
return function tokenString(stream, state) {
return function(stream, state) {
while (!stream.eol()) {

@@ -335,3 +335,3 @@ stream.eatWhile(/[^'"\/\\]/);

indent: function(state, textAfter) {
indent: function(state) {
if (state.tokenize != tokenBase) {

@@ -338,0 +338,0 @@ return 0;

CodeMirror.defineMode("css", function(config) {
var indentUnit = config.indentUnit, type;
var atMediaTypes = keySet([
"all", "aural", "braille", "handheld", "print", "projection", "screen",
"tty", "tv", "embossed"
]);
var atMediaFeatures = keySet([
"width", "min-width", "max-width", "height", "min-height", "max-height",
"device-width", "min-device-width", "max-device-width", "device-height",
"min-device-height", "max-device-height", "aspect-ratio",
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
"max-color", "color-index", "min-color-index", "max-color-index",
"monochrome", "min-monochrome", "max-monochrome", "resolution",
"min-resolution", "max-resolution", "scan", "grid"
]);
return CodeMirror.getMode(config, "text/css");
});
var propertyKeywords = keySet([
"align-content", "align-items", "align-self", "alignment-adjust",
"alignment-baseline", "anchor-point", "animation", "animation-delay",
"animation-direction", "animation-duration", "animation-iteration-count",
"animation-name", "animation-play-state", "animation-timing-function",
"appearance", "azimuth", "backface-visibility", "background",
"background-attachment", "background-clip", "background-color",
"background-image", "background-origin", "background-position",
"background-repeat", "background-size", "baseline-shift", "binding",
"bleed", "bookmark-label", "bookmark-level", "bookmark-state",
"bookmark-target", "border", "border-bottom", "border-bottom-color",
"border-bottom-left-radius", "border-bottom-right-radius",
"border-bottom-style", "border-bottom-width", "border-collapse",
"border-color", "border-image", "border-image-outset",
"border-image-repeat", "border-image-slice", "border-image-source",
"border-image-width", "border-left", "border-left-color",
"border-left-style", "border-left-width", "border-radius", "border-right",
"border-right-color", "border-right-style", "border-right-width",
"border-spacing", "border-style", "border-top", "border-top-color",
"border-top-left-radius", "border-top-right-radius", "border-top-style",
"border-top-width", "border-width", "bottom", "box-decoration-break",
"box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
"caption-side", "clear", "clip", "color", "color-profile", "column-count",
"column-fill", "column-gap", "column-rule", "column-rule-color",
"column-rule-style", "column-rule-width", "column-span", "column-width",
"columns", "content", "counter-increment", "counter-reset", "crop", "cue",
"cue-after", "cue-before", "cursor", "direction", "display",
"dominant-baseline", "drop-initial-after-adjust",
"drop-initial-after-align", "drop-initial-before-adjust",
"drop-initial-before-align", "drop-initial-size", "drop-initial-value",
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
"float", "float-offset", "font", "font-feature-settings", "font-family",
"font-kerning", "font-language-override", "font-size", "font-size-adjust",
"font-stretch", "font-style", "font-synthesis", "font-variant",
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
"font-weight", "grid-cell", "grid-column", "grid-column-align",
"grid-column-sizing", "grid-column-span", "grid-columns", "grid-flow",
"grid-row", "grid-row-align", "grid-row-sizing", "grid-row-span",
"grid-rows", "grid-template", "hanging-punctuation", "height", "hyphens",
"icon", "image-orientation", "image-rendering", "image-resolution",
"inline-box-align", "justify-content", "left", "letter-spacing",
"line-break", "line-height", "line-stacking", "line-stacking-ruby",
"line-stacking-shift", "line-stacking-strategy", "list-style",
"list-style-image", "list-style-position", "list-style-type", "margin",
"margin-bottom", "margin-left", "margin-right", "margin-top",
"marker-offset", "marks", "marquee-direction", "marquee-loop",
"marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
"nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline",
"outline-color", "outline-offset", "outline-style", "outline-width",
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
"page", "page-break-after", "page-break-before", "page-break-inside",
"page-policy", "pause", "pause-after", "pause-before", "perspective",
"perspective-origin", "pitch", "pitch-range", "play-during", "position",
"presentation-level", "punctuation-trim", "quotes", "rendering-intent",
"resize", "rest", "rest-after", "rest-before", "richness", "right",
"rotation", "rotation-point", "ruby-align", "ruby-overhang",
"ruby-position", "ruby-span", "size", "speak", "speak-as", "speak-header",
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
"tab-size", "table-layout", "target", "target-name", "target-new",
"target-position", "text-align", "text-align-last", "text-decoration",
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
"text-decoration-style", "text-emphasis", "text-emphasis-color",
"text-emphasis-position", "text-emphasis-style", "text-height",
"text-indent", "text-justify", "text-outline", "text-shadow",
"text-space-collapse", "text-transform", "text-underline-position",
"text-wrap", "top", "transform", "transform-origin", "transform-style",
"transition", "transition-delay", "transition-duration",
"transition-property", "transition-timing-function", "unicode-bidi",
"vertical-align", "visibility", "voice-balance", "voice-duration",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
"word-spacing", "word-wrap", "z-index"
]);
CodeMirror.defineMode("css-base", function(config, parserConfig) {
"use strict";
var colorKeywords = keySet([
"black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia",
"green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua"
]);
var valueKeywords = keySet([
"above", "absolute", "activeborder", "activecaption", "afar",
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
"arabic-indic", "armenian", "asterisks", "auto", "avoid", "background",
"backwards", "baseline", "below", "bidi-override", "binary", "bengali",
"blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
"both", "bottom", "break-all", "break-word", "button", "button-bevel",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
"cell", "center", "checkbox", "circle", "cjk-earthly-branch",
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
"col-resize", "collapse", "compact", "condensed", "contain", "content",
"content-box", "context-menu", "continuous", "copy", "cover", "crop",
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
"decimal-leading-zero", "default", "default-button", "destination-atop",
"destination-in", "destination-out", "destination-over", "devanagari",
"disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
"double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
"element", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et",
"ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed",
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes",
"forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
"italic", "justify", "kannada", "katakana", "katakana-iroha", "khmer",
"landscape", "lao", "large", "larger", "left", "level", "lighter",
"line-through", "linear", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
"lower-roman", "lowercase", "ltr", "malayalam", "match",
"media-controls-background", "media-current-time-display",
"media-fullscreen-button", "media-mute-button", "media-play-button",
"media-return-to-realtime-button", "media-rewind-button",
"media-seek-back-button", "media-seek-forward-button", "media-slider",
"media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
"media-volume-slider-container", "media-volume-sliderthumb", "medium",
"menu", "menulist", "menulist-button", "menulist-text",
"menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
"mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
"narrower", "navy", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
"outside", "overlay", "overline", "padding", "padding-box", "painted",
"paused", "persian", "plus-darker", "plus-lighter", "pointer", "portrait",
"pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
"radio", "read-only", "read-write", "read-write-plaintext-only", "relative",
"repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
"ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
"s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
"searchfield-cancel-button", "searchfield-decoration",
"searchfield-results-button", "searchfield-results-decoration",
"semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
"single", "skip-white-space", "slide", "slider-horizontal",
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
"small", "small-caps", "small-caption", "smaller", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "square",
"square-button", "start", "static", "status-bar", "stretch", "stroke",
"sub", "subpixel-antialiased", "super", "sw-resize", "table",
"table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group",
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
"transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
"vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
"visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider",
"window", "windowframe", "windowtext", "x-large", "x-small", "xor",
"xx-large", "xx-small", "yellow"
]);
var indentUnit = config.indentUnit,
hooks = parserConfig.hooks || {},
atMediaTypes = parserConfig.atMediaTypes || {},
atMediaFeatures = parserConfig.atMediaFeatures || {},
propertyKeywords = parserConfig.propertyKeywords || {},
colorKeywords = parserConfig.colorKeywords || {},
valueKeywords = parserConfig.valueKeywords || {},
allowNested = !!parserConfig.allowNested,
type = null;
function keySet(array) { var keys = {}; for (var i = 0; i < array.length; ++i) keys[array[i]] = true; return keys; }
function ret(style, tp) {type = tp; return style;}
function ret(style, tp) { type = tp; return style; }
function tokenBase(stream, state) {
var ch = stream.next();
if (hooks[ch]) {
// result[0] is style and result[1] is type
var result = hooks[ch](stream, state);
if (result !== false) return result;
}
if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("def", stream.current());}
else if (ch == "/" && stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
}
else if (ch == "<" && stream.eat("!")) {
state.tokenize = tokenSGMLComment;
return tokenSGMLComment(stream, state);
}
else if (ch == "=") ret(null, "compare");

@@ -225,3 +51,3 @@ else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");

} else if (stream.match(/^[^-]+-/)) {
return ret("meta", type);
return ret("meta", "meta");
}

@@ -232,4 +58,4 @@ }

}
else if (ch == "." && stream.match(/^\w+/)) {
return ret("qualifier", type);
else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
return ret("qualifier", "qualifier");
}

@@ -242,2 +68,7 @@ else if (ch == ":") {

}
else if (ch == "u" && stream.match("rl(")) {
stream.backUp(1);
state.tokenize = tokenParenthesized;
return ret("property", "variable");
}
else {

@@ -249,27 +80,3 @@ stream.eatWhile(/[\w\\\-]/);

function tokenCComment(stream, state) {
var maybeEnd = false, ch;
while ((ch = stream.next()) != null) {
if (maybeEnd && ch == "/") {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "*");
}
return ret("comment", "comment");
}
function tokenSGMLComment(stream, state) {
var dashes = 0, ch;
while ((ch = stream.next()) != null) {
if (dashes >= 2 && ch == ">") {
state.tokenize = tokenBase;
break;
}
dashes = (ch == "-") ? dashes + 1 : 0;
}
return ret("comment", "comment");
}
function tokenString(quote) {
function tokenString(quote, nonInclusive) {
return function(stream, state) {

@@ -282,3 +89,6 @@ var escaped = false, ch;

}
if (!escaped) state.tokenize = tokenBase;
if (!escaped) {
if (nonInclusive) stream.backUp(1);
state.tokenize = tokenBase;
}
return ret("string", "string");

@@ -288,2 +98,11 @@ };

function tokenParenthesized(stream, state) {
stream.next(); // Must be '('
if (!stream.match(/\s*[\"\']/, false))
state.tokenize = tokenString(")", true);
else
state.tokenize = tokenBase;
return ret(null, "(");
}
return {

@@ -297,17 +116,17 @@ startState: function(base) {

token: function(stream, state) {
// Use these terms when applicable (see http://www.xanthir.com/blog/b4E50)
//
//
// rule** or **ruleset:
// A selector + braces combo, or an at-rule.
//
//
// declaration block:
// A sequence of declarations.
//
//
// declaration:
// A property + colon + value combo.
//
//
// property value:
// The entire value of a property.
//
//
// component value:

@@ -318,3 +137,3 @@ // A single piece of a property value. Like the 5px in

// portion of the background shorthand.
//
//
// term:

@@ -324,15 +143,15 @@ // The basic unit of author-facing CSS, like a single number (5),

// by the CSS 2.1 grammar (look for the 'term' production)
//
//
//
//
// simple selector:
// A single atomic selector, like a type selector, an attr selector, a
// class selector, etc.
//
//
// compound selector:
// One or more simple selectors without a combinator. div.example is
// compound, div > .example is not.
//
//
// complex selector:
// One or more compound selectors chained with combinators.
//
//
// combinator:

@@ -343,12 +162,17 @@ // The parts of selectors that express relationships. There are four

// and the tilda (following sibling combinator).
//
//
// sequence of selectors:
// One or more of the named type of selector chained with commas.
if (stream.eatSpace()) return null;
state.tokenize = state.tokenize || tokenBase;
if (state.tokenize == tokenBase && stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
if (style && typeof style != "string") style = ret(style[0], style[1]);
// Changing style returned based on context
var context = state.stack[state.stack.length-1];
if (style == "property") {
if (style == "variable") {
if (type == "variable-definition") state.stack.push("propertyValue");
return "variable-2";
} else if (style == "property") {
if (context == "propertyValue"){

@@ -366,2 +190,14 @@ if (valueKeywords[stream.current()]) {

}
} else if (context == "block") {
// if a value is present in both property, value, or color, the order
// of preference is property -> color -> value
if (propertyKeywords[stream.current()]) {
style = "property";
} else if (colorKeywords[stream.current()]) {
style = "keyword";
} else if (valueKeywords[stream.current()]) {
style = "string-2";
} else {
style = "tag";
}
} else if (!context || context == "@media{") {

@@ -412,3 +248,3 @@ style = "tag";

} else if (style == "atom") {
if(!context || context == "@media{") {
if(!context || context == "@media{" || context == "block") {
style = "builtin";

@@ -432,8 +268,14 @@ } else if (context == "propertyValue") {

}
else state.stack.push("rule");
else {
var newContext = allowNested ? "block" : "rule";
state.stack.push(newContext);
}
}
else if (type == "}") {
var lastState = state.stack[state.stack.length - 1];
if (lastState == "interpolation") style = "operator";
state.stack.pop();
if (context == "propertyValue") state.stack.pop();
}
else if (type == "interpolation") state.stack.push("interpolation");
else if (type == "@media") state.stack.push("@media");

@@ -445,3 +287,3 @@ else if (context == "@media" && /\b(keyword|attribute)\b/.test(style))

else if (context == "@mediaType(" && type == ")") state.stack.pop();
else if (context == "rule" && type == ":") state.stack.push("propertyValue");
else if ((context == "rule" || context == "block") && type == ":") state.stack.push("propertyValue");
else if (context == "propertyValue" && type == ";") state.stack.pop();

@@ -462,2 +304,279 @@ return style;

CodeMirror.defineMIME("text/css", "css");
(function() {
function keySet(array) {
var keys = {};
for (var i = 0; i < array.length; ++i) {
keys[array[i]] = true;
}
return keys;
}
var atMediaTypes = keySet([
"all", "aural", "braille", "handheld", "print", "projection", "screen",
"tty", "tv", "embossed"
]);
var atMediaFeatures = keySet([
"width", "min-width", "max-width", "height", "min-height", "max-height",
"device-width", "min-device-width", "max-device-width", "device-height",
"min-device-height", "max-device-height", "aspect-ratio",
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
"max-color", "color-index", "min-color-index", "max-color-index",
"monochrome", "min-monochrome", "max-monochrome", "resolution",
"min-resolution", "max-resolution", "scan", "grid"
]);
var propertyKeywords = keySet([
"align-content", "align-items", "align-self", "alignment-adjust",
"alignment-baseline", "anchor-point", "animation", "animation-delay",
"animation-direction", "animation-duration", "animation-iteration-count",
"animation-name", "animation-play-state", "animation-timing-function",
"appearance", "azimuth", "backface-visibility", "background",
"background-attachment", "background-clip", "background-color",
"background-image", "background-origin", "background-position",
"background-repeat", "background-size", "baseline-shift", "binding",
"bleed", "bookmark-label", "bookmark-level", "bookmark-state",
"bookmark-target", "border", "border-bottom", "border-bottom-color",
"border-bottom-left-radius", "border-bottom-right-radius",
"border-bottom-style", "border-bottom-width", "border-collapse",
"border-color", "border-image", "border-image-outset",
"border-image-repeat", "border-image-slice", "border-image-source",
"border-image-width", "border-left", "border-left-color",
"border-left-style", "border-left-width", "border-radius", "border-right",
"border-right-color", "border-right-style", "border-right-width",
"border-spacing", "border-style", "border-top", "border-top-color",
"border-top-left-radius", "border-top-right-radius", "border-top-style",
"border-top-width", "border-width", "bottom", "box-decoration-break",
"box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
"caption-side", "clear", "clip", "color", "color-profile", "column-count",
"column-fill", "column-gap", "column-rule", "column-rule-color",
"column-rule-style", "column-rule-width", "column-span", "column-width",
"columns", "content", "counter-increment", "counter-reset", "crop", "cue",
"cue-after", "cue-before", "cursor", "direction", "display",
"dominant-baseline", "drop-initial-after-adjust",
"drop-initial-after-align", "drop-initial-before-adjust",
"drop-initial-before-align", "drop-initial-size", "drop-initial-value",
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
"float", "float-offset", "font", "font-feature-settings", "font-family",
"font-kerning", "font-language-override", "font-size", "font-size-adjust",
"font-stretch", "font-style", "font-synthesis", "font-variant",
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
"font-weight", "grid-cell", "grid-column", "grid-column-align",
"grid-column-sizing", "grid-column-span", "grid-columns", "grid-flow",
"grid-row", "grid-row-align", "grid-row-sizing", "grid-row-span",
"grid-rows", "grid-template", "hanging-punctuation", "height", "hyphens",
"icon", "image-orientation", "image-rendering", "image-resolution",
"inline-box-align", "justify-content", "left", "letter-spacing",
"line-break", "line-height", "line-stacking", "line-stacking-ruby",
"line-stacking-shift", "line-stacking-strategy", "list-style",
"list-style-image", "list-style-position", "list-style-type", "margin",
"margin-bottom", "margin-left", "margin-right", "margin-top",
"marker-offset", "marks", "marquee-direction", "marquee-loop",
"marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
"nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline",
"outline-color", "outline-offset", "outline-style", "outline-width",
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
"page", "page-break-after", "page-break-before", "page-break-inside",
"page-policy", "pause", "pause-after", "pause-before", "perspective",
"perspective-origin", "pitch", "pitch-range", "play-during", "position",
"presentation-level", "punctuation-trim", "quotes", "rendering-intent",
"resize", "rest", "rest-after", "rest-before", "richness", "right",
"rotation", "rotation-point", "ruby-align", "ruby-overhang",
"ruby-position", "ruby-span", "size", "speak", "speak-as", "speak-header",
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
"tab-size", "table-layout", "target", "target-name", "target-new",
"target-position", "text-align", "text-align-last", "text-decoration",
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
"text-decoration-style", "text-emphasis", "text-emphasis-color",
"text-emphasis-position", "text-emphasis-style", "text-height",
"text-indent", "text-justify", "text-outline", "text-shadow",
"text-space-collapse", "text-transform", "text-underline-position",
"text-wrap", "top", "transform", "transform-origin", "transform-style",
"transition", "transition-delay", "transition-duration",
"transition-property", "transition-timing-function", "unicode-bidi",
"vertical-align", "visibility", "voice-balance", "voice-duration",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
"word-spacing", "word-wrap", "z-index"
]);
var colorKeywords = keySet([
"black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia",
"green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua"
]);
var valueKeywords = keySet([
"above", "absolute", "activeborder", "activecaption", "afar",
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
"arabic-indic", "armenian", "asterisks", "auto", "avoid", "background",
"backwards", "baseline", "below", "bidi-override", "binary", "bengali",
"blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
"both", "bottom", "break-all", "break-word", "button", "button-bevel",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
"cell", "center", "checkbox", "circle", "cjk-earthly-branch",
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
"col-resize", "collapse", "compact", "condensed", "contain", "content",
"content-box", "context-menu", "continuous", "copy", "cover", "crop",
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
"decimal-leading-zero", "default", "default-button", "destination-atop",
"destination-in", "destination-out", "destination-over", "devanagari",
"disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
"double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
"element", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et",
"ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed",
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes",
"forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
"italic", "justify", "kannada", "katakana", "katakana-iroha", "khmer",
"landscape", "lao", "large", "larger", "left", "level", "lighter",
"line-through", "linear", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
"lower-roman", "lowercase", "ltr", "malayalam", "match",
"media-controls-background", "media-current-time-display",
"media-fullscreen-button", "media-mute-button", "media-play-button",
"media-return-to-realtime-button", "media-rewind-button",
"media-seek-back-button", "media-seek-forward-button", "media-slider",
"media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
"media-volume-slider-container", "media-volume-sliderthumb", "medium",
"menu", "menulist", "menulist-button", "menulist-text",
"menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
"mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
"outside", "overlay", "overline", "padding", "padding-box", "painted",
"paused", "persian", "plus-darker", "plus-lighter", "pointer", "portrait",
"pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
"radio", "read-only", "read-write", "read-write-plaintext-only", "relative",
"repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
"ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
"s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
"searchfield-cancel-button", "searchfield-decoration",
"searchfield-results-button", "searchfield-results-decoration",
"semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
"single", "skip-white-space", "slide", "slider-horizontal",
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
"small", "small-caps", "small-caption", "smaller", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "square",
"square-button", "start", "static", "status-bar", "stretch", "stroke",
"sub", "subpixel-antialiased", "super", "sw-resize", "table",
"table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group",
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
"transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
"vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
"visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider",
"window", "windowframe", "windowtext", "x-large", "x-small", "xor",
"xx-large", "xx-small"
]);
function tokenCComment(stream, state) {
var maybeEnd = false, ch;
while ((ch = stream.next()) != null) {
if (maybeEnd && ch == "/") {
state.tokenize = null;
break;
}
maybeEnd = (ch == "*");
}
return ["comment", "comment"];
}
CodeMirror.defineMIME("text/css", {
atMediaTypes: atMediaTypes,
atMediaFeatures: atMediaFeatures,
propertyKeywords: propertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
hooks: {
"<": function(stream, state) {
function tokenSGMLComment(stream, state) {
var dashes = 0, ch;
while ((ch = stream.next()) != null) {
if (dashes >= 2 && ch == ">") {
state.tokenize = null;
break;
}
dashes = (ch == "-") ? dashes + 1 : 0;
}
return ["comment", "comment"];
}
if (stream.eat("!")) {
state.tokenize = tokenSGMLComment;
return tokenSGMLComment(stream, state);
}
},
"/": function(stream, state) {
if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
}
return false;
}
},
name: "css-base"
});
CodeMirror.defineMIME("text/x-scss", {
atMediaTypes: atMediaTypes,
atMediaFeatures: atMediaFeatures,
propertyKeywords: propertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
allowNested: true,
hooks: {
"$": function(stream) {
stream.match(/^[\w-]+/);
if (stream.peek() == ":") {
return ["variable", "variable-definition"];
}
return ["variable", "variable"];
},
"/": function(stream, state) {
if (stream.eat("/")) {
stream.skipToEnd();
return ["comment", "comment"];
} else if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
} else {
return ["operator", "operator"];
}
},
"#": function(stream) {
if (stream.eat("{")) {
return ["operator", "interpolation"];
} else {
stream.eatWhile(/[\w\\\-]/);
return ["atom", "hash"];
}
}
},
name: "css-base"
});
})();

@@ -1,501 +0,113 @@

// Initiate ModeTest and set defaults
var MT = ModeTest;
MT.modeName = 'css';
MT.modeOptions = {};
(function() {
var mode = CodeMirror.getMode({tabSize: 4}, "css");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
// Requires at least one media query
MT.testMode(
'atMediaEmpty',
'@media { }',
[
'def', '@media',
null, ' ',
'error', '{',
null, ' }'
]
);
// Requires at least one media query
MT("atMediaEmpty",
"[def @media] [error {] }");
MT.testMode(
'atMediaMultiple',
'@media not screen and (color), not print and (color) { }',
[
'def', '@media',
null, ' ',
'keyword', 'not',
null, ' ',
'attribute', 'screen',
null, ' ',
'operator', 'and',
null, ' (',
'property', 'color',
null, '), ',
'keyword', 'not',
null, ' ',
'attribute', 'print',
null, ' ',
'operator', 'and',
null, ' (',
'property', 'color',
null, ') { }'
]
);
MT("atMediaMultiple",
"[def @media] [keyword not] [attribute screen] [operator and] ([property color]), [keyword not] [attribute print] [operator and] ([property color]) { }");
MT.testMode(
'atMediaCheckStack',
'@media screen { } foo { }',
[
'def', '@media',
null, ' ',
'attribute', 'screen',
null, ' { } ',
'tag', 'foo',
null, ' { }'
]
);
MT("atMediaCheckStack",
"[def @media] [attribute screen] { } [tag foo] { }");
MT.testMode(
'atMediaCheckStack',
'@media screen (color) { } foo { }',
[
'def', '@media',
null, ' ',
'attribute', 'screen',
null, ' (',
'property', 'color',
null, ') { } ',
'tag', 'foo',
null, ' { }'
]
);
MT("atMediaCheckStack",
"[def @media] [attribute screen] ([property color]) { } [tag foo] { }");
MT.testMode(
'atMediaCheckStackInvalidAttribute',
'@media foobarhello { } foo { }',
[
'def', '@media',
null, ' ',
'attribute error', 'foobarhello',
null, ' { } ',
'tag', 'foo',
null, ' { }'
]
);
MT("atMediaCheckStackInvalidAttribute",
"[def @media] [attribute&error foobarhello] { } [tag foo] { }");
// Error, because "and" is only allowed immediately preceding a media expression
MT.testMode(
'atMediaInvalidAttribute',
'@media foobarhello { }',
[
'def', '@media',
null, ' ',
'attribute error', 'foobarhello',
null, ' { }'
]
);
// Error, because "and" is only allowed immediately preceding a media expression
MT("atMediaInvalidAttribute",
"[def @media] [attribute&error foobarhello] { }");
// Error, because "and" is only allowed immediately preceding a media expression
MT.testMode(
'atMediaInvalidAnd',
'@media and screen { }',
[
'def', '@media',
null, ' ',
'error', 'and',
null, ' ',
'attribute', 'screen',
null, ' { }'
]
);
// Error, because "and" is only allowed immediately preceding a media expression
MT("atMediaInvalidAnd",
"[def @media] [error and] [attribute screen] { }");
// Error, because "not" is only allowed as the first item in each media query
MT.testMode(
'atMediaInvalidNot',
'@media screen not (not) { }',
[
'def', '@media',
null, ' ',
'attribute', 'screen',
null, ' ',
'error', 'not',
null, ' (',
'error', 'not',
null, ') { }'
]
);
// Error, because "not" is only allowed as the first item in each media query
MT("atMediaInvalidNot",
"[def @media] [attribute screen] [error not] ([error not]) { }");
// Error, because "only" is only allowed as the first item in each media query
MT.testMode(
'atMediaInvalidOnly',
'@media screen only (only) { }',
[
'def', '@media',
null, ' ',
'attribute', 'screen',
null, ' ',
'error', 'only',
null, ' (',
'error', 'only',
null, ') { }'
]
);
// Error, because "only" is only allowed as the first item in each media query
MT("atMediaInvalidOnly",
"[def @media] [attribute screen] [error only] ([error only]) { }");
// Error, because "foobarhello" is neither a known type or property, but
// property was expected (after "and"), and it should be in parenthese.
MT.testMode(
'atMediaUnknownType',
'@media screen and foobarhello { }',
[
'def', '@media',
null, ' ',
'attribute', 'screen',
null, ' ',
'operator', 'and',
null, ' ',
'error', 'foobarhello',
null, ' { }'
]
);
// Error, because "foobarhello" is neither a known type or property, but
// property was expected (after "and"), and it should be in parenthese.
MT("atMediaUnknownType",
"[def @media] [attribute screen] [operator and] [error foobarhello] { }");
// Error, because "color" is not a known type, but is a known property, and
// should be in parentheses.
MT.testMode(
'atMediaInvalidType',
'@media screen and color { }',
[
'def', '@media',
null, ' ',
'attribute', 'screen',
null, ' ',
'operator', 'and',
null, ' ',
'error', 'color',
null, ' { }'
]
);
// Error, because "color" is not a known type, but is a known property, and
// should be in parentheses.
MT("atMediaInvalidType",
"[def @media] [attribute screen] [operator and] [error color] { }");
// Error, because "print" is not a known property, but is a known type,
// and should not be in parenthese.
MT.testMode(
'atMediaInvalidProperty',
'@media screen and (print) { }',
[
'def', '@media',
null, ' ',
'attribute', 'screen',
null, ' ',
'operator', 'and',
null, ' (',
'error', 'print',
null, ') { }'
]
);
// Error, because "print" is not a known property, but is a known type,
// and should not be in parenthese.
MT("atMediaInvalidProperty",
"[def @media] [attribute screen] [operator and] ([error print]) { }");
// Soft error, because "foobarhello" is not a known property or type.
MT.testMode(
'atMediaUnknownProperty',
'@media screen and (foobarhello) { }',
[
'def', '@media',
null, ' ',
'attribute', 'screen',
null, ' ',
'operator', 'and',
null, ' (',
'property error', 'foobarhello',
null, ') { }'
]
);
// Soft error, because "foobarhello" is not a known property or type.
MT("atMediaUnknownProperty",
"[def @media] [attribute screen] [operator and] ([property&error foobarhello]) { }");
MT.testMode(
'tagSelector',
'foo { }',
[
'tag', 'foo',
null, ' { }'
]
);
MT("tagSelector",
"[tag foo] { }");
MT.testMode(
'classSelector',
'.foo { }',
[
'qualifier', '.foo',
null, ' { }'
]
);
MT("classSelector",
"[qualifier .foo-bar_hello] { }");
MT.testMode(
'idSelector',
'#foo { #foo }',
[
'builtin', '#foo',
null, ' { ',
'error', '#foo',
null, ' }'
]
);
MT("idSelector",
"[builtin #foo] { [error #foo] }");
MT.testMode(
'tagSelectorUnclosed',
'foo { margin: 0 } bar { }',
[
'tag', 'foo',
null, ' { ',
'property', 'margin',
'operator', ':',
null, ' ',
'number', '0',
null, ' } ',
'tag', 'bar',
null, ' { }'
]
);
MT("tagSelectorUnclosed",
"[tag foo] { [property margin][operator :] [number 0] } [tag bar] { }");
MT.testMode(
'tagStringNoQuotes',
'foo { font-family: hello world; }',
[
'tag', 'foo',
null, ' { ',
'property', 'font-family',
'operator', ':',
null, ' ',
'variable-2', 'hello',
null, ' ',
'variable-2', 'world',
null, '; }'
]
);
MT("tagStringNoQuotes",
"[tag foo] { [property font-family][operator :] [variable-2 hello] [variable-2 world]; }");
MT.testMode(
'tagStringDouble',
'foo { font-family: "hello world"; }',
[
'tag', 'foo',
null, ' { ',
'property', 'font-family',
'operator', ':',
null, ' ',
'string', '"hello world"',
null, '; }'
]
);
MT("tagStringDouble",
"[tag foo] { [property font-family][operator :] [string \"hello world\"]; }");
MT.testMode(
'tagStringSingle',
'foo { font-family: \'hello world\'; }',
[
'tag', 'foo',
null, ' { ',
'property', 'font-family',
'operator', ':',
null, ' ',
'string', '\'hello world\'',
null, '; }'
]
);
MT("tagStringSingle",
"[tag foo] { [property font-family][operator :] [string 'hello world']; }");
MT.testMode(
'tagColorKeyword',
'foo { color: black; }',
[
'tag', 'foo',
null, ' { ',
'property', 'color',
'operator', ':',
null, ' ',
'keyword', 'black',
null, '; }'
]
);
MT("tagColorKeyword",
"[tag foo] {" +
"[property color][operator :] [keyword black];" +
"[property color][operator :] [keyword navy];" +
"[property color][operator :] [keyword yellow];" +
"}");
MT.testMode(
'tagColorHex3',
'foo { background: #fff; }',
[
'tag', 'foo',
null, ' { ',
'property', 'background',
'operator', ':',
null, ' ',
'atom', '#fff',
null, '; }'
]
);
MT("tagColorHex3",
"[tag foo] { [property background][operator :] [atom #fff]; }");
MT.testMode(
'tagColorHex6',
'foo { background: #ffffff; }',
[
'tag', 'foo',
null, ' { ',
'property', 'background',
'operator', ':',
null, ' ',
'atom', '#ffffff',
null, '; }'
]
);
MT("tagColorHex6",
"[tag foo] { [property background][operator :] [atom #ffffff]; }");
MT.testMode(
'tagColorHex4',
'foo { background: #ffff; }',
[
'tag', 'foo',
null, ' { ',
'property', 'background',
'operator', ':',
null, ' ',
'atom error', '#ffff',
null, '; }'
]
);
MT("tagColorHex4",
"[tag foo] { [property background][operator :] [atom&error #ffff]; }");
MT.testMode(
'tagColorHexInvalid',
'foo { background: #ffg; }',
[
'tag', 'foo',
null, ' { ',
'property', 'background',
'operator', ':',
null, ' ',
'atom error', '#ffg',
null, '; }'
]
);
MT("tagColorHexInvalid",
"[tag foo] { [property background][operator :] [atom&error #ffg]; }");
MT.testMode(
'tagNegativeNumber',
'foo { margin: -5px; }',
[
'tag', 'foo',
null, ' { ',
'property', 'margin',
'operator', ':',
null, ' ',
'number', '-5px',
null, '; }'
]
);
MT("tagNegativeNumber",
"[tag foo] { [property margin][operator :] [number -5px]; }");
MT.testMode(
'tagPositiveNumber',
'foo { padding: 5px; }',
[
'tag', 'foo',
null, ' { ',
'property', 'padding',
'operator', ':',
null, ' ',
'number', '5px',
null, '; }'
]
);
MT("tagPositiveNumber",
"[tag foo] { [property padding][operator :] [number 5px]; }");
MT.testMode(
'tagVendor',
'foo { -foo-box-sizing: -foo-border-box; }',
[
'tag', 'foo',
null, ' { ',
'meta', '-foo-',
'property', 'box-sizing',
'operator', ':',
null, ' ',
'meta', '-foo-',
'string-2', 'border-box',
null, '; }'
]
);
MT("tagVendor",
"[tag foo] { [meta -foo-][property box-sizing][operator :] [meta -foo-][string-2 border-box]; }");
MT.testMode(
'tagBogusProperty',
'foo { barhelloworld: 0; }',
[
'tag', 'foo',
null, ' { ',
'property error', 'barhelloworld',
'operator', ':',
null, ' ',
'number', '0',
null, '; }'
]
);
MT("tagBogusProperty",
"[tag foo] { [property&error barhelloworld][operator :] [number 0]; }");
MT.testMode(
'tagTwoProperties',
'foo { margin: 0; padding: 0; }',
[
'tag', 'foo',
null, ' { ',
'property', 'margin',
'operator', ':',
null, ' ',
'number', '0',
null, '; ',
'property', 'padding',
'operator', ':',
null, ' ',
'number', '0',
null, '; }'
]
);
//
//MT.testMode(
// 'tagClass',
// '@media only screen and (min-width: 500px), print {foo.bar#hello { color: black !important; background: #f00; margin: -5px; padding: 5px; -foo-box-sizing: border-box; } /* world */}',
// [
// 'def', '@media',
// null, ' ',
// 'keyword', 'only',
// null, ' ',
// 'attribute', 'screen',
// null, ' ',
// 'operator', 'and',
// null, ' ',
// 'bracket', '(',
// 'property', 'min-width',
// 'operator', ':',
// null, ' ',
// 'number', '500px',
// 'bracket', ')',
// null, ', ',
// 'attribute', 'print',
// null, ' {',
// 'tag', 'foo',
// 'qualifier', '.bar',
// 'header', '#hello',
// null, ' { ',
// 'property', 'color',
// 'operator', ':',
// null, ' ',
// 'keyword', 'black',
// null, ' ',
// 'keyword', '!important',
// null, '; ',
// 'property', 'background',
// 'operator', ':',
// null, ' ',
// 'atom', '#f00',
// null, '; ',
// 'property', 'padding',
// 'operator', ':',
// null, ' ',
// 'number', '5px',
// null, '; ',
// 'property', 'margin',
// 'operator', ':',
// null, ' ',
// 'number', '-5px',
// null, '; ',
// 'meta', '-foo-',
// 'property', 'box-sizing',
// 'operator', ':',
// null, ' ',
// 'string-2', 'border-box',
// null, '; } ',
// 'comment', '/* world */',
// null, '}'
// ]
//);
MT("tagTwoProperties",
"[tag foo] { [property margin][operator :] [number 0]; [property padding][operator :] [number 0]; }");
MT("commentSGML",
"[comment <!--comment-->]");
})();
CodeMirror.defineMode("diff", function() {
var TOKEN_NAMES = {
'+': 'tag',
'-': 'string',
'+': 'positive',
'-': 'negative',
'@': 'meta'

@@ -7,0 +7,0 @@ };

@@ -15,13 +15,2 @@ CodeMirror.defineMode("ecl", function(config) {

function tokenAtString(stream, state) {
var next;
while ((next = stream.next()) != null) {
if (next == '"' && !stream.eat('"')) {
state.tokenize = null;
break;
}
}
return "string";
}
var indentUnit = config.indentUnit;

@@ -28,0 +17,0 @@ var keyword = words("abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode");

@@ -12,3 +12,3 @@ // block; "begin", "case", "fun", "if", "receive", "try": closed by "end"

CodeMirror.defineMode("erlang", function(cmCfg, modeCfg) {
CodeMirror.defineMode("erlang", function(cmCfg) {

@@ -15,0 +15,0 @@ function rval(state,stream,type) {

@@ -1,145 +0,96 @@

CodeMirror.defineMode("gfm", function(config, parserConfig) {
var mdMode = CodeMirror.getMode(config, "markdown");
var aliases = {
html: "htmlmixed",
js: "javascript",
json: "application/json",
c: "text/x-csrc",
"c++": "text/x-c++src",
java: "text/x-java",
csharp: "text/x-csharp",
"c#": "text/x-csharp"
};
// make this lazy so that we don't need to load GFM last
var getMode = (function () {
var i, modes = {}, mimes = {}, mime;
var list = CodeMirror.listModes();
for (i = 0; i < list.length; i++) {
modes[list[i]] = list[i];
}
var mimesList = CodeMirror.listMIMEs();
for (i = 0; i < mimesList.length; i++) {
mime = mimesList[i].mime;
mimes[mime] = mimesList[i].mime;
}
for (var a in aliases) {
if (aliases[a] in modes || aliases[a] in mimes)
modes[a] = aliases[a];
}
return function (lang) {
return modes[lang] ? CodeMirror.getMode(config, modes[lang]) : null;
};
}());
function markdown(stream, state) {
// intercept fenced code blocks
if (stream.sol() && stream.match(/^```([\w+#]*)/)) {
// try switching mode
state.localMode = getMode(RegExp.$1);
if (state.localMode)
state.localState = state.localMode.startState();
state.token = local;
return 'code';
}
return mdMode.token(stream, state.mdState);
CodeMirror.defineMode("gfm", function(config) {
var codeDepth = 0;
function blankLine(state) {
state.code = false;
return null;
}
function local(stream, state) {
if (stream.sol() && stream.match(/^```/)) {
state.localMode = state.localState = null;
state.token = markdown;
return 'code';
}
else if (state.localMode) {
return state.localMode.token(stream, state.localState);
} else {
stream.skipToEnd();
return 'code';
}
}
// custom handleText to prevent emphasis in the middle of a word
// and add autolinking
function handleText(stream, mdState) {
var match;
if (stream.match(/^\w+:\/\/\S+/)) {
return 'link';
}
if (stream.match(/^[^\[*\\<>` _][^\[*\\<>` ]*[^\[*\\<>` _]/)) {
return mdMode.getType(mdState);
}
if (match = stream.match(/^[^\[*\\<>` ]+/)) {
var word = match[0];
if (word[0] === '_' && word[word.length-1] === '_') {
stream.backUp(word.length);
return undefined;
}
return mdMode.getType(mdState);
}
if (stream.eatSpace()) {
return null;
}
}
return {
var gfmOverlay = {
startState: function() {
var mdState = mdMode.startState();
mdState.text = handleText;
return {token: markdown, mode: "markdown", mdState: mdState,
localMode: null, localState: null};
return {
code: false,
codeBlock: false,
ateSpace: false
};
},
copyState: function(state) {
return {token: state.token, mode: state.mode, mdState: CodeMirror.copyState(mdMode, state.mdState),
localMode: state.localMode,
localState: state.localMode ? CodeMirror.copyState(state.localMode, state.localState) : null};
copyState: function(s) {
return {
code: s.code,
codeBlock: s.codeBlock,
ateSpace: s.ateSpace
};
},
token: function(stream, state) {
/* Parse GFM double bracket links */
var ch;
if ((ch = stream.peek()) != undefined && ch == '[') {
stream.next(); // Advance the stream
/* Only handle double bracket links */
if ((ch = stream.peek()) == undefined || ch != '[') {
stream.backUp(1);
return state.token(stream, state);
}
while ((ch = stream.next()) != undefined && ch != ']') {}
if (ch == ']' && (ch = stream.next()) != undefined && ch == ']')
return 'link';
/* If we did not find the second ']' */
stream.backUp(1);
// Hack to prevent formatting override inside code blocks (block and inline)
if (state.codeBlock) {
if (stream.match(/^```/)) {
state.codeBlock = false;
return null;
}
/* Match GFM latex formulas, as well as latex formulas within '$' */
if (stream.match(/^\$[^\$]+\$/)) {
return "string";
stream.skipToEnd();
return null;
}
if (stream.sol()) {
state.code = false;
}
if (stream.sol() && stream.match(/^```/)) {
stream.skipToEnd();
state.codeBlock = true;
return null;
}
// If this block is changed, it may need to be updated in Markdown mode
if (stream.peek() === '`') {
stream.next();
var before = stream.pos;
stream.eatWhile('`');
var difference = 1 + stream.pos - before;
if (!state.code) {
codeDepth = difference;
state.code = true;
} else {
if (difference === codeDepth) { // Must be exact
state.code = false;
}
}
if (stream.match(/^\\\((.*?)\\\)/)) {
return "string";
return null;
} else if (state.code) {
stream.next();
return null;
}
// Check if space. If so, links can be formatted later on
if (stream.eatSpace()) {
state.ateSpace = true;
return null;
}
if (stream.sol() || state.ateSpace) {
state.ateSpace = false;
if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
// User/Project@SHA
// User@SHA
// SHA
return "link";
} else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
// User/Project#Num
// User#Num
// #Num
return "link";
}
if (stream.match(/^\$\$[^\$]+\$\$/)) {
return "string";
}
if (stream.match(/^\\\[(.*?)\\\]/)) {
return "string";
}
return state.token(stream, state);
}
}
if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i)) {
// URLs
// Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
// And then (issue #1160) simplified to make it not crash the Chrome Regexp engine
return "link";
}
stream.next();
return null;
},
blankLine: blankLine
};
CodeMirror.defineMIME("gfmBase", {
name: "markdown",
underscoresBreakWords: false,
taskLists: true,
fencedCodeBlocks: true
});
return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);
}, "markdown");

@@ -1,2 +0,2 @@

CodeMirror.defineMode("go", function(config, parserConfig) {
CodeMirror.defineMode("go", function(config) {
var indentUnit = config.indentUnit;

@@ -23,7 +23,2 @@

var blockKeywords = {
"else":true, "for":true, "func":true, "if":true, "interface":true,
"select":true, "struct":true, "switch":true
};
var isOperatorChar = /[+\-*&^%:=<>!|\/]/;

@@ -30,0 +25,0 @@

@@ -1,2 +0,2 @@

CodeMirror.defineMode("groovy", function(config, parserConfig) {
CodeMirror.defineMode("groovy", function(config) {
function words(str) {

@@ -3,0 +3,0 @@ var obj = {}, words = str.split(" ");

@@ -1,2 +0,2 @@

CodeMirror.defineMode("haskell", function(cmCfg, modeCfg) {
CodeMirror.defineMode("haskell", function() {

@@ -3,0 +3,0 @@ function switchState(source, setState, f) {

@@ -238,3 +238,3 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {

function expect(wanted) {
return function expecting(type) {
return function(type) {
if (type == wanted) return cont();

@@ -292,3 +292,3 @@ else if (wanted == ";") return pass();

function maybeattribute(type, value) {
function maybeattribute(type) {
if (type == "attribute") return cont(maybeattribute);

@@ -299,3 +299,3 @@ if (type == "function") return cont(functiondef);

function metadef(type, value) {
function metadef(type) {
if(type == ":") return cont(metadef);

@@ -305,4 +305,4 @@ if(type == "variable") return cont(metadef);

}
function metaargs(type, value) {
if(typ == "variable") return cont();
function metaargs(type) {
if(type == "variable") return cont();
}

@@ -337,3 +337,3 @@

}
return function commaSeparated(type) {
return function(type) {
if (type == end) return cont();

@@ -361,3 +361,3 @@ else return pass(what, proceed);

}
function forin(type, value) {
function forin(_type, value) {
if (value == "in") return cont();

@@ -370,12 +370,12 @@ }

}
function typeuse(type, value) {
if(type == ":") return cont(typestring);
function typeuse(type) {
if(type == ":") return cont(typestring);
}
function typestring(type, value) {
if(type == "type") return cont();
if(type == "variable") return cont();
if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex);
function typestring(type) {
if(type == "type") return cont();
if(type == "variable") return cont();
if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex);
}
function typeprop(type, value) {
if(type == "variable") return cont(typeuse);
function typeprop(type) {
if(type == "variable") return cont(typeuse);
}

@@ -382,0 +382,0 @@ function funarg(type, value) {

@@ -37,4 +37,4 @@ CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {

token : parserConfig.startOpen ? scriptingDispatch : htmlDispatch,
htmlState : htmlMixedMode.startState(),
scriptState : scriptingMode.startState()
htmlState : CodeMirror.startState(htmlMixedMode),
scriptState : CodeMirror.startState(scriptingMode)
};

@@ -50,3 +50,3 @@ },

return htmlMixedMode.indent(state.htmlState, textAfter);
else
else if (scriptingMode.indent)
return scriptingMode.indent(state.scriptState, textAfter);

@@ -63,4 +63,8 @@ },

electricChars: "/{}:",
electricChars: "/{}:"
innerMode: function(state) {
if (state.token == scriptingDispatch) return {state: state.scriptState, mode: scriptingMode};
else return {state: state.htmlState, mode: htmlMixedMode};
}
};

@@ -72,1 +76,2 @@ }, "htmlmixed");

CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"});
CodeMirror.defineMIME("application/x-erb", { name: "htmlembedded", scriptingModeSpec:"ruby"});
CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
var jsMode = CodeMirror.getMode(config, "javascript");
var cssMode = CodeMirror.getMode(config, "css");
var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
mode: CodeMirror.getMode(config, "javascript")});
if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
var conf = scriptTypesConf[i];
scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
}
scriptTypes.push({matches: /./,
mode: CodeMirror.getMode(config, "text/plain")});
function html(stream, state) {
var tagName = state.htmlState.tagName;
var style = htmlMode.token(stream, state.htmlState);
if (style == "tag" && stream.current() == ">" && state.htmlState.context) {
if (/^script$/i.test(state.htmlState.context.tagName)) {
state.token = javascript;
state.localState = jsMode.startState(htmlMode.indent(state.htmlState, ""));
state.mode = "javascript";
if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
// Script block: mode to change to depends on type attribute
var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
scriptType = scriptType ? scriptType[1] : "";
if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
for (var i = 0; i < scriptTypes.length; ++i) {
var tp = scriptTypes[i];
if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
if (tp.mode) {
state.token = script;
state.localMode = tp.mode;
state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
}
break;
}
}
else if (/^style$/i.test(state.htmlState.context.tagName)) {
state.token = css;
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
state.mode = "css";
}
} else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
state.token = css;
state.localMode = cssMode;
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
}

@@ -27,3 +46,3 @@ return style;

else if (m = cur.match(/<\/?$/)) {
stream.backUp(cur[0].length);
stream.backUp(cur.length);
if (!stream.match(pat, false)) stream.match(cur[0]);

@@ -33,11 +52,10 @@ }

}
function javascript(stream, state) {
function script(stream, state) {
if (stream.match(/^<\/\s*script\s*>/i, false)) {
state.token = html;
state.localState = null;
state.mode = "html";
state.localState = state.localMode = null;
return html(stream, state);
}
return maybeBackup(stream, /<\/\s*script\s*>/,
jsMode.token(stream, state.localState));
state.localMode.token(stream, state.localState));
}

@@ -47,4 +65,3 @@ function css(stream, state) {

state.token = html;
state.localState = null;
state.mode = "html";
state.localState = state.localMode = null;
return html(stream, state);

@@ -59,3 +76,3 @@ }

var state = htmlMode.startState();
return {token: html, localState: null, mode: "html", htmlState: state};
return {token: html, localMode: null, localState: null, htmlState: state};
},

@@ -65,4 +82,4 @@

if (state.localState)
var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);
return {token: state.token, localState: local, mode: state.mode,
var local = CodeMirror.copyState(state.localMode, state.localState);
return {token: state.token, localMode: state.localMode, localState: local,
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};

@@ -76,11 +93,15 @@ },

indent: function(state, textAfter) {
if (state.token == html || /^\s*<\//.test(textAfter))
if (!state.localMode || /^\s*<\//.test(textAfter))
return htmlMode.indent(state.htmlState, textAfter);
else if (state.token == javascript)
return jsMode.indent(state.localState, textAfter);
else if (state.localMode.indent)
return state.localMode.indent(state.localState, textAfter);
else
return cssMode.indent(state.localState, textAfter);
return CodeMirror.Pass;
},
electricChars: "/{}:"
electricChars: "/{}:",
innerMode: function(state) {
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
}
};

@@ -87,0 +108,0 @@ }, "xml", "javascript", "css");

@@ -0,4 +1,7 @@

// TODO actually recognize syntax of TypeScript constructs
CodeMirror.defineMode("javascript", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var jsonMode = parserConfig.json;
var isTS = parserConfig.typescript;

@@ -11,3 +14,4 @@ // Tokenizer

var operator = kw("operator"), atom = {type: "atom", style: "atom"};
return {
var jsKeywords = {
"if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,

@@ -19,7 +23,37 @@ "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,

"in": operator, "typeof": operator, "instanceof": operator,
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
"this": kw("this")
};
// Extend the 'normal' keywords with the TypeScript language extensions
if (isTS) {
var type = {type: "variable", style: "variable-3"};
var tsKeywords = {
// object-like things
"interface": kw("interface"),
"class": kw("class"),
"extends": kw("extends"),
"constructor": kw("constructor"),
// scope modifiers
"public": kw("public"),
"private": kw("private"),
"protected": kw("protected"),
"static": kw("static"),
"super": kw("super"),
// types
"string": type, "number": type, "bool": type, "any": type
};
for (var attr in tsKeywords) {
jsKeywords[attr] = tsKeywords[attr];
}
}
return jsKeywords;
}();
var isOperatorChar = /[+\-*&%=<>!?|]/;
var isOperatorChar = /[+\-*&%=<>!?|~^]/;

@@ -71,3 +105,4 @@ function chain(stream, state, f) {

}
else if (state.reAllowed) {
else if (state.lastType == "operator" || state.lastType == "keyword c" ||
/^[\[{}\(,;:]$/.test(state.lastType)) {
nextUntilUnescaped(stream, "/");

@@ -83,4 +118,4 @@ stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla

else if (ch == "#") {
stream.skipToEnd();
return ret("error", "error");
stream.skipToEnd();
return ret("error", "error");
}

@@ -94,3 +129,3 @@ else if (isOperatorChar.test(ch)) {

var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
ret("variable", "variable", word);

@@ -122,3 +157,3 @@ }

var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true};

@@ -171,8 +206,15 @@ function JSLexical(indented, column, type, align, prev, info) {

function register(varname) {
function inList(list) {
for (var v = list; v; v = v.next)
if (v.name == varname) return true;
return false;
}
var state = cx.state;
if (state.context) {
cx.marked = "def";
for (var v = state.localVars; v; v = v.next)
if (v.name == varname) return;
if (inList(state.localVars)) return;
state.localVars = {name: varname, next: state.localVars};
} else {
if (inList(state.globalVars)) return;
state.globalVars = {name: varname, next: state.globalVars};
}

@@ -185,4 +227,4 @@ }

function pushcontext() {
if (!cx.state.context) cx.state.localVars = defaultVars;
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
cx.state.localVars = defaultVars;
}

@@ -212,3 +254,3 @@ function popcontext() {

function expect(wanted) {
return function expecting(type) {
return function(type) {
if (type == wanted) return cont();

@@ -254,4 +296,7 @@ else if (wanted == ";") return pass();

function maybeoperator(type, value) {
if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
if (type == "operator" && value == "?") return cont(expression, expect(":"), expression);
if (type == "operator") {
if (/\+\+|--/.test(value)) return cont(maybeoperator);
if (value == "?") return cont(expression, expect(":"), expression);
return cont(expression);
}
if (type == ";") return;

@@ -269,6 +314,17 @@ if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);

}
function objprop(type) {
if (type == "variable") cx.marked = "property";
function objprop(type, value) {
if (type == "variable") {
cx.marked = "property";
if (value == "get" || value == "set") return cont(getterSetter);
} else if (type == "number" || type == "string") {
cx.marked = type + " property";
}
if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
}
function getterSetter(type) {
if (type == ":") return cont(expression);
if (type != "variable") return cont(expect(":"), expression);
cx.marked = "property";
return cont(functiondef);
}
function commasep(what, end) {

@@ -280,3 +336,3 @@ function proceed(type) {

}
return function commaSeparated(type) {
return function(type) {
if (type == end) return cont();

@@ -290,5 +346,16 @@ else return pass(what, proceed);

}
function maybetype(type) {
if (type == ":") return cont(typedef);
return pass();
}
function typedef(type) {
if (type == "variable"){cx.marked = "variable-3"; return cont();}
return pass();
}
function vardef1(type, value) {
if (type == "variable"){register(value); return cont(vardef2);}
return cont();
if (type == "variable") {
register(value);
return isTS ? cont(maybetype, vardef2) : cont(vardef2);
}
return pass();
}

@@ -300,8 +367,8 @@ function vardef2(type, value) {

function forspec1(type) {
if (type == "var") return cont(vardef1, forspec2);
if (type == ";") return pass(forspec2);
if (type == "var") return cont(vardef1, expect(";"), forspec2);
if (type == ";") return cont(forspec2);
if (type == "variable") return cont(formaybein);
return pass(forspec2);
return cont(forspec2);
}
function formaybein(type, value) {
function formaybein(_type, value) {
if (value == "in") return cont(expression);

@@ -323,3 +390,3 @@ return cont(maybeoperator, forspec2);

function funarg(type, value) {
if (type == "variable") {register(value); return cont();}
if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();}
}

@@ -333,7 +400,7 @@

tokenize: jsTokenBase,
reAllowed: true,
kwAllowed: true,
lastType: null,
cc: [],
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: parserConfig.localVars,
globalVars: parserConfig.globalVars,
context: parserConfig.localVars && {vars: parserConfig.localVars},

@@ -353,4 +420,3 @@ indented: 0

if (type == "comment") return style;
state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
state.kwAllowed = type != '.';
state.lastType = type;
return parseJS(state, style, type, content, stream);

@@ -360,2 +426,3 @@ },

indent: function(state, textAfter) {
if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
if (state.tokenize != jsTokenBase) return 0;

@@ -365,5 +432,7 @@ var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;

var type = lexical.type, closing = firstChar == type;
if (type == "vardef") return lexical.indented + 4;
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0);
else if (type == "form" && firstChar == "{") return lexical.indented;
else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
else if (type == "form") return lexical.indented + indentUnit;
else if (type == "stat")
return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? indentUnit : 0);
else if (lexical.info == "switch" && !closing)

@@ -375,3 +444,5 @@ return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);

electricChars: ":{}"
electricChars: ":{}",
jsonMode: jsonMode
};

@@ -381,2 +452,7 @@ });

CodeMirror.defineMIME("text/javascript", "javascript");
CodeMirror.defineMIME("text/ecmascript", "javascript");
CodeMirror.defineMIME("application/javascript", "javascript");
CodeMirror.defineMIME("application/ecmascript", "javascript");
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });

@@ -1,2 +0,2 @@

CodeMirror.defineMode("jinja2", function(config, parserConf) {
CodeMirror.defineMode("jinja2", function() {
var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",

@@ -3,0 +3,0 @@ "loop", "none", "self", "super", "if", "as", "not", "and",

@@ -67,3 +67,3 @@ // LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's

if (ch == "-" && stream.eat("-")) {
if (stream.eat("["))
if (stream.eat("[") && stream.eat("["))
return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state);

@@ -70,0 +70,0 @@ stream.skipToEnd();

@@ -5,12 +5,63 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {

var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? "text/html" : "text/plain");
var aliases = {
html: "htmlmixed",
js: "javascript",
json: "application/json",
c: "text/x-csrc",
"c++": "text/x-c++src",
java: "text/x-java",
csharp: "text/x-csharp",
"c#": "text/x-csharp",
scala: "text/x-scala"
};
var getMode = (function () {
var i, modes = {}, mimes = {}, mime;
var list = [];
for (var m in CodeMirror.modes)
if (CodeMirror.modes.propertyIsEnumerable(m)) list.push(m);
for (i = 0; i < list.length; i++) {
modes[list[i]] = list[i];
}
var mimesList = [];
for (var m in CodeMirror.mimeModes)
if (CodeMirror.mimeModes.propertyIsEnumerable(m))
mimesList.push({mime: m, mode: CodeMirror.mimeModes[m]});
for (i = 0; i < mimesList.length; i++) {
mime = mimesList[i].mime;
mimes[mime] = mimesList[i].mime;
}
for (var a in aliases) {
if (aliases[a] in modes || aliases[a] in mimes)
modes[a] = aliases[a];
}
return function (lang) {
return modes[lang] ? CodeMirror.getMode(cmCfg, modes[lang]) : null;
};
}());
// Should underscores in words open/close em/strong?
if (modeCfg.underscoresBreakWords === undefined)
modeCfg.underscoresBreakWords = true;
// Turn on fenced code blocks? ("```" to start/end)
if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
// Turn on task lists? ("- [ ] " and "- [x] ")
if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
var codeDepth = 0;
var prevLineHasContent = false
, thisLineHasContent = false;
var header = 'header'
, code = 'comment'
, quote = 'quote'
, list = 'string'
, quote1 = 'atom'
, quote2 = 'number'
, list1 = 'variable-2'
, list2 = 'variable-3'
, list3 = 'keyword'
, hr = 'hr'
, image = 'tag'
, linkinline = 'link'

@@ -21,4 +72,3 @@ , linkemail = 'link'

, em = 'em'
, strong = 'strong'
, emstrong = 'emstrong';
, strong = 'strong';

@@ -28,4 +78,5 @@ var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/

, olRE = /^[0-9]+\.\s+/
, taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
, headerRE = /^(?:\={1,}|-{1,})$/
, textRE = /^[^\[*_\\<>` "'(]+/;
, textRE = /^[^!\[\]*_\\<>` "'(]+/;

@@ -48,4 +99,2 @@ function switchInline(stream, state, f) {

state.linkTitle = false;
// Reset CODE state
state.code = false;
// Reset EM state

@@ -56,3 +105,3 @@ state.em = false;

// Reset state.quote
state.quote = false;
state.quote = 0;
if (!htmlFound && state.f == htmlBlock) {

@@ -62,2 +111,4 @@ state.f = inlineNormal;

}
// Mark this line as blank
state.thisLineHasContent = false;
return null;

@@ -67,4 +118,4 @@ }

function blockNormal(stream, state) {
var match;
var prevLineIsList = (state.list !== false);
if (state.list !== false && state.indentationDiff >= 0) { // Continued list

@@ -75,4 +126,8 @@ if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block

state.list = null;
} else { // No longer a list
} else if (state.list !== false && state.indentation > 0) {
state.list = null;
state.listDepth = Math.floor(state.indentation / 4);
} else if (state.list !== false) { // No longer a list
state.list = false;
state.listDepth = 0;
}

@@ -86,7 +141,12 @@

return null;
} else if (stream.peek() === '#' || (prevLineHasContent && stream.match(headerRE)) ) {
} else if (stream.peek() === '#' || (state.prevLineHasContent && stream.match(headerRE)) ) {
state.header = true;
} else if (stream.eat('>')) {
state.indentation++;
state.quote = true;
state.quote = 1;
stream.eatSpace();
while (stream.eat('>')) {
stream.eatSpace();
state.quote++;
}
} else if (stream.peek() === '[') {

@@ -96,5 +156,15 @@ return switchInline(stream, state, footnoteLink);

return hr;
} else if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
} else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, true) || stream.match(olRE, true))) {
state.indentation += 4;
state.list = true;
state.listDepth++;
if (modeCfg.taskLists && stream.match(taskListRE, false)) {
state.taskList = true;
}
} else if (modeCfg.fencedCodeBlocks && stream.match(/^```([\w+#]*)/, true)) {
// try switching mode
state.localMode = getMode(RegExp.$1);
if (state.localMode) state.localState = state.localMode.startState();
switchBlock(stream, state, local);
return code;
}

@@ -119,2 +189,15 @@

function local(stream, state) {
if (stream.sol() && stream.match(/^```/, true)) {
state.localMode = state.localState = null;
state.f = inlineNormal;
state.block = blockNormal;
return code;
} else if (state.localMode) {
return state.localMode.token(stream, state.localState);
} else {
stream.skipToEnd();
return code;
}
}

@@ -125,10 +208,24 @@ // Inline

if (state.strong) { styles.push(state.em ? emstrong : strong); }
else if (state.em) { styles.push(em); }
if (state.taskOpen) { return "meta"; }
if (state.taskClosed) { return "property"; }
if (state.strong) { styles.push(strong); }
if (state.em) { styles.push(em); }
if (state.linkText) { styles.push(linktext); }
if (state.code) { styles.push(code); }
if (state.header) { styles.push(header); }
if (state.quote) { styles.push(quote); }
if (state.list !== false) { styles.push(list); }
if (state.quote) { styles.push(state.quote % 2 ? quote1 : quote2); }
if (state.list !== false) {
var listMod = (state.listDepth - 1) % 3;
if (!listMod) {
styles.push(list1);
} else if (listMod === 1) {
styles.push(list2);
} else {
styles.push(list3);
}
}

@@ -152,5 +249,16 @@ return styles.length ? styles.join(' ') : null;

state.list = null;
return list;
return getType(state);
}
if (state.taskList) {
var taskOpen = stream.match(taskListRE, true)[1] !== "x";
if (taskOpen) state.taskOpen = true;
else state.taskClosed = true;
state.taskList = false;
return getType(state);
}
state.taskOpen = false;
state.taskClosed = false;
var ch = stream.next();

@@ -177,2 +285,3 @@

// If this block is changed, it may need to be updated in GFM mode
if (ch === '`') {

@@ -198,5 +307,19 @@ var t = getType(state);

if (ch === '[' && stream.match(/.*\] ?(?:\(|\[)/, false)) {
return switchInline(stream, state, linkText);
if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
stream.match(/\[[^\]]*\]/);
state.inline = state.f = linkHref;
return image;
}
if (ch === '[' && stream.match(/.*\](\(| ?\[)/, false)) {
state.linkText = true;
return getType(state);
}
if (ch === ']' && state.linkText) {
var type = getType(state);
state.linkText = false;
state.inline = state.f = linkHref;
return type;
}

@@ -212,3 +335,2 @@ if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, true)) {

if (ch === '<' && stream.match(/^\w/, false)) {
var md_inside = false;
if (stream.string.indexOf(">")!=-1) {

@@ -229,4 +351,16 @@ var atts = stream.string.substring(1,stream.string.indexOf(">"));

var ignoreUnderscore = false;
if (!modeCfg.underscoresBreakWords) {
if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
var prevPos = stream.pos - 2;
if (prevPos >= 0) {
var prevCh = stream.string.charAt(prevPos);
if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
ignoreUnderscore = true;
}
}
}
}
var t = getType(state);
if (ch === '*' || ch === '_') {
if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
if (state.strong === ch && stream.eat(ch)) { // Remove STRONG

@@ -258,14 +392,2 @@ state.strong = false;

function linkText(stream, state) {
while (!stream.eol()) {
var ch = stream.next();
if (ch === '\\') stream.next();
if (ch === ']') {
state.inline = state.f = linkHref;
return linktext;
}
}
return linktext;
}
function linkHref(stream, state) {

@@ -308,4 +430,5 @@ // Check if space, and return NULL if so (to avoid marking the space)

var savedInlineRE = [];
function inlineRE(endChar) {
if (!inlineRE[endChar]) {
if (!savedInlineRE[endChar]) {
// Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)

@@ -315,5 +438,5 @@ endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");

// endChar.
inlineRE[endChar] = new RegExp('^(?:[^\\\\]+?|\\\\.)*?(' + endChar + ')');
savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')');
}
return inlineRE[endChar];
return savedInlineRE[endChar];
}

@@ -335,2 +458,5 @@

prevLineHasContent: false,
thisLineHasContent: false,
block: blockNormal,

@@ -342,2 +468,4 @@ htmlState: CodeMirror.startState(htmlMode),

text: handleText,
linkText: false,
linkTitle: false,

@@ -347,4 +475,6 @@ em: false,

header: false,
taskList: false,
list: false,
quote: false
listDepth: 0,
quote: 0
};

@@ -357,5 +487,11 @@ },

prevLineHasContent: s.prevLineHasContent,
thisLineHasContent: s.thisLineHasContent,
block: s.block,
htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
indentation: s.indentation,
localMode: s.localMode,
localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,

@@ -368,3 +504,5 @@ inline: s.inline,

header: s.header,
taskList: s.taskList,
list: s.list,
listDepth: s.listDepth,
quote: s.quote,

@@ -378,10 +516,7 @@ md_inside: s.md_inside

if (stream.match(/^\s*$/, true)) {
prevLineHasContent = false;
state.prevLineHasContent = false;
return blankLine(state);
} else {
if(thisLineHasContent){
prevLineHasContent = true;
thisLineHasContent = false;
}
thisLineHasContent = true;
state.prevLineHasContent = state.thisLineHasContent;
state.thisLineHasContent = true;
}

@@ -391,8 +526,17 @@

state.header = false;
// Reset state.taskList
state.taskList = false;
// Reset state.code
state.code = false;
state.f = state.block;
var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length;
state.indentationDiff = indentation - state.indentation;
state.indentation = indentation;
if (indentation > 0) { return null; }
var difference = Math.floor((indentation - state.indentation) / 4) * 4;
if (difference > 4) difference = 4;
var adjustedIndentation = state.indentation + difference;
state.indentationDiff = adjustedIndentation - state.indentation;
state.indentation = adjustedIndentation;
if (indentation > 0) return null;
}

@@ -399,0 +543,0 @@ return state.f(stream, state);

@@ -1,1084 +0,636 @@

// Initiate ModeTest and set defaults
var MT = ModeTest;
MT.modeName = 'markdown';
MT.modeOptions = {};
(function() {
var mode = CodeMirror.getMode({tabSize: 4}, "markdown");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
MT.testMode(
'plainText',
'foo',
[
null, 'foo'
]
);
MT("plainText",
"foo");
// Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)
MT.testMode(
'codeBlocksUsing4Spaces',
' foo',
[
null, ' ',
'comment', 'foo'
]
);
// Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)
MT("codeBlocksUsing4Spaces",
" [comment foo]");
// Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
MT.testMode(
'codeBlocksUsing1Tab',
'\tfoo',
[
null, '\t',
'comment', 'foo'
]
);
// Code blocks using 4 spaces with internal indentation
MT("codeBlocksUsing4SpacesIndentation",
" [comment bar]",
" [comment hello]",
" [comment world]",
" [comment foo]",
"bar");
// Inline code using backticks
MT.testMode(
'inlineCodeUsingBackticks',
'foo `bar`',
[
null, 'foo ',
'comment', '`bar`'
]
);
// Code blocks using 4 spaces with internal indentation
MT("codeBlocksUsing4SpacesIndentation",
" foo",
" [comment bar]",
" [comment hello]",
" [comment world]");
// Unclosed backticks
// Instead of simply marking as CODE, it would be nice to have an
// incomplete flag for CODE, that is styled slightly different.
MT.testMode(
'unclosedBackticks',
'foo `bar',
[
null, 'foo ',
'comment', '`bar'
]
);
// Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
MT("codeBlocksUsing1Tab",
"\t[comment foo]");
// Per documentation: "To include a literal backtick character within a
// code span, you can use multiple backticks as the opening and closing
// delimiters"
MT.testMode(
'doubleBackticks',
'``foo ` bar``',
[
'comment', '``foo ` bar``'
]
);
// Inline code using backticks
MT("inlineCodeUsingBackticks",
"foo [comment `bar`]");
// Tests based on Dingus
// http://daringfireball.net/projects/markdown/dingus
//
// Multiple backticks within an inline code block
MT.testMode(
'consecutiveBackticks',
'`foo```bar`',
[
'comment', '`foo```bar`'
]
);
// Multiple backticks within an inline code block with a second code block
MT.testMode(
'consecutiveBackticks',
'`foo```bar` hello `world`',
[
'comment', '`foo```bar`',
null, ' hello ',
'comment', '`world`'
]
);
// Unclosed with several different groups of backticks
MT.testMode(
'unclosedBackticks',
'``foo ``` bar` hello',
[
'comment', '``foo ``` bar` hello'
]
);
// Closed with several different groups of backticks
MT.testMode(
'closedBackticks',
'``foo ``` bar` hello`` world',
[
'comment', '``foo ``` bar` hello``',
null, ' world'
]
);
// Block code using single backtick (shouldn't work)
MT("blockCodeSingleBacktick",
"[comment `]",
"foo",
"[comment `]");
// atx headers
// http://daringfireball.net/projects/markdown/syntax#header
//
// H1
MT.testMode(
'atxH1',
'# foo',
[
'header', '# foo'
]
);
// H2
MT.testMode(
'atxH2',
'## foo',
[
'header', '## foo'
]
);
// H3
MT.testMode(
'atxH3',
'### foo',
[
'header', '### foo'
]
);
// H4
MT.testMode(
'atxH4',
'#### foo',
[
'header', '#### foo'
]
);
// H5
MT.testMode(
'atxH5',
'##### foo',
[
'header', '##### foo'
]
);
// H6
MT.testMode(
'atxH6',
'###### foo',
[
'header', '###### foo'
]
);
// H6 - 7x '#' should still be H6, per Dingus
// http://daringfireball.net/projects/markdown/dingus
MT.testMode(
'atxH6NotH7',
'####### foo',
[
'header', '####### foo'
]
);
// Unclosed backticks
// Instead of simply marking as CODE, it would be nice to have an
// incomplete flag for CODE, that is styled slightly different.
MT("unclosedBackticks",
"foo [comment `bar]");
// Setext headers - H1, H2
// Per documentation, "Any number of underlining =’s or -’s will work."
// http://daringfireball.net/projects/markdown/syntax#header
// Ideally, the text would be marked as `header` as well, but this is
// not really feasible at the moment. So, instead, we're testing against
// what works today, to avoid any regressions.
//
// Check if single underlining = works
MT.testMode(
'setextH1',
'foo\n=',
[
null, 'foo',
'header', '='
]
);
// Check if 3+ ='s work
MT.testMode(
'setextH1',
'foo\n===',
[
null, 'foo',
'header', '==='
]
);
// Check if single underlining - works
MT.testMode(
'setextH2',
'foo\n-',
[
null, 'foo',
'header', '-'
]
);
// Check if 3+ -'s work
MT.testMode(
'setextH2',
'foo\n---',
[
null, 'foo',
'header', '---'
]
);
// Per documentation: "To include a literal backtick character within a
// code span, you can use multiple backticks as the opening and closing
// delimiters"
MT("doubleBackticks",
"[comment ``foo ` bar``]");
// Single-line blockquote with trailing space
MT.testMode(
'blockquoteSpace',
'> foo',
[
'quote', '> foo'
]
);
// Tests based on Dingus
// http://daringfireball.net/projects/markdown/dingus
//
// Multiple backticks within an inline code block
MT("consecutiveBackticks",
"[comment `foo```bar`]");
// Single-line blockquote
MT.testMode(
'blockquoteNoSpace',
'>foo',
[
'quote', '>foo'
]
);
// Multiple backticks within an inline code block with a second code block
MT("consecutiveBackticks",
"[comment `foo```bar`] hello [comment `world`]");
// Single-line blockquote followed by normal paragraph
MT.testMode(
'blockquoteThenParagraph',
'>foo\n\nbar',
[
'quote', '>foo',
null, 'bar'
]
);
// Unclosed with several different groups of backticks
MT("unclosedBackticks",
"[comment ``foo ``` bar` hello]");
// Multi-line blockquote (lazy mode)
MT.testMode(
'multiBlockquoteLazy',
'>foo\nbar',
[
'quote', '>foo',
'quote', 'bar'
]
);
// Closed with several different groups of backticks
MT("closedBackticks",
"[comment ``foo ``` bar` hello``] world");
// Multi-line blockquote followed by normal paragraph (lazy mode)
MT.testMode(
'multiBlockquoteLazyThenParagraph',
'>foo\nbar\n\nhello',
[
'quote', '>foo',
'quote', 'bar',
null, 'hello'
]
);
// atx headers
// http://daringfireball.net/projects/markdown/syntax#header
// Multi-line blockquote (non-lazy mode)
MT.testMode(
'multiBlockquote',
'>foo\n>bar',
[
'quote', '>foo',
'quote', '>bar'
]
);
MT("atxH1",
"[header # foo]");
// Multi-line blockquote followed by normal paragraph (non-lazy mode)
MT.testMode(
'multiBlockquoteThenParagraph',
'>foo\n>bar\n\nhello',
[
'quote', '>foo',
'quote', '>bar',
null, 'hello'
]
);
MT("atxH2",
"[header ## foo]");
// Check list types
MT.testMode(
'listAsterisk',
'* foo\n* bar',
[
'string', '* foo',
'string', '* bar'
]
);
MT.testMode(
'listPlus',
'+ foo\n+ bar',
[
'string', '+ foo',
'string', '+ bar'
]
);
MT.testMode(
'listDash',
'- foo\n- bar',
[
'string', '- foo',
'string', '- bar'
]
);
MT.testMode(
'listNumber',
'1. foo\n2. bar',
[
'string', '1. foo',
'string', '2. bar'
]
);
MT("atxH3",
"[header ### foo]");
// Formatting in lists (*)
MT.testMode(
'listAsteriskFormatting',
'* *foo* bar\n\n* **foo** bar\n\n* ***foo*** bar\n\n* `foo` bar',
[
'string', '* ',
'string em', '*foo*',
'string', ' bar',
'string', '* ',
'string strong', '**foo**',
'string', ' bar',
'string', '* ',
'string strong', '**',
'string emstrong', '*foo**',
'string em', '*',
'string', ' bar',
'string', '* ',
'string comment', '`foo`',
'string', ' bar'
]
);
// Formatting in lists (+)
MT.testMode(
'listPlusFormatting',
'+ *foo* bar\n\n+ **foo** bar\n\n+ ***foo*** bar\n\n+ `foo` bar',
[
'string', '+ ',
'string em', '*foo*',
'string', ' bar',
'string', '+ ',
'string strong', '**foo**',
'string', ' bar',
'string', '+ ',
'string strong', '**',
'string emstrong', '*foo**',
'string em', '*',
'string', ' bar',
'string', '+ ',
'string comment', '`foo`',
'string', ' bar'
]
);
// Formatting in lists (-)
MT.testMode(
'listDashFormatting',
'- *foo* bar\n\n- **foo** bar\n\n- ***foo*** bar\n\n- `foo` bar',
[
'string', '- ',
'string em', '*foo*',
'string', ' bar',
'string', '- ',
'string strong', '**foo**',
'string', ' bar',
'string', '- ',
'string strong', '**',
'string emstrong', '*foo**',
'string em', '*',
'string', ' bar',
'string', '- ',
'string comment', '`foo`',
'string', ' bar'
]
);
// Formatting in lists (1.)
MT.testMode(
'listNumberFormatting',
'1. *foo* bar\n\n2. **foo** bar\n\n3. ***foo*** bar\n\n4. `foo` bar',
[
'string', '1. ',
'string em', '*foo*',
'string', ' bar',
'string', '2. ',
'string strong', '**foo**',
'string', ' bar',
'string', '3. ',
'string strong', '**',
'string emstrong', '*foo**',
'string em', '*',
'string', ' bar',
'string', '4. ',
'string comment', '`foo`',
'string', ' bar'
]
);
MT("atxH4",
"[header #### foo]");
// Paragraph lists
MT.testMode(
'listParagraph',
'* foo\n\n* bar',
[
'string', '* foo',
'string', '* bar'
]
);
MT("atxH5",
"[header ##### foo]");
// Multi-paragraph lists
//
// 4 spaces
MT.testMode(
'listMultiParagraph',
'* foo\n\n* bar\n\n hello',
[
'string', '* foo',
'string', '* bar',
null, ' ',
'string', 'hello'
]
);
// 4 spaces, extra blank lines (should still be list, per Dingus)
MT.testMode(
'listMultiParagraphExtra',
'* foo\n\n* bar\n\n\n hello',
[
'string', '* foo',
'string', '* bar',
null, ' ',
'string', 'hello'
]
);
// 4 spaces, plus 1 space (should still be list, per Dingus)
MT.testMode(
'listMultiParagraphExtraSpace',
'* foo\n\n* bar\n\n hello\n\n world',
[
'string', '* foo',
'string', '* bar',
null, ' ',
'string', 'hello',
null, ' ',
'string', 'world'
]
);
// 1 tab
MT.testMode(
'listTab',
'* foo\n\n* bar\n\n\thello',
[
'string', '* foo',
'string', '* bar',
null, '\t',
'string', 'hello'
]
);
// No indent
MT.testMode(
'listNoIndent',
'* foo\n\n* bar\n\nhello',
[
'string', '* foo',
'string', '* bar',
null, 'hello'
]
);
// Blockquote
MT.testMode(
'blockquote',
'* foo\n\n* bar\n\n > hello',
[
'string', '* foo',
'string', '* bar',
null, ' ',
'string quote', '> hello'
]
);
// Code block
MT.testMode(
'blockquoteCode',
'* foo\n\n* bar\n\n > hello\n\n world',
[
'string', '* foo',
'string', '* bar',
null, ' ',
'comment', '> hello',
null, ' ',
'string', 'world'
]
);
// Code block followed by text
MT.testMode(
'blockquoteCodeText',
'* foo\n\n bar\n\n hello\n\n world',
[
'string', '* foo',
null, ' ',
'string', 'bar',
null, ' ',
'comment', 'hello',
null, ' ',
'string', 'world'
]
);
MT("atxH6",
"[header ###### foo]");
// Nested list
//
// *
MT.testMode(
'listAsteriskNested',
'* foo\n\n * bar',
[
'string', '* foo',
null, ' ',
'string', '* bar'
]
);
// +
MT.testMode(
'listPlusNested',
'+ foo\n\n + bar',
[
'string', '+ foo',
null, ' ',
'string', '+ bar'
]
);
// -
MT.testMode(
'listDashNested',
'- foo\n\n - bar',
[
'string', '- foo',
null, ' ',
'string', '- bar'
]
);
// 1.
MT.testMode(
'listNumberNested',
'1. foo\n\n 2. bar',
[
'string', '1. foo',
null, ' ',
'string', '2. bar'
]
);
// Mixed
MT.testMode(
'listMixed',
'* foo\n\n + bar\n\n - hello\n\n 1. world',
[
'string', '* foo',
null, ' ',
'string', '+ bar',
null, ' ',
'string', '- hello',
null, ' ',
'string', '1. world'
]
);
// Blockquote
MT.testMode(
'listBlockquote',
'* foo\n\n + bar\n\n > hello',
[
'string', '* foo',
null, ' ',
'string', '+ bar',
null, ' ',
'quote string', '> hello'
]
);
// Code
MT.testMode(
'listCode',
'* foo\n\n + bar\n\n hello',
[
'string', '* foo',
null, ' ',
'string', '+ bar',
null, ' ',
'comment', 'hello'
]
);
// Code followed by text
MT.testMode(
'listCodeText',
'* foo\n\n bar\n\nhello',
[
'string', '* foo',
null, ' ',
'comment', 'bar',
null, 'hello'
]
);
// H6 - 7x '#' should still be H6, per Dingus
// http://daringfireball.net/projects/markdown/dingus
MT("atxH6NotH7",
"[header ####### foo]");
// Following tests directly from official Markdown documentation
// http://daringfireball.net/projects/markdown/syntax#hr
MT.testMode(
'hrSpace',
'* * *',
[
'hr', '* * *'
]
);
// Setext headers - H1, H2
// Per documentation, "Any number of underlining =’s or -’s will work."
// http://daringfireball.net/projects/markdown/syntax#header
// Ideally, the text would be marked as `header` as well, but this is
// not really feasible at the moment. So, instead, we're testing against
// what works today, to avoid any regressions.
//
// Check if single underlining = works
MT("setextH1",
"foo",
"[header =]");
MT.testMode(
'hr',
'***',
[
'hr', '***'
]
);
// Check if 3+ ='s work
MT("setextH1",
"foo",
"[header ===]");
MT.testMode(
'hrLong',
'*****',
[
'hr', '*****'
]
);
// Check if single underlining - works
MT("setextH2",
"foo",
"[header -]");
MT.testMode(
'hrSpaceDash',
'- - -',
[
'hr', '- - -'
]
);
// Check if 3+ -'s work
MT("setextH2",
"foo",
"[header ---]");
MT.testMode(
'hrDashLong',
'---------------------------------------',
[
'hr', '---------------------------------------'
]
);
// Single-line blockquote with trailing space
MT("blockquoteSpace",
"[atom > foo]");
// Inline link with title
MT.testMode(
'linkTitle',
'[foo](http://example.com/ "bar") hello',
[
'link', '[foo]',
'string', '(http://example.com/ "bar")',
null, ' hello'
]
);
// Single-line blockquote
MT("blockquoteNoSpace",
"[atom >foo]");
// Inline link without title
MT.testMode(
'linkNoTitle',
'[foo](http://example.com/) bar',
[
'link', '[foo]',
'string', '(http://example.com/)',
null, ' bar'
]
);
// No blank line before blockquote
MT("blockquoteNoBlankLine",
"foo",
"[atom > bar]");
// Reference-style links
MT.testMode(
'linkReference',
'[foo][bar] hello',
[
'link', '[foo]',
'string', '[bar]',
null, ' hello'
]
);
// Nested blockquote
MT("blockquoteSpace",
"[atom > foo]",
"[number > > foo]",
"[atom > > > foo]");
// Reference-style links with optional space separator (per docuentation)
// "You can optionally use a space to separate the sets of brackets"
MT.testMode(
'linkReferenceSpace',
'[foo] [bar] hello',
[
'link', '[foo]',
null, ' ',
'string', '[bar]',
null, ' hello'
]
);
// Should only allow a single space ("...use *a* space...")
MT.testMode(
'linkReferenceDoubleSpace',
'[foo] [bar] hello',
[
null, '[foo] [bar] hello'
]
);
// Single-line blockquote followed by normal paragraph
MT("blockquoteThenParagraph",
"[atom >foo]",
"",
"bar");
// Reference-style links with implicit link name
MT.testMode(
'linkImplicit',
'[foo][] hello',
[
'link', '[foo]',
'string', '[]',
null, ' hello'
]
);
// Multi-line blockquote (lazy mode)
MT("multiBlockquoteLazy",
"[atom >foo]",
"[atom bar]");
// @todo It would be nice if, at some point, the document was actually
// checked to see if the referenced link exists
// Multi-line blockquote followed by normal paragraph (lazy mode)
MT("multiBlockquoteLazyThenParagraph",
"[atom >foo]",
"[atom bar]",
"",
"hello");
// Link label, for reference-style links (taken from documentation)
//
// No title
MT.testMode(
'labelNoTitle',
'[foo]: http://example.com/',
[
'link', '[foo]:',
null, ' ',
'string', 'http://example.com/'
]
);
// Space in ID and title
MT.testMode(
'labelSpaceTitle',
'[foo bar]: http://example.com/ "hello"',
[
'link', '[foo bar]:',
null, ' ',
'string', 'http://example.com/ "hello"'
]
);
// Double title
MT.testMode(
'labelDoubleTitle',
'[foo bar]: http://example.com/ "hello" "world"',
[
'link', '[foo bar]:',
null, ' ',
'string', 'http://example.com/ "hello"',
null, ' "world"'
]
);
// Double quotes around title
MT.testMode(
'labelTitleDoubleQuotes',
'[foo]: http://example.com/ "bar"',
[
'link', '[foo]:',
null, ' ',
'string', 'http://example.com/ "bar"'
]
);
// Single quotes around title
MT.testMode(
'labelTitleSingleQuotes',
'[foo]: http://example.com/ \'bar\'',
[
'link', '[foo]:',
null, ' ',
'string', 'http://example.com/ \'bar\''
]
);
// Parentheses around title
MT.testMode(
'labelTitleParenthese',
'[foo]: http://example.com/ (bar)',
[
'link', '[foo]:',
null, ' ',
'string', 'http://example.com/ (bar)'
]
);
// Invalid title
MT.testMode(
'labelTitleInvalid',
'[foo]: http://example.com/ bar',
[
'link', '[foo]:',
null, ' ',
'string', 'http://example.com/',
null, ' bar'
]
);
// Angle brackets around URL
MT.testMode(
'labelLinkAngleBrackets',
'[foo]: <http://example.com/> "bar"',
[
'link', '[foo]:',
null, ' ',
'string', '<http://example.com/> "bar"'
]
);
// Title on next line per documentation (double quotes)
MT.testMode(
'labelTitleNextDoubleQuotes',
'[foo]: http://example.com/\n"bar" hello',
[
'link', '[foo]:',
null, ' ',
'string', 'http://example.com/',
'string', '"bar"',
null, ' hello'
]
);
// Title on next line per documentation (single quotes)
MT.testMode(
'labelTitleNextSingleQuotes',
'[foo]: http://example.com/\n\'bar\' hello',
[
'link', '[foo]:',
null, ' ',
'string', 'http://example.com/',
'string', '\'bar\'',
null, ' hello'
]
);
// Title on next line per documentation (parentheses)
MT.testMode(
'labelTitleNextParenthese',
'[foo]: http://example.com/\n(bar) hello',
[
'link', '[foo]:',
null, ' ',
'string', 'http://example.com/',
'string', '(bar)',
null, ' hello'
]
);
// Title on next line per documentation (mixed)
MT.testMode(
'labelTitleNextMixed',
'[foo]: http://example.com/\n(bar" hello',
[
'link', '[foo]:',
null, ' ',
'string', 'http://example.com/',
null, '(bar" hello'
]
);
// Multi-line blockquote (non-lazy mode)
MT("multiBlockquote",
"[atom >foo]",
"[atom >bar]");
// Automatic links
MT.testMode(
'linkWeb',
'<http://example.com/> foo',
[
'link', '<http://example.com/>',
null, ' foo'
]
);
// Multi-line blockquote followed by normal paragraph (non-lazy mode)
MT("multiBlockquoteThenParagraph",
"[atom >foo]",
"[atom >bar]",
"",
"hello");
// Automatic email links
MT.testMode(
'linkEmail',
'<user@example.com> foo',
[
'link', '<user@example.com>',
null, ' foo'
]
);
// Check list types
// Single asterisk
MT.testMode(
'emAsterisk',
'*foo* bar',
[
'em', '*foo*',
null, ' bar'
]
);
MT("listAsterisk",
"foo",
"bar",
"",
"[variable-2 * foo]",
"[variable-2 * bar]");
// Single underscore
MT.testMode(
'emUnderscore',
'_foo_ bar',
[
'em', '_foo_',
null, ' bar'
]
);
MT("listPlus",
"foo",
"bar",
"",
"[variable-2 + foo]",
"[variable-2 + bar]");
// Emphasis characters within a word
MT.testMode(
'emInWordAsterisk',
'foo*bar*hello',
[
null, 'foo',
'em', '*bar*',
null, 'hello'
]
);
MT.testMode(
'emInWordUnderscore',
'foo_bar_hello',
[
null, 'foo',
'em', '_bar_',
null, 'hello'
]
);
// Per documentation: "...surround an * or _ with spaces, it’ll be
// treated as a literal asterisk or underscore."
//
// Inside EM
MT.testMode(
'emEscapedBySpaceIn',
'foo _bar _ hello_ world',
[
null, 'foo ',
'em', '_bar _ hello_',
null, ' world'
]
);
// Outside EM
MT.testMode(
'emEscapedBySpaceOut',
'foo _ bar_hello_world',
[
null, 'foo _ bar',
'em', '_hello_',
null, 'world'
]
);
MT("listDash",
"foo",
"bar",
"",
"[variable-2 - foo]",
"[variable-2 - bar]");
// Unclosed emphasis characters
// Instead of simply marking as EM / STRONG, it would be nice to have an
// incomplete flag for EM and STRONG, that is styled slightly different.
MT.testMode(
'emIncompleteAsterisk',
'foo *bar',
[
null, 'foo ',
'em', '*bar'
]
);
MT.testMode(
'emIncompleteUnderscore',
'foo _bar',
[
null, 'foo ',
'em', '_bar'
]
);
MT("listNumber",
"foo",
"bar",
"",
"[variable-2 1. foo]",
"[variable-2 2. bar]");
// Double asterisk
MT.testMode(
'strongAsterisk',
'**foo** bar',
[
'strong', '**foo**',
null, ' bar'
]
);
// Lists require a preceding blank line (per Dingus)
MT("listBogus",
"foo",
"1. bar",
"2. hello");
// Double underscore
MT.testMode(
'strongUnderscore',
'__foo__ bar',
[
'strong', '__foo__',
null, ' bar'
]
);
// Formatting in lists (*)
MT("listAsteriskFormatting",
"[variable-2 * ][variable-2&em *foo*][variable-2 bar]",
"[variable-2 * ][variable-2&strong **foo**][variable-2 bar]",
"[variable-2 * ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
"[variable-2 * ][variable-2&comment `foo`][variable-2 bar]");
// Triple asterisk
MT.testMode(
'emStrongAsterisk',
'*foo**bar*hello** world',
[
'em', '*foo',
'emstrong', '**bar*',
'strong', 'hello**',
null, ' world'
]
);
// Formatting in lists (+)
MT("listPlusFormatting",
"[variable-2 + ][variable-2&em *foo*][variable-2 bar]",
"[variable-2 + ][variable-2&strong **foo**][variable-2 bar]",
"[variable-2 + ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
"[variable-2 + ][variable-2&comment `foo`][variable-2 bar]");
// Triple underscore
MT.testMode(
'emStrongUnderscore',
'_foo__bar_hello__ world',
[
'em', '_foo',
'emstrong', '__bar_',
'strong', 'hello__',
null, ' world'
]
);
// Formatting in lists (-)
MT("listDashFormatting",
"[variable-2 - ][variable-2&em *foo*][variable-2 bar]",
"[variable-2 - ][variable-2&strong **foo**][variable-2 bar]",
"[variable-2 - ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
"[variable-2 - ][variable-2&comment `foo`][variable-2 bar]");
// Triple mixed
// "...same character must be used to open and close an emphasis span.""
MT.testMode(
'emStrongMixed',
'_foo**bar*hello__ world',
[
'em', '_foo',
'emstrong', '**bar*hello__ world'
]
);
// Formatting in lists (1.)
MT("listNumberFormatting",
"[variable-2 1. ][variable-2&em *foo*][variable-2 bar]",
"[variable-2 2. ][variable-2&strong **foo**][variable-2 bar]",
"[variable-2 3. ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
"[variable-2 4. ][variable-2&comment `foo`][variable-2 bar]");
MT.testMode(
'emStrongMixed',
'*foo__bar_hello** world',
[
'em', '*foo',
'emstrong', '__bar_hello** world'
]
);
// Paragraph lists
MT("listParagraph",
"[variable-2 * foo]",
"",
"[variable-2 * bar]");
// These characters should be escaped:
// \ backslash
// ` backtick
// * asterisk
// _ underscore
// {} curly braces
// [] square brackets
// () parentheses
// # hash mark
// + plus sign
// - minus sign (hyphen)
// . dot
// ! exclamation mark
//
// Backtick (code)
MT.testMode(
'escapeBacktick',
'foo \\`bar\\`',
[
null, 'foo \\`bar\\`'
]
);
MT.testMode(
'doubleEscapeBacktick',
'foo \\\\`bar\\\\`',
[
null, 'foo \\\\',
'comment', '`bar\\\\`'
]
);
// Asterisk (em)
MT.testMode(
'escapeAsterisk',
'foo \\*bar\\*',
[
null, 'foo \\*bar\\*'
]
);
MT.testMode(
'doubleEscapeAsterisk',
'foo \\\\*bar\\\\*',
[
null, 'foo \\\\',
'em', '*bar\\\\*'
]
);
// Underscore (em)
MT.testMode(
'escapeUnderscore',
'foo \\_bar\\_',
[
null, 'foo \\_bar\\_'
]
);
MT.testMode(
'doubleEscapeUnderscore',
'foo \\\\_bar\\\\_',
[
null, 'foo \\\\',
'em', '_bar\\\\_'
]
);
// Hash mark (headers)
MT.testMode(
'escapeHash',
'\\# foo',
[
null, '\\# foo'
]
);
MT.testMode(
'doubleEscapeHash',
'\\\\# foo',
[
null, '\\\\# foo'
]
);
// Multi-paragraph lists
//
// 4 spaces
MT("listMultiParagraph",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
" [variable-2 hello]");
// 4 spaces, extra blank lines (should still be list, per Dingus)
MT("listMultiParagraphExtra",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
"",
" [variable-2 hello]");
// 4 spaces, plus 1 space (should still be list, per Dingus)
MT("listMultiParagraphExtraSpace",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
" [variable-2 hello]",
"",
" [variable-2 world]");
// 1 tab
MT("listTab",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
"\t[variable-2 hello]");
// No indent
MT("listNoIndent",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
"hello");
// Blockquote
MT("blockquote",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
" [variable-2&atom > hello]");
// Code block
MT("blockquoteCode",
"[variable-2 * foo]",
"",
"[variable-2 * bar]",
"",
" [comment > hello]",
"",
" [variable-2 world]");
// Code block followed by text
MT("blockquoteCodeText",
"[variable-2 * foo]",
"",
" [variable-2 bar]",
"",
" [comment hello]",
"",
" [variable-2 world]");
// Nested list
MT("listAsteriskNested",
"[variable-2 * foo]",
"",
" [variable-3 * bar]");
MT("listPlusNested",
"[variable-2 + foo]",
"",
" [variable-3 + bar]");
MT("listDashNested",
"[variable-2 - foo]",
"",
" [variable-3 - bar]");
MT("listNumberNested",
"[variable-2 1. foo]",
"",
" [variable-3 2. bar]");
MT("listMixed",
"[variable-2 * foo]",
"",
" [variable-3 + bar]",
"",
" [keyword - hello]",
"",
" [variable-2 1. world]");
MT("listBlockquote",
"[variable-2 * foo]",
"",
" [variable-3 + bar]",
"",
" [atom&variable-3 > hello]");
MT("listCode",
"[variable-2 * foo]",
"",
" [variable-3 + bar]",
"",
" [comment hello]");
// Code with internal indentation
MT("listCodeIndentation",
"[variable-2 * foo]",
"",
" [comment bar]",
" [comment hello]",
" [comment world]",
" [comment foo]",
" [variable-2 bar]");
// List nesting edge cases
MT("listNested",
"[variable-2 * foo]",
"",
" [variable-3 * bar]",
"",
" [variable-2 hello]"
);
MT("listNested",
"[variable-2 * foo]",
"",
" [variable-3 * bar]",
"",
" [variable-3 * foo]"
);
// Code followed by text
MT("listCodeText",
"[variable-2 * foo]",
"",
" [comment bar]",
"",
"hello");
// Following tests directly from official Markdown documentation
// http://daringfireball.net/projects/markdown/syntax#hr
MT("hrSpace",
"[hr * * *]");
MT("hr",
"[hr ***]");
MT("hrLong",
"[hr *****]");
MT("hrSpaceDash",
"[hr - - -]");
MT("hrDashLong",
"[hr ---------------------------------------]");
// Inline link with title
MT("linkTitle",
"[link [[foo]]][string (http://example.com/ \"bar\")] hello");
// Inline link without title
MT("linkNoTitle",
"[link [[foo]]][string (http://example.com/)] bar");
// Inline link with image
MT("linkImage",
"[link [[][tag ![[foo]]][string (http://example.com/)][link ]]][string (http://example.com/)] bar");
// Inline link with Em
MT("linkEm",
"[link [[][link&em *foo*][link ]]][string (http://example.com/)] bar");
// Inline link with Strong
MT("linkStrong",
"[link [[][link&strong **foo**][link ]]][string (http://example.com/)] bar");
// Inline link with EmStrong
MT("linkEmStrong",
"[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string (http://example.com/)] bar");
// Image with title
MT("imageTitle",
"[tag ![[foo]]][string (http://example.com/ \"bar\")] hello");
// Image without title
MT("imageNoTitle",
"[tag ![[foo]]][string (http://example.com/)] bar");
// Image with asterisks
MT("imageAsterisks",
"[tag ![[*foo*]]][string (http://example.com/)] bar");
// Not a link. Should be normal text due to square brackets being used
// regularly in text, especially in quoted material, and no space is allowed
// between square brackets and parentheses (per Dingus).
MT("notALink",
"[[foo]] (bar)");
// Reference-style links
MT("linkReference",
"[link [[foo]]][string [[bar]]] hello");
// Reference-style links with Em
MT("linkReferenceEm",
"[link [[][link&em *foo*][link ]]][string [[bar]]] hello");
// Reference-style links with Strong
MT("linkReferenceStrong",
"[link [[][link&strong **foo**][link ]]][string [[bar]]] hello");
// Reference-style links with EmStrong
MT("linkReferenceEmStrong",
"[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string [[bar]]] hello");
// Reference-style links with optional space separator (per docuentation)
// "You can optionally use a space to separate the sets of brackets"
MT("linkReferenceSpace",
"[link [[foo]]] [string [[bar]]] hello");
// Should only allow a single space ("...use *a* space...")
MT("linkReferenceDoubleSpace",
"[[foo]] [[bar]] hello");
// Reference-style links with implicit link name
MT("linkImplicit",
"[link [[foo]]][string [[]]] hello");
// @todo It would be nice if, at some point, the document was actually
// checked to see if the referenced link exists
// Link label, for reference-style links (taken from documentation)
MT("labelNoTitle",
"[link [[foo]]:] [string http://example.com/]");
MT("labelIndented",
" [link [[foo]]:] [string http://example.com/]");
MT("labelSpaceTitle",
"[link [[foo bar]]:] [string http://example.com/ \"hello\"]");
MT("labelDoubleTitle",
"[link [[foo bar]]:] [string http://example.com/ \"hello\"] \"world\"");
MT("labelTitleDoubleQuotes",
"[link [[foo]]:] [string http://example.com/ \"bar\"]");
MT("labelTitleSingleQuotes",
"[link [[foo]]:] [string http://example.com/ 'bar']");
MT("labelTitleParenthese",
"[link [[foo]]:] [string http://example.com/ (bar)]");
MT("labelTitleInvalid",
"[link [[foo]]:] [string http://example.com/] bar");
MT("labelLinkAngleBrackets",
"[link [[foo]]:] [string <http://example.com/> \"bar\"]");
MT("labelTitleNextDoubleQuotes",
"[link [[foo]]:] [string http://example.com/]",
"[string \"bar\"] hello");
MT("labelTitleNextSingleQuotes",
"[link [[foo]]:] [string http://example.com/]",
"[string 'bar'] hello");
MT("labelTitleNextParenthese",
"[link [[foo]]:] [string http://example.com/]",
"[string (bar)] hello");
MT("labelTitleNextMixed",
"[link [[foo]]:] [string http://example.com/]",
"(bar\" hello");
MT("linkWeb",
"[link <http://example.com/>] foo");
MT("linkEmail",
"[link <user@example.com>] foo");
MT("emAsterisk",
"[em *foo*] bar");
MT("emUnderscore",
"[em _foo_] bar");
MT("emInWordAsterisk",
"foo[em *bar*]hello");
MT("emInWordUnderscore",
"foo[em _bar_]hello");
// Per documentation: "...surround an * or _ with spaces, it’ll be
// treated as a literal asterisk or underscore."
MT("emEscapedBySpaceIn",
"foo [em _bar _ hello_] world");
MT("emEscapedBySpaceOut",
"foo _ bar[em _hello_]world");
// Unclosed emphasis characters
// Instead of simply marking as EM / STRONG, it would be nice to have an
// incomplete flag for EM and STRONG, that is styled slightly different.
MT("emIncompleteAsterisk",
"foo [em *bar]");
MT("emIncompleteUnderscore",
"foo [em _bar]");
MT("strongAsterisk",
"[strong **foo**] bar");
MT("strongUnderscore",
"[strong __foo__] bar");
MT("emStrongAsterisk",
"[em *foo][em&strong **bar*][strong hello**] world");
MT("emStrongUnderscore",
"[em _foo][em&strong __bar_][strong hello__] world");
// "...same character must be used to open and close an emphasis span.""
MT("emStrongMixed",
"[em _foo][em&strong **bar*hello__ world]");
MT("emStrongMixed",
"[em *foo][em&strong __bar_hello** world]");
// These characters should be escaped:
// \ backslash
// ` backtick
// * asterisk
// _ underscore
// {} curly braces
// [] square brackets
// () parentheses
// # hash mark
// + plus sign
// - minus sign (hyphen)
// . dot
// ! exclamation mark
MT("escapeBacktick",
"foo \\`bar\\`");
MT("doubleEscapeBacktick",
"foo \\\\[comment `bar\\\\`]");
MT("escapeAsterisk",
"foo \\*bar\\*");
MT("doubleEscapeAsterisk",
"foo \\\\[em *bar\\\\*]");
MT("escapeUnderscore",
"foo \\_bar\\_");
MT("doubleEscapeUnderscore",
"foo \\\\[em _bar\\\\_]");
MT("escapeHash",
"\\# foo");
MT("doubleEscapeHash",
"\\\\# foo");
// Tests to make sure GFM-specific things aren't getting through
MT("taskList",
"[variable-2 * [ ]] bar]");
MT("fencedCodeBlocks",
"[comment ```]",
"foo",
"[comment ```]");
})();

@@ -90,4 +90,2 @@ /**********************************************************

var untilSpace = function(c) { return c != ' '; };
var untilEndURI = function(c) { return c != '>'; };
return {

@@ -94,0 +92,0 @@ startState: function() {

@@ -1,2 +0,2 @@

CodeMirror.defineMode('ocaml', function(config) {
CodeMirror.defineMode('ocaml', function() {

@@ -40,3 +40,2 @@ var words = {

function tokenBase(stream, state) {
var sol = stream.sol();
var ch = stream.next();

@@ -43,0 +42,0 @@

@@ -1,2 +0,2 @@

CodeMirror.defineMode("pascal", function(config) {
CodeMirror.defineMode("pascal", function() {
function words(str) {

@@ -79,3 +79,3 @@ var obj = {}, words = str.split(" ");

return {
startState: function(basecolumn) {
startState: function() {
return {tokenize: null};

@@ -82,0 +82,0 @@ },

// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)
// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)
CodeMirror.defineMode("perl",function(config,parserConfig){
CodeMirror.defineMode("perl",function(){
// http://perldoc.perl.org

@@ -5,0 +5,0 @@ var PERL={ // null - magic touch

@@ -23,6 +23,7 @@ (function() {

blockKeywords: keywords("catch do else elseif for foreach if switch try while"),
atoms: keywords("true false null TRUE FALSE NULL"),
atoms: keywords("true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__"),
builtin: keywords("func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport echo print global static exit array empty eval isset unset die include require include_once require_once"),
multiLineStrings: true,
hooks: {
"$": function(stream, state) {
"$": function(stream) {
stream.eatWhile(/[\w\$_]/);

@@ -39,7 +40,7 @@ return "variable-2";

},
"#": function(stream, state) {
"#": function(stream) {
while (!stream.eol() && !stream.match("?>", false)) stream.next();
return "comment";
},
"/": function(stream, state) {
"/": function(stream) {
if (stream.eat("/")) {

@@ -55,16 +56,12 @@ while (!stream.eol() && !stream.match("?>", false)) stream.next();

CodeMirror.defineMode("php", function(config, parserConfig) {
var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
var jsMode = CodeMirror.getMode(config, "javascript");
var cssMode = CodeMirror.getMode(config, "css");
var htmlMode = CodeMirror.getMode(config, "text/html");
var phpMode = CodeMirror.getMode(config, phpConfig);
function dispatch(stream, state) { // TODO open PHP inside text/css
var isPHP = state.mode == "php";
function dispatch(stream, state) {
var isPHP = state.curMode == phpMode;
if (stream.sol() && state.pending != '"') state.pending = null;
if (state.curMode == htmlMode) {
if (!isPHP) {
if (stream.match(/^<\?\w*/)) {
state.curMode = phpMode;
state.curState = state.php;
state.curClose = "?>";
state.mode = "php";
return "meta";

@@ -87,27 +84,10 @@ }

stream.backUp(cur.length - openPHP);
} else if (style == "tag" && stream.current() == ">" && state.curState.context) {
if (/^script$/i.test(state.curState.context.tagName)) {
state.curMode = jsMode;
state.curState = jsMode.startState(htmlMode.indent(state.curState, ""));
state.curClose = /^<\/\s*script\s*>/i;
state.mode = "javascript";
}
else if (/^style$/i.test(state.curState.context.tagName)) {
state.curMode = cssMode;
state.curState = cssMode.startState(htmlMode.indent(state.curState, ""));
state.curClose = /^<\/\s*style\s*>/i;
state.mode = "css";
}
}
return style;
} else if ((!isPHP || state.php.tokenize == null) &&
stream.match(state.curClose, isPHP)) {
} else if (isPHP && state.php.tokenize == null && stream.match("?>")) {
state.curMode = htmlMode;
state.curState = state.html;
state.curClose = null;
state.mode = "html";
if (isPHP) return "meta";
else return dispatch(stream, state);
return "meta";
} else {
return state.curMode.token(stream, state.curState);
return phpMode.token(stream, state.curState);
}

@@ -118,9 +98,7 @@ }

startState: function() {
var html = htmlMode.startState();
var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode);
return {html: html,
php: phpMode.startState(),
php: php,
curMode: parserConfig.startOpen ? phpMode : htmlMode,
curState: parserConfig.startOpen ? phpMode.startState() : html,
curClose: parserConfig.startOpen ? /^\?>/ : null,
mode: parserConfig.startOpen ? "php" : "html",
curState: parserConfig.startOpen ? php : html,
pending: null};

@@ -132,7 +110,5 @@ },

php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
if (state.curState == html) cur = htmlNew;
else if (state.curState == php) cur = phpNew;
else cur = CodeMirror.copyState(state.curMode, state.curState);
if (state.curMode == htmlMode) cur = htmlNew;
else cur = phpNew;
return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
curClose: state.curClose, mode: state.mode,
pending: state.pending};

@@ -150,5 +126,8 @@ },

electricChars: "/{}:"
electricChars: "/{}:",
innerMode: function(state) { return {state: state.curState, mode: state.curMode}; }
};
}, "xml", "clike", "javascript", "css");
}, "htmlmixed", "clike");
CodeMirror.defineMIME("application/x-httpd-php", "php");

@@ -155,0 +134,0 @@ CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});

@@ -7,5 +7,4 @@ /*

*/
CodeMirror.defineMode("pig", function(config, parserConfig) {
var indentUnit = config.indentUnit,
keywords = parserConfig.keywords,
CodeMirror.defineMode("pig", function(_config, parserConfig) {
var keywords = parserConfig.keywords,
builtins = parserConfig.builtins,

@@ -123,3 +122,3 @@ types = parserConfig.types,

return {
startState: function(basecolumn) {
startState: function() {
return {

@@ -126,0 +125,0 @@ tokenize: tokenBase,

CodeMirror.defineMode("python", function(conf, parserConf) {
var ERRORCLASS = 'error';
function wordRegexp(words) {

@@ -8,8 +8,8 @@ return new RegExp("^((" + words.join(")|(") + "))\\b");

var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
var singleDelimiters = parserConf.singleDelimiters || new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");

@@ -164,3 +164,3 @@ var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']);

return function tokenString(stream, state) {
function tokenString(stream, state) {
while (!stream.eol()) {

@@ -188,3 +188,5 @@ stream.eatWhile(/[^'"\\]/);

return OUTCLASS;
};
}
tokenString.isString = true;
return tokenString;
}

@@ -329,5 +331,5 @@

indent: function(state, textAfter) {
indent: function(state) {
if (state.tokenize != tokenBase) {
return 0;
return state.tokenize.isString ? CodeMirror.Pass : 0;
}

@@ -334,0 +336,0 @@

@@ -98,3 +98,3 @@ CodeMirror.defineMode("r", function(config) {

return {
startState: function(base) {
startState: function() {
return {tokenize: tokenBase,

@@ -101,0 +101,0 @@ ctx: {type: "top",

@@ -1,2 +0,2 @@

CodeMirror.defineMode("changes", function(config, modeConfig) {
CodeMirror.defineMode("changes", function() {
var headerSeperator = /^-+$/;

@@ -3,0 +3,0 @@ var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /;

// Quick and dirty spec file highlighting
CodeMirror.defineMode("spec", function(config, modeConfig) {
CodeMirror.defineMode("spec", function() {
var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;

@@ -5,0 +5,0 @@

@@ -1,326 +0,550 @@

CodeMirror.defineMode('rst', function(config, options) {
function setState(state, fn, ctx) {
state.fn = fn;
setCtx(state, ctx);
CodeMirror.defineMode('rst-base', function (config) {
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
function format(string) {
var args = Array.prototype.slice.call(arguments, 1);
return string.replace(/{(\d+)}/g, function (match, n) {
return typeof args[n] != 'undefined' ? args[n] : match;
});
}
function setCtx(state, ctx) {
state.ctx = ctx || {};
function AssertException(message) {
this.message = message;
}
function setNormal(state, ch) {
if (ch && (typeof ch !== 'string')) {
var str = ch.current();
ch = str[str.length-1];
}
AssertException.prototype.toString = function () {
return 'AssertException: ' + this.message;
};
setState(state, normal, {back: ch});
function assert(expression, message) {
if (!expression) throw new AssertException(message);
return expression;
}
function hasMode(mode) {
if (mode) {
var modes = CodeMirror.listModes();
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
for (var i in modes) {
if (modes[i] == mode) {
return true;
}
}
}
var mode_python = CodeMirror.getMode(config, 'python');
var mode_stex = CodeMirror.getMode(config, 'stex');
return false;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
function getMode(mode) {
if (hasMode(mode)) {
return CodeMirror.getMode(config, mode);
} else {
return null;
}
}
var SEPA = "\\s+";
var TAIL = "(?:\\s*|\\W|$)",
rx_TAIL = new RegExp(format('^{0}', TAIL));
var verbatimMode = getMode(options.verbatim);
var pythonMode = getMode('python');
var NAME = "(?:[^\\W\\d_](?:[\\w\\+\\.\\-:]*[^\\W_])?)",
rx_NAME = new RegExp(format('^{0}', NAME));
var NAME_WWS = "(?:[^\\W\\d_](?:[\\w\\s\\+\\.\\-:]*[^\\W_])?)";
var REF_NAME = format('(?:{0}|`{1}`)', NAME, NAME_WWS);
var reSection = /^[!"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]/;
var reDirective = /^\s*\w([-:.\w]*\w)?::(\s|$)/;
var reHyperlink = /^\s*_[\w-]+:(\s|$)/;
var reFootnote = /^\s*\[(\d+|#)\](\s|$)/;
var reCitation = /^\s*\[[A-Za-z][\w-]*\](\s|$)/;
var reFootnoteRef = /^\[(\d+|#)\]_/;
var reCitationRef = /^\[[A-Za-z][\w-]*\]_/;
var reDirectiveMarker = /^\.\.(\s|$)/;
var reVerbatimMarker = /^::\s*$/;
var rePreInline = /^[-\s"([{</:]/;
var rePostInline = /^[-\s`'")\]}>/:.,;!?\\_]/;
var reEnumeratedList = /^\s*((\d+|[A-Za-z#])[.)]|\((\d+|[A-Z-a-z#])\))\s/;
var reBulletedList = /^\s*[-\+\*]\s/;
var reExamples = /^\s+(>>>|In \[\d+\]:)\s/;
var TEXT1 = "(?:[^\\s\\|](?:[^\\|]*[^\\s\\|])?)";
var TEXT2 = "(?:[^\\`]+)",
rx_TEXT2 = new RegExp(format('^{0}', TEXT2));
function normal(stream, state) {
var ch, sol, i;
var rx_section = new RegExp(
"^([!'#$%&\"()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~])\\1{3,}\\s*$");
var rx_explicit = new RegExp(
format('^\\.\\.{0}', SEPA));
var rx_link = new RegExp(
format('^_{0}:{1}|^__:{1}', REF_NAME, TAIL));
var rx_directive = new RegExp(
format('^{0}::{1}', REF_NAME, TAIL));
var rx_substitution = new RegExp(
format('^\\|{0}\\|{1}{2}::{3}', TEXT1, SEPA, REF_NAME, TAIL));
var rx_footnote = new RegExp(
format('^\\[(?:\\d+|#{0}?|\\*)]{1}', REF_NAME, TAIL));
var rx_citation = new RegExp(
format('^\\[{0}\\]{1}', REF_NAME, TAIL));
if (stream.eat(/\\/)) {
ch = stream.next();
setNormal(state, ch);
return null;
}
var rx_substitution_ref = new RegExp(
format('^\\|{0}\\|', TEXT1));
var rx_footnote_ref = new RegExp(
format('^\\[(?:\\d+|#{0}?|\\*)]_', REF_NAME));
var rx_citation_ref = new RegExp(
format('^\\[{0}\\]_', REF_NAME));
var rx_link_ref1 = new RegExp(
format('^{0}__?', REF_NAME));
var rx_link_ref2 = new RegExp(
format('^`{0}`_', TEXT2));
sol = stream.sol();
var rx_role_pre = new RegExp(
format('^:{0}:`{1}`{2}', NAME, TEXT2, TAIL));
var rx_role_suf = new RegExp(
format('^`{1}`:{0}:{2}', NAME, TEXT2, TAIL));
var rx_role = new RegExp(
format('^:{0}:{1}', NAME, TAIL));
if (sol && (ch = stream.eat(reSection))) {
for (i = 0; stream.eat(ch); i++);
var rx_directive_name = new RegExp(format('^{0}', REF_NAME));
var rx_directive_tail = new RegExp(format('^::{0}', TAIL));
var rx_substitution_text = new RegExp(format('^\\|{0}\\|', TEXT1));
var rx_substitution_sepa = new RegExp(format('^{0}', SEPA));
var rx_substitution_name = new RegExp(format('^{0}', REF_NAME));
var rx_substitution_tail = new RegExp(format('^::{0}', TAIL));
var rx_link_head = new RegExp("^_");
var rx_link_name = new RegExp(format('^{0}|_', REF_NAME));
var rx_link_tail = new RegExp(format('^:{0}', TAIL));
if (i >= 3 && stream.match(/^\s*$/)) {
setNormal(state, null);
return 'header';
} else {
stream.backUp(i + 1);
}
}
var rx_verbatim = new RegExp('^::\\s*$');
var rx_examples = new RegExp('^\\s+(?:>>>|In \\[\\d+\\]:)\\s');
if (sol && stream.match(reDirectiveMarker)) {
if (!stream.eol()) {
setState(state, directive);
}
return 'meta';
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
if (stream.match(reVerbatimMarker)) {
if (!verbatimMode) {
setState(state, verbatim);
} else {
var mode = verbatimMode;
function to_normal(stream, state) {
var token = null;
setState(state, verbatim, {
mode: mode,
local: mode.startState()
});
}
return 'meta';
}
if (stream.sol() && stream.match(rx_examples, false)) {
change(state, to_mode, {
mode: mode_python, local: mode_python.startState()
});
} else if (stream.sol() && stream.match(rx_explicit)) {
change(state, to_explicit);
token = 'meta';
} else if (stream.sol() && stream.match(rx_section)) {
change(state, to_normal);
token = 'header';
} else if (phase(state) == rx_role_pre ||
stream.match(rx_role_pre, false)) {
if (sol && stream.match(reExamples, false)) {
if (!pythonMode) {
setState(state, verbatim);
return 'meta';
} else {
var mode = pythonMode;
switch (stage(state)) {
case 0:
change(state, to_normal, context(rx_role_pre, 1));
assert(stream.match(/^:/));
token = 'meta';
break;
case 1:
change(state, to_normal, context(rx_role_pre, 2));
assert(stream.match(rx_NAME));
token = 'keyword';
setState(state, verbatim, {
mode: mode,
local: mode.startState()
});
if (stream.current().match(/^(?:math|latex)/)) {
state.tmp = {
mode: mode_stex, local: mode_stex.startState()
};
}
break;
case 2:
change(state, to_normal, context(rx_role_pre, 3));
assert(stream.match(/^:`/));
token = 'meta';
break;
case 3:
if (state.tmp) {
if (stream.peek() == '`') {
change(state, to_normal, context(rx_role_pre, 4));
state.tmp = undefined;
break;
}
return null;
token = state.tmp.mode.token(stream, state.tmp.local);
break;
}
change(state, to_normal, context(rx_role_pre, 4));
assert(stream.match(rx_TEXT2));
token = 'string';
break;
case 4:
change(state, to_normal, context(rx_role_pre, 5));
assert(stream.match(/^`/));
token = 'meta';
break;
case 5:
change(state, to_normal, context(rx_role_pre, 6));
assert(stream.match(rx_TAIL));
break;
default:
change(state, to_normal);
assert(stream.current() == '');
}
}
} else if (phase(state) == rx_role_suf ||
stream.match(rx_role_suf, false)) {
function testBackward(re) {
return sol || !state.ctx.back || re.test(state.ctx.back);
}
switch (stage(state)) {
case 0:
change(state, to_normal, context(rx_role_suf, 1));
assert(stream.match(/^`/));
token = 'meta';
break;
case 1:
change(state, to_normal, context(rx_role_suf, 2));
assert(stream.match(rx_TEXT2));
token = 'string';
break;
case 2:
change(state, to_normal, context(rx_role_suf, 3));
assert(stream.match(/^`:/));
token = 'meta';
break;
case 3:
change(state, to_normal, context(rx_role_suf, 4));
assert(stream.match(rx_NAME));
token = 'keyword';
break;
case 4:
change(state, to_normal, context(rx_role_suf, 5));
assert(stream.match(/^:/));
token = 'meta';
break;
case 5:
change(state, to_normal, context(rx_role_suf, 6));
assert(stream.match(rx_TAIL));
break;
default:
change(state, to_normal);
assert(stream.current() == '');
}
} else if (phase(state) == rx_role || stream.match(rx_role, false)) {
function testForward(re) {
return stream.eol() || stream.match(re, false);
}
switch (stage(state)) {
case 0:
change(state, to_normal, context(rx_role, 1));
assert(stream.match(/^:/));
token = 'meta';
break;
case 1:
change(state, to_normal, context(rx_role, 2));
assert(stream.match(rx_NAME));
token = 'keyword';
break;
case 2:
change(state, to_normal, context(rx_role, 3));
assert(stream.match(/^:/));
token = 'meta';
break;
case 3:
change(state, to_normal, context(rx_role, 4));
assert(stream.match(rx_TAIL));
break;
default:
change(state, to_normal);
assert(stream.current() == '');
}
} else if (phase(state) == rx_substitution_ref ||
stream.match(rx_substitution_ref, false)) {
function testInline(re) {
return stream.match(re) && testBackward(/\W/) && testForward(/\W/);
}
switch (stage(state)) {
case 0:
change(state, to_normal, context(rx_substitution_ref, 1));
assert(stream.match(rx_substitution_text));
token = 'variable-2';
break;
case 1:
change(state, to_normal, context(rx_substitution_ref, 2));
if (stream.match(/^_?_?/)) token = 'link';
break;
default:
change(state, to_normal);
assert(stream.current() == '');
}
} else if (stream.match(rx_footnote_ref)) {
change(state, to_normal);
token = 'quote';
} else if (stream.match(rx_citation_ref)) {
change(state, to_normal);
token = 'quote';
} else if (stream.match(rx_link_ref1)) {
change(state, to_normal);
if (!stream.peek() || stream.peek().match(/^\W$/)) {
token = 'link';
}
} else if (phase(state) == rx_link_ref2 ||
stream.match(rx_link_ref2, false)) {
if (testInline(reFootnoteRef)) {
setNormal(state, stream);
return 'footnote';
switch (stage(state)) {
case 0:
if (!stream.peek() || stream.peek().match(/^\W$/)) {
change(state, to_normal, context(rx_link_ref2, 1));
} else {
stream.match(rx_link_ref2);
}
break;
case 1:
change(state, to_normal, context(rx_link_ref2, 2));
assert(stream.match(/^`/));
token = 'link';
break;
case 2:
change(state, to_normal, context(rx_link_ref2, 3));
assert(stream.match(rx_TEXT2));
break;
case 3:
change(state, to_normal, context(rx_link_ref2, 4));
assert(stream.match(/^`_/));
token = 'link';
break;
default:
change(state, to_normal);
assert(stream.current() == '');
}
} else if (stream.match(rx_verbatim)) {
change(state, to_verbatim);
}
if (testInline(reCitationRef)) {
setNormal(state, stream);
return 'citation';
else {
if (stream.next()) change(state, to_normal);
}
ch = stream.next();
return token;
}
if (testBackward(rePreInline)) {
if ((ch === ':' || ch === '|') && stream.eat(/\S/)) {
var token;
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
if (ch === ':') {
token = 'builtin';
} else {
token = 'atom';
}
function to_explicit(stream, state) {
var token = null;
setState(state, inline, {
ch: ch,
wide: false,
prev: null,
token: token
});
if (phase(state) == rx_substitution ||
stream.match(rx_substitution, false)) {
return token;
switch (stage(state)) {
case 0:
change(state, to_explicit, context(rx_substitution, 1));
assert(stream.match(rx_substitution_text));
token = 'variable-2';
break;
case 1:
change(state, to_explicit, context(rx_substitution, 2));
assert(stream.match(rx_substitution_sepa));
break;
case 2:
change(state, to_explicit, context(rx_substitution, 3));
assert(stream.match(rx_substitution_name));
token = 'keyword';
break;
case 3:
change(state, to_explicit, context(rx_substitution, 4));
assert(stream.match(rx_substitution_tail));
token = 'meta';
break;
default:
change(state, to_normal);
assert(stream.current() == '');
}
} else if (phase(state) == rx_directive ||
stream.match(rx_directive, false)) {
if (ch === '*' || ch === '`') {
var orig = ch,
wide = false;
switch (stage(state)) {
case 0:
change(state, to_explicit, context(rx_directive, 1));
assert(stream.match(rx_directive_name));
token = 'keyword';
ch = stream.next();
if (stream.current().match(/^(?:math|latex)/))
state.tmp_stex = true;
else if (stream.current().match(/^python/))
state.tmp_py = true;
break;
case 1:
change(state, to_explicit, context(rx_directive, 2));
assert(stream.match(rx_directive_tail));
token = 'meta';
break;
default:
if (stream.match(/^latex\s*$/) || state.tmp_stex) {
state.tmp_stex = undefined;
change(state, to_mode, {
mode: mode_stex, local: mode_stex.startState()
});
} else if (stream.match(/^python\s*$/) || state.tmp_py) {
state.tmp_py = undefined;
change(state, to_mode, {
mode: mode_python, local: mode_python.startState()
});
}
if (ch == orig) {
wide = true;
ch = stream.next();
}
if (ch && !/\s/.test(ch)) {
var token;
if (orig === '*') {
token = wide ? 'strong' : 'em';
} else {
token = wide ? 'string' : 'string-2';
else {
change(state, to_normal);
assert(stream.current() == '');
}
}
} else if (phase(state) == rx_link || stream.match(rx_link, false)) {
setState(state, inline, {
ch: orig, // inline() has to know what to search for
wide: wide, // are we looking for `ch` or `chch`
prev: null, // terminator must not be preceeded with whitespace
token: token // I don't want to recompute this all the time
});
switch (stage(state)) {
case 0:
change(state, to_explicit, context(rx_link, 1));
assert(stream.match(rx_link_head));
assert(stream.match(rx_link_name));
token = 'link';
break;
case 1:
change(state, to_explicit, context(rx_link, 2));
assert(stream.match(rx_link_tail));
token = 'meta';
break;
default:
change(state, to_normal);
assert(stream.current() == '');
}
} else if (stream.match(rx_footnote)) {
change(state, to_normal);
token = 'quote';
} else if (stream.match(rx_citation)) {
change(state, to_normal);
token = 'quote';
}
return token;
}
else {
stream.eatSpace();
if (stream.eol()) {
change(state, to_normal);
} else {
stream.skipToEnd();
change(state, to_comment);
token = 'comment';
}
}
setNormal(state, ch);
return null;
return token;
}
function inline(stream, state) {
var ch = stream.next(),
token = state.ctx.token;
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
function finish(ch) {
state.ctx.prev = ch;
function to_comment(stream, state) {
return as_block(stream, state, 'comment');
}
function to_verbatim(stream, state) {
return as_block(stream, state, 'meta');
}
function as_block(stream, state, token) {
if (stream.eol() || stream.eatSpace()) {
stream.skipToEnd();
return token;
} else {
change(state, to_normal);
return null;
}
}
if (ch != state.ctx.ch) {
return finish(ch);
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
if (/\s/.test(state.ctx.prev)) {
return finish(ch);
}
function to_mode(stream, state) {
if (state.ctx.wide) {
ch = stream.next();
if (state.ctx.mode && state.ctx.local) {
if (ch != state.ctx.ch) {
return finish(ch);
if (stream.sol()) {
if (!stream.eatSpace()) change(state, to_normal);
return null;
}
}
if (!stream.eol() && !rePostInline.test(stream.peek())) {
if (state.ctx.wide) {
stream.backUp(1);
try {
return state.ctx.mode.token(stream, state.ctx.local);
} catch (ex) {
change(state, to_normal);
return null;
}
return finish(ch);
}
setState(state, normal);
setNormal(state, ch);
return token;
change(state, to_normal);
return null;
}
function directive(stream, state) {
var token = null;
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
if (stream.match(reDirective)) {
token = 'attribute';
} else if (stream.match(reHyperlink)) {
token = 'link';
} else if (stream.match(reFootnote)) {
token = 'quote';
} else if (stream.match(reCitation)) {
token = 'quote';
} else {
stream.eatSpace();
function context(phase, stage, mode, local) {
return {phase: phase, stage: stage, mode: mode, local: local};
}
if (stream.eol()) {
setNormal(state, stream);
return null;
} else {
stream.skipToEnd();
setState(state, comment);
return 'comment';
}
}
function change(state, tok, ctx) {
state.tok = tok;
state.ctx = ctx || {};
}
// FIXME this is unreachable
setState(state, body, {start: true});
return token;
function stage(state) {
return state.ctx.stage || 0;
}
function body(stream, state) {
var token = 'body';
function phase(state) {
return state.ctx.phase;
}
if (!state.ctx.start || stream.sol()) {
return block(stream, state, token);
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
return {
startState: function () {
return {tok: to_normal, ctx: context(undefined, 0)};
},
copyState: function (state) {
return {tok: state.tok, ctx: state.ctx};
},
innerMode: function (state) {
return {state: state.ctx.local, mode: state.ctx.mode};
},
token: function (stream, state) {
return state.tok(stream, state);
}
};
}, 'python', 'stex');
stream.skipToEnd();
setCtx(state);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
return token;
}
CodeMirror.defineMode('rst', function (config, options) {
function comment(stream, state) {
return block(stream, state, 'comment');
}
var rx_uri_protocol = "[Hh][Tt][Tt][Pp][Ss]?://";
var rx_uri_domain = "(?:[\\d\\w.-]+)\\.(?:\\w{2,6})";
var rx_uri_path = "(?:/[\\d\\w\\#\\%\\&\\-\\.\\,\\/\\:\\=\\?\\~]+)*";
var rx_uri = new RegExp("^" +
rx_uri_protocol + rx_uri_domain + rx_uri_path
);
function verbatim(stream, state) {
if (!verbatimMode) {
return block(stream, state, 'meta');
} else {
if (stream.sol()) {
if (!stream.eatSpace()) {
setNormal(state, stream);
}
var rx_strong = /^\*\*[^\*\s](?:[^\*]*[^\*\s])?\*\*/;
var rx_emphasis = /^\*[^\*\s](?:[^\*]*[^\*\s])?\*/;
var rx_literal = /^``[^`\s](?:[^`]*[^`\s])``/;
return null;
var rx_number = /^(?:[\d]+(?:[\.,]\d+)*)/;
var rx_positive = /^(?:\s\+[\d]+(?:[\.,]\d+)*)/;
var rx_negative = /^(?:\s\-[\d]+(?:[\.,]\d+)*)/;
var overlay = {
token: function (stream) {
if (stream.match(rx_uri)) return 'link';
if (stream.match(rx_strong)) return 'strong';
if (stream.match(rx_emphasis)) return 'em';
if (stream.match(rx_literal)) return 'string-2';
if (stream.match(rx_number)) return 'number';
if (stream.match(rx_positive)) return 'positive';
if (stream.match(rx_negative)) return 'negative';
while (stream.next() != null) {
if (stream.match(rx_uri, false)) break;
if (stream.match(rx_strong, false)) break;
if (stream.match(rx_emphasis, false)) break;
if (stream.match(rx_literal, false)) break;
if (stream.match(rx_number, false)) break;
if (stream.match(rx_positive, false)) break;
if (stream.match(rx_negative, false)) break;
}
return verbatimMode.token(stream, state.ctx.local);
}
}
function block(stream, state, token) {
if (stream.eol() || stream.eatSpace()) {
stream.skipToEnd();
return token;
} else {
setNormal(state, stream);
return null;
}
}
};
return {
startState: function() {
return {fn: normal, ctx: {}};
},
var mode = CodeMirror.getMode(
config, options.backdrop || 'rst-base'
);
copyState: function(state) {
return {fn: state.fn, ctx: state.ctx};
},
return CodeMirror.overlayMode(mode, overlay, true); // combine
}, 'python', 'stex');
token: function(stream, state) {
var token = state.fn(stream, state);
return token;
}
};
}, "python");
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
CodeMirror.defineMIME("text/x-rst", "rst");
CodeMirror.defineMIME('text/x-rst', 'rst');
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

@@ -1,2 +0,2 @@

CodeMirror.defineMode("ruby", function(config, parserConfig) {
CodeMirror.defineMode("ruby", function(config) {
function wordObj(words) {

@@ -3,0 +3,0 @@ var o = {};

@@ -212,3 +212,3 @@ CodeMirror.defineMode("rust", function() {

}
function maybeprop(type) {
function maybeprop() {
if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);}

@@ -308,3 +308,3 @@ return pass(expression);

}
function typarams(type) {
function typarams() {
if (content == ">") return cont();

@@ -329,3 +329,3 @@ if (content == ",") return cont(typarams);

}
function rtypemaybeparam(type) {
function rtypemaybeparam() {
if (content == "<") return cont(typarams);

@@ -332,0 +332,0 @@ return pass();

/**
* Author: Koh Zi Han, based on implementation by Koh Zi Chun
*/
CodeMirror.defineMode("scheme", function (config, mode) {
CodeMirror.defineMode("scheme", function () {
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD="keyword";
var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
ATOM = "atom", NUMBER = "number", BRACKET = "bracket";
var INDENT_WORD_SKIP = 2;

@@ -223,3 +223,3 @@ function makeKeywords(str) {

indent: function (state, textAfter) {
indent: function (state) {
if (state.indentStack == null) return state.indentation;

@@ -226,0 +226,0 @@ return state.indentStack.indent;

@@ -1,2 +0,2 @@

CodeMirror.defineMode('shell', function(config) {
CodeMirror.defineMode('shell', function() {

@@ -3,0 +3,0 @@ var words = {};

@@ -34,15 +34,33 @@ /*

}
if (ch == "(") {
state._indent.push("(");
// add virtual angel wings so that editor behaves...
// ...more sane incase of broken brackets
state._indent.push("{");
return null;
}
if (ch === "{")
{
state._indent++;
if (ch === "{") {
state._indent.push("{");
return null;
}
if (ch == ")") {
state._indent.pop();
state._indent.pop();
}
if (ch === "}")
{
state._indent--;
if (ch === "}") {
state._indent.pop();
return null;
}
if (ch == ",")
return null;
if (ch == ";")
return null;
if (/[{}\(\),;]/.test(ch))

@@ -66,3 +84,3 @@ return null;

stream.eatWhile(/[\w\$_]/);
stream.eatWhile(/\w/);
var cur = stream.current();

@@ -84,2 +102,4 @@

return "atom";
return null;
}

@@ -141,3 +161,3 @@

baseIndent: base || 0,
_indent: 0};
_indent: []};
},

@@ -152,4 +172,11 @@

indent: function(state, textAfter) {
return state.baseIndent + state._indent * indentUnit;
indent: function(state, _textAfter) {
var length = state._indent.length;
if (_textAfter && (_textAfter[0] == "}"))
length--;
if (length <0)
length = 0;
return length * indentUnit;
},

@@ -156,0 +183,0 @@

@@ -1,2 +0,2 @@

CodeMirror.defineMode('smalltalk', function(config, modeConfig) {
CodeMirror.defineMode('smalltalk', function(config) {

@@ -89,3 +89,3 @@ var specialChars = /[+\-/\\*~<>=@%|&?!.:;^]/;

var nextTemporaries = function(stream, context, state) {
var nextTemporaries = function(stream, context) {
var token = new Token(null, context, false);

@@ -92,0 +92,0 @@ var aChar = stream.next();

@@ -1,2 +0,2 @@

CodeMirror.defineMode("smarty", function(config, parserConfig) {
CodeMirror.defineMode("smarty", function(config) {
var keyFuncs = ["debug", "extends", "function", "include", "literal"];

@@ -3,0 +3,0 @@ var last;

@@ -52,3 +52,3 @@ CodeMirror.defineMode("sparql", function(config) {

}
var word = stream.current(), type;
var word = stream.current();
if (ops.test(word))

@@ -86,3 +86,3 @@ return null;

return {
startState: function(base) {
startState: function() {
return {tokenize: tokenBase,

@@ -89,0 +89,0 @@ context: null,

@@ -6,97 +6,89 @@ /*

CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
{
CodeMirror.defineMode("stex", function() {
"use strict";
function pushCommand(state, command) {
state.cmdState.push(command);
state.cmdState.push(command);
}
function peekCommand(state) {
if (state.cmdState.length>0)
return state.cmdState[state.cmdState.length-1];
else
return null;
function peekCommand(state) {
if (state.cmdState.length > 0) {
return state.cmdState[state.cmdState.length - 1];
} else {
return null;
}
}
function popCommand(state) {
if (state.cmdState.length>0) {
var plug = state.cmdState.pop();
plug.closeBracket();
}
var plug = state.cmdState.pop();
if (plug) {
plug.closeBracket();
}
}
function applyMostPowerful(state) {
var context = state.cmdState;
for (var i = context.length - 1; i >= 0; i--) {
var plug = context[i];
if (plug.name=="DEFAULT")
continue;
return plug.styleIdentifier();
}
return null;
// returns the non-default plugin closest to the end of the list
function getMostPowerful(state) {
var context = state.cmdState;
for (var i = context.length - 1; i >= 0; i--) {
var plug = context[i];
if (plug.name == "DEFAULT") {
continue;
}
return plug;
}
return { styleIdentifier: function() { return null; } };
}
function addPluginPattern(pluginName, cmdStyle, brackets, styles) {
return function () {
this.name=pluginName;
this.bracketNo = 0;
this.style=cmdStyle;
this.styles = styles;
this.brackets = brackets;
function addPluginPattern(pluginName, cmdStyle, styles) {
return function () {
this.name = pluginName;
this.bracketNo = 0;
this.style = cmdStyle;
this.styles = styles;
this.argument = null; // \begin and \end have arguments that follow. These are stored in the plugin
this.styleIdentifier = function(content) {
if (this.bracketNo<=this.styles.length)
return this.styles[this.bracketNo-1];
else
return null;
};
this.openBracket = function(content) {
this.bracketNo++;
return "bracket";
};
this.closeBracket = function(content) {
};
};
this.styleIdentifier = function() {
return this.styles[this.bracketNo - 1] || null;
};
this.openBracket = function() {
this.bracketNo++;
return "bracket";
};
this.closeBracket = function() {};
};
}
var plugins = new Array();
plugins["importmodule"] = addPluginPattern("importmodule", "tag", "{[", ["string", "builtin"]);
plugins["documentclass"] = addPluginPattern("documentclass", "tag", "{[", ["", "atom"]);
plugins["usepackage"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
plugins["begin"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
plugins["end"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
var plugins = {};
plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]);
plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]);
plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]);
plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]);
plugins["end"] = addPluginPattern("end", "tag", ["atom"]);
plugins["DEFAULT"] = function () {
this.name="DEFAULT";
this.style="tag";
this.name = "DEFAULT";
this.style = "tag";
this.styleIdentifier = function(content) {
};
this.openBracket = function(content) {
};
this.closeBracket = function(content) {
};
this.styleIdentifier = this.openBracket = this.closeBracket = function() {};
};
function setState(state, f) {
state.f = f;
state.f = f;
}
// called when in a normal (no environment) context
function normal(source, state) {
if (source.match(/^\\[a-zA-Z@]+/)) {
var cmdName = source.current();
cmdName = cmdName.substr(1, cmdName.length-1);
var plug;
if (plugins.hasOwnProperty(cmdName)) {
plug = plugins[cmdName];
} else {
plug = plugins["DEFAULT"];
}
plug = new plug();
pushCommand(state, plug);
setState(state, beginParams);
return plug.style;
}
var plug;
// Do we look like '\command' ? If so, attempt to apply the plugin 'command'
if (source.match(/^\\[a-zA-Z@]+/)) {
var cmdName = source.current().slice(1);
plug = plugins[cmdName] || plugins["DEFAULT"];
plug = new plug();
pushCommand(state, plug);
setState(state, beginParams);
return plug.style;
}
// escape characters
// escape characters
if (source.match(/^\\[$&%#{}_]/)) {

@@ -111,4 +103,18 @@ return "tag";

var ch = source.next();
if (ch == "%") {
// find if we're starting various math modes
if (source.match("\\[")) {
setState(state, function(source, state){ return inMathMode(source, state, "\\]"); });
return "keyword";
}
if (source.match("$$")) {
setState(state, function(source, state){ return inMathMode(source, state, "$$"); });
return "keyword";
}
if (source.match("$")) {
setState(state, function(source, state){ return inMathMode(source, state, "$"); });
return "keyword";
}
var ch = source.next();
if (ch == "%") {
// special case: % at end of its own line; stay in same state

@@ -118,52 +124,103 @@ if (!source.eol()) {

}
return "comment";
}
else if (ch=='}' || ch==']') {
plug = peekCommand(state);
if (plug) {
plug.closeBracket(ch);
setState(state, beginParams);
} else
return "error";
return "bracket";
} else if (ch=='{' || ch=='[') {
plug = plugins["DEFAULT"];
plug = new plug();
pushCommand(state, plug);
return "bracket";
}
else if (/\d/.test(ch)) {
source.eatWhile(/[\w.%]/);
return "atom";
}
else {
source.eatWhile(/[\w-_]/);
return applyMostPowerful(state);
}
return "comment";
}
else if (ch == '}' || ch == ']') {
plug = peekCommand(state);
if (plug) {
plug.closeBracket(ch);
setState(state, beginParams);
} else {
return "error";
}
return "bracket";
} else if (ch == '{' || ch == '[') {
plug = plugins["DEFAULT"];
plug = new plug();
pushCommand(state, plug);
return "bracket";
}
else if (/\d/.test(ch)) {
source.eatWhile(/[\w.%]/);
return "atom";
}
else {
source.eatWhile(/[\w\-_]/);
plug = getMostPowerful(state);
if (plug.name == 'begin') {
plug.argument = source.current();
}
return plug.styleIdentifier();
}
}
function inCComment(source, state) {
source.skipToEnd();
setState(state, normal);
return "comment";
source.skipToEnd();
setState(state, normal);
return "comment";
}
function inMathMode(source, state, endModeSeq) {
if (source.eatSpace()) {
return null;
}
if (source.match(endModeSeq)) {
setState(state, normal);
return "keyword";
}
if (source.match(/^\\[a-zA-Z@]+/)) {
return "tag";
}
if (source.match(/^[a-zA-Z]+/)) {
return "variable-2";
}
// escape characters
if (source.match(/^\\[$&%#{}_]/)) {
return "tag";
}
// white space control characters
if (source.match(/^\\[,;!\/]/)) {
return "tag";
}
// special math-mode characters
if (source.match(/^[\^_&]/)) {
return "tag";
}
// non-special characters
if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) {
return null;
}
if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) {
return "number";
}
var ch = source.next();
if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {
return "bracket";
}
// eat comments here, because inCComment returns us to normal state!
if (ch == "%") {
if (!source.eol()) {
source.skipToEnd();
}
return "comment";
}
return "error";
}
function beginParams(source, state) {
var ch = source.peek();
if (ch == '{' || ch == '[') {
var lastPlug = peekCommand(state);
var style = lastPlug.openBracket(ch);
source.eat(ch);
setState(state, normal);
return "bracket";
}
if (/[ \t\r]/.test(ch)) {
source.eat(ch);
return null;
}
setState(state, normal);
lastPlug = peekCommand(state);
if (lastPlug) {
popCommand(state);
}
var ch = source.peek(), lastPlug;
if (ch == '{' || ch == '[') {
lastPlug = peekCommand(state);
lastPlug.openBracket(ch);
source.eat(ch);
setState(state, normal);
return "bracket";
}
if (/[ \t\r]/.test(ch)) {
source.eat(ch);
return null;
}
setState(state, normal);
popCommand(state);
return normal(source, state);

@@ -173,11 +230,18 @@ }

return {
startState: function() { return { f:normal, cmdState:[] }; },
copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; },
token: function(stream, state) {
var t = state.f(stream, state);
var w = stream.current();
return t;
}
};
startState: function() {
return {
cmdState: [],
f: normal
};
},
copyState: function(s) {
return {
cmdState: s.cmdState.slice(),
f: s.f
};
},
token: function(stream, state) {
return state.f(stream, state);
}
};
});

@@ -184,0 +248,0 @@

@@ -1,343 +0,117 @@

var MT = ModeTest;
MT.modeName = 'stex';
MT.modeOptions = {};
(function() {
var mode = CodeMirror.getMode({tabSize: 4}, "stex");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
MT.testMode(
'word',
'foo',
[
null, 'foo'
]
);
MT("word",
"foo");
MT.testMode(
'twoWords',
'foo bar',
[
null, 'foo bar'
]
);
MT("twoWords",
"foo bar");
MT.testMode(
'beginEndDocument',
'\\begin{document}\n\\end{document}',
[
'tag', '\\begin',
'bracket', '{',
'atom', 'document',
'bracket', '}',
'tag', '\\end',
'bracket', '{',
'atom', 'document',
'bracket', '}'
]
);
MT("beginEndDocument",
"[tag \\begin][bracket {][atom document][bracket }]",
"[tag \\end][bracket {][atom document][bracket }]");
MT.testMode(
'beginEndEquation',
'\\begin{equation}\n E=mc^2\n\\end{equation}',
[
'tag', '\\begin',
'bracket', '{',
'atom', 'equation',
'bracket', '}',
null, ' E=mc^2',
'tag', '\\end',
'bracket', '{',
'atom', 'equation',
'bracket', '}'
]
);
MT("beginEndEquation",
"[tag \\begin][bracket {][atom equation][bracket }]",
" E=mc^2",
"[tag \\end][bracket {][atom equation][bracket }]");
MT.testMode(
'beginModule',
'\\begin{module}[]',
[
'tag', '\\begin',
'bracket', '{',
'atom', 'module',
'bracket', '}[]'
]
);
MT("beginModule",
"[tag \\begin][bracket {][atom module][bracket }[[]]]");
MT.testMode(
'beginModuleId',
'\\begin{module}[id=bbt-size]',
[
'tag', '\\begin',
'bracket', '{',
'atom', 'module',
'bracket', '}[',
null, 'id=bbt-size',
'bracket', ']'
]
);
MT("beginModuleId",
"[tag \\begin][bracket {][atom module][bracket }[[]id=bbt-size[bracket ]]]");
MT.testMode(
'importModule',
'\\importmodule[b-b-t]{b-b-t}',
[
'tag', '\\importmodule',
'bracket', '[',
'string', 'b-b-t',
'bracket', ']{',
'builtin', 'b-b-t',
'bracket', '}'
]
);
MT("importModule",
"[tag \\importmodule][bracket [[][string b-b-t][bracket ]]{][builtin b-b-t][bracket }]");
MT.testMode(
'importModulePath',
'\\importmodule[\\KWARCslides{dmath/en/cardinality}]{card}',
[
'tag', '\\importmodule',
'bracket', '[',
'tag', '\\KWARCslides',
'bracket', '{',
'string', 'dmath/en/cardinality',
'bracket', '}]{',
'builtin', 'card',
'bracket', '}'
]
);
MT("importModulePath",
"[tag \\importmodule][bracket [[][tag \\KWARCslides][bracket {][string dmath/en/cardinality][bracket }]]{][builtin card][bracket }]");
MT.testMode(
'psForPDF',
'\\PSforPDF[1]{#1}', // could treat #1 specially
[
'tag', '\\PSforPDF',
'bracket', '[',
'atom', '1',
'bracket', ']{',
null, '#1',
'bracket', '}'
]
);
MT("psForPDF",
"[tag \\PSforPDF][bracket [[][atom 1][bracket ]]{]#1[bracket }]");
MT.testMode(
'comment',
'% foo',
[
'comment', '% foo'
]
);
MT("comment",
"[comment % foo]");
MT.testMode(
'tagComment',
'\\item% bar',
[
'tag', '\\item',
'comment', '% bar'
]
);
MT("tagComment",
"[tag \\item][comment % bar]");
MT.testMode(
'commentTag',
' % \\item',
[
null, ' ',
'comment', '% \\item'
]
);
MT("commentTag",
" [comment % \\item]");
MT.testMode(
'commentLineBreak',
'%\nfoo',
[
'comment', '%',
null, 'foo'
]
);
MT("commentLineBreak",
"[comment %]",
"foo");
MT.testMode(
'tagErrorCurly',
'\\begin}{',
[
'tag', '\\begin',
'error', '}',
'bracket', '{'
]
);
MT("tagErrorCurly",
"[tag \\begin][error }][bracket {]");
MT.testMode(
'tagErrorSquare',
'\\item]{',
[
'tag', '\\item',
'error', ']',
'bracket', '{'
]
);
MT("tagErrorSquare",
"[tag \\item][error ]]][bracket {]");
MT.testMode(
'commentCurly',
'% }',
[
'comment', '% }'
]
);
MT("commentCurly",
"[comment % }]");
MT.testMode(
'tagHash',
'the \\# key',
[
null, 'the ',
'tag', '\\#',
null, ' key'
]
);
MT("tagHash",
"the [tag \\#] key");
MT.testMode(
'tagNumber',
'a \\$5 stetson',
[
null, 'a ',
'tag', '\\$',
'atom', 5,
null, ' stetson'
]
);
MT("tagNumber",
"a [tag \\$][atom 5] stetson");
MT.testMode(
'tagPercent',
'100\\% beef',
[
'atom', '100',
'tag', '\\%',
null, ' beef'
]
);
MT("tagPercent",
"[atom 100][tag \\%] beef");
MT.testMode(
'tagAmpersand',
'L \\& N',
[
null, 'L ',
'tag', '\\&',
null, ' N'
]
);
MT("tagAmpersand",
"L [tag \\&] N");
MT.testMode(
'tagUnderscore',
'foo\\_bar',
[
null, 'foo',
'tag', '\\_',
null, 'bar'
]
);
MT("tagUnderscore",
"foo[tag \\_]bar");
MT.testMode(
'tagBracketOpen',
'\\emph{\\{}',
[
'tag', '\\emph',
'bracket', '{',
'tag', '\\{',
'bracket', '}'
]
);
MT("tagBracketOpen",
"[tag \\emph][bracket {][tag \\{][bracket }]");
MT.testMode(
'tagBracketClose',
'\\emph{\\}}',
[
'tag', '\\emph',
'bracket', '{',
'tag', '\\}',
'bracket', '}'
]
);
MT("tagBracketClose",
"[tag \\emph][bracket {][tag \\}][bracket }]");
MT.testMode(
'tagLetterNumber',
'section \\S1',
[
null, 'section ',
'tag', '\\S',
'atom', '1'
]
);
MT("tagLetterNumber",
"section [tag \\S][atom 1]");
MT.testMode(
'textTagNumber',
'para \\P2',
[
null, 'para ',
'tag', '\\P',
'atom', '2'
]
);
MT("textTagNumber",
"para [tag \\P][atom 2]");
MT.testMode(
'thinspace',
'x\\,y', // thinspace
[
null, 'x',
'tag', '\\,',
null, 'y'
]
);
MT("thinspace",
"x[tag \\,]y");
MT.testMode(
'thickspace',
'x\\;y', // thickspace
[
null, 'x',
'tag', '\\;',
null, 'y'
]
);
MT("thickspace",
"x[tag \\;]y");
MT.testMode(
'negativeThinspace',
'x\\!y', // negative thinspace
[
null, 'x',
'tag', '\\!',
null, 'y'
]
);
MT("negativeThinspace",
"x[tag \\!]y");
MT.testMode(
'periodNotSentence',
'J.\\ L.\\ is', // period not ending a sentence
[
null, 'J.\\ L.\\ is'
]
); // maybe could be better
MT("periodNotSentence",
"J.\\ L.\\ is");
MT.testMode(
'periodSentence',
'X\\@. The', // period ending a sentence
[
null, 'X',
'tag', '\\@',
null, '. The'
]
);
MT("periodSentence",
"X[tag \\@]. The");
MT.testMode(
'italicCorrection',
'{\\em If\\/} I', // italic correction
[
'bracket', '{',
'tag', '\\em',
null, ' If',
'tag', '\\/',
'bracket', '}',
null, ' I'
]
);
MT("italicCorrection",
"[bracket {][tag \\em] If[tag \\/][bracket }] I");
MT.testMode(
'tagBracket',
'\\newcommand{\\pop}',
[
'tag', '\\newcommand',
'bracket', '{',
'tag', '\\pop',
'bracket', '}'
]
);
MT("tagBracket",
"[tag \\newcommand][bracket {][tag \\pop][bracket }]");
MT("inlineMathTagFollowedByNumber",
"[keyword $][tag \\pi][number 2][keyword $]");
MT("inlineMath",
"[keyword $][number 3][variable-2 x][tag ^][number 2.45]-[tag \\sqrt][bracket {][tag \\$\\alpha][bracket }] = [number 2][keyword $] other text");
MT("displayMath",
"More [keyword $$]\t[variable-2 S][tag ^][variable-2 n][tag \\sum] [variable-2 i][keyword $$] other text");
MT("mathWithComment",
"[keyword $][variable-2 x] [comment % $]",
"[variable-2 y][keyword $] other text");
})();

@@ -17,15 +17,5 @@ /***

//{{{
CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
var indentUnit = config.indentUnit;
CodeMirror.defineMode("tiddlywiki", function () {
// Tokenizer
var textwords = function () {
function kw(type) {
return {
type: type,
style: "text"
};
}
return {};
}();
var textwords = {};

@@ -64,3 +54,2 @@ var keywords = function () {

reCodeStart = /\{\{\{/, // {{{ code span start
reUntilCodeStop = /.*?\}\}\}/;

@@ -73,13 +62,2 @@

// used for strings
function nextUntilUnescaped(stream, end) {
var escaped = false,
next;
while ((next = stream.next()) != null) {
if (next == end && !escaped) return false;
escaped = !escaped && next == "\\";
}
return escaped;
}
// Used as scratch variables to communicate multiple values without

@@ -96,4 +74,3 @@ // consing up tons of objects.

function jsTokenBase(stream, state) {
var sol = stream.sol(),
ch, tch;
var sol = stream.sol(), ch;

@@ -233,9 +210,2 @@ state.block = false; // indicates the start of a code block.

function twTokenString(quote) {
return function (stream, state) {
if (!nextUntilUnescaped(stream, quote)) state.tokenize = jsTokenBase;
return ret("string", "string");
};
}
// tw invisible comment

@@ -322,4 +292,3 @@ function twTokenComment(stream, state) {

function twTokenStrike(stream, state) {
var maybeEnd = false,
ch, nr;
var maybeEnd = false, ch;

@@ -338,3 +307,3 @@ while (ch = stream.next()) {

function twTokenMacro(stream, state) {
var ch, tmp, word, known;
var ch, word, known;

@@ -372,3 +341,3 @@ if (stream.current() == '<<') {

return {
startState: function (basecolumn) {
startState: function () {
return {

@@ -375,0 +344,0 @@ tokenize: jsTokenBase,

@@ -1,2 +0,2 @@

CodeMirror.defineMode('tiki', function(config, parserConfig) {
CodeMirror.defineMode('tiki', function(config) {
function inBlock(style, terminator, returnTokenizer) {

@@ -18,3 +18,3 @@ return function(stream, state) {

function inLine(style, terminator) {
function inLine(style) {
return function(stream, state) {

@@ -41,3 +41,3 @@ while(!stream.eol()) {

case "{": //plugin
var type = stream.eat("/") ? "closeTag" : "openTag";
stream.eat("/");
stream.eatSpace();

@@ -44,0 +44,0 @@ var tagName = "";

@@ -15,4 +15,4 @@ CodeMirror.defineMode("vb", function(conf, parserConf) {

var openingKeywords = ['class','module', 'sub','enum','select','while','if','function', 'get','set','property'];
var middleKeywords = ['else','elseif','case'];
var openingKeywords = ['class','module', 'sub','enum','select','while','if','function', 'get','set','property', 'try'];
var middleKeywords = ['else','elseif','case', 'catch'];
var endKeywords = ['next','loop'];

@@ -41,7 +41,7 @@

function indent(stream, state) {
function indent(_stream, state) {
state.currentIndent++;
}
function dedent(stream, state) {
function dedent(_stream, state) {
state.currentIndent--;

@@ -164,3 +164,3 @@ }

return function tokenString(stream, state) {
return function(stream, state) {
while (!stream.eol()) {

@@ -224,3 +224,3 @@ stream.eatWhile(/[^'"]/);

electricChars:"dDpPtTfFeE ",
startState: function(basecolumn) {
startState: function() {
return {

@@ -227,0 +227,0 @@ tokenize: tokenBase,

@@ -1,2 +0,2 @@

CodeMirror.defineMode("velocity", function(config) {
CodeMirror.defineMode("velocity", function() {
function parseWords(str) {

@@ -8,3 +8,2 @@ var obj = {}, words = str.split(" ");

var indentUnit = config.indentUnit;
var keywords = parseWords("#end #else #break #stop #[[ #]] " +

@@ -16,3 +15,2 @@ "#{end} #{else} #{break} #{stop}");

var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
var multiLineStrings =true;

@@ -133,3 +131,3 @@ function chain(stream, state, f) {

return {
startState: function(basecolumn) {
startState: function() {
return {

@@ -136,0 +134,0 @@ tokenize: tokenBase,

@@ -170,3 +170,3 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) {

function metaHook(stream, state) {
function metaHook(stream) {
stream.eatWhile(/[\w\$_]/);

@@ -176,14 +176,2 @@ return "meta";

// C#-style strings where "" escapes a quote.
function tokenAtString(stream, state) {
var next;
while ((next = stream.next()) != null) {
if (next == '"' && !stream.eat('"')) {
state.tokenize = null;
break;
}
}
return "string";
}
CodeMirror.defineMIME("text/x-verilog", {

@@ -190,0 +178,0 @@ name: "verilog",

CodeMirror.defineMode("xml", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
var Kludges = parserConfig.htmlMode ? {

@@ -73,7 +75,8 @@ autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,

else {
type = stream.eat("/") ? "closeTag" : "openTag";
stream.eatSpace();
var isClose = stream.eat("/");
tagName = "";
var c;
while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
if (!tagName) return "error";
type = isClose ? "closeTag" : "openTag";
state.tokenize = inTag;

@@ -118,3 +121,3 @@ return "tag";

else {
stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/);
stream.eatWhile(/[^\s\u00a0=<>\"\']/);
return "word";

@@ -169,3 +172,3 @@ }

var curState, setStyle;
var curState, curStream, setStyle;
function pass() {

@@ -196,2 +199,3 @@ for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);

curState.tagName = tagName;
curState.tagStart = curStream.column();
return cont(attributes, endtag(curState.startOfLine));

@@ -217,10 +221,12 @@ } else if (type == "closeTag") {

return function(type) {
var tagName = curState.tagName;
curState.tagName = curState.tagStart = null;
if (type == "selfcloseTag" ||
(type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) {
maybePopContext(curState.tagName.toLowerCase());
(type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))) {
maybePopContext(tagName.toLowerCase());
return cont();
}
if (type == "endTag") {
maybePopContext(curState.tagName.toLowerCase());
pushContext(curState.tagName, startOfLine);
maybePopContext(tagName.toLowerCase());
pushContext(tagName, startOfLine);
return cont();

@@ -263,2 +269,3 @@ }

if (!Kludges.allowMissing) setStyle = "error";
else if (type == "word") setStyle = "attribute";
return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();

@@ -279,7 +286,7 @@ }

startState: function() {
return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};
return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, tagStart: null, context: null};
},
token: function(stream, state) {
if (stream.sol()) {
if (!state.tagName && stream.sol()) {
state.startOfLine = true;

@@ -294,3 +301,3 @@ state.indented = stream.indentation();

if ((style || type) && style != "comment") {
curState = state;
curState = state; curStream = stream;
while (true) {

@@ -310,2 +317,3 @@ var comb = state.cc.pop() || element;

return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
if (state.tagName) return state.tagStart + indentUnit * multilineTagIndentFactor;
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;

@@ -320,3 +328,5 @@ if (context && /^<\//.test(textAfter))

electricChars: "/"
electricChars: "/",
configuration: parserConfig.htmlMode ? "html" : "xml"
};

@@ -323,0 +333,0 @@ });

@@ -23,3 +23,3 @@ /*

*/
CodeMirror.defineMode("xquery", function(config, parserConfig) {
CodeMirror.defineMode("xquery", function() {

@@ -37,3 +37,3 @@ // The keywords object is set to the result of this self executing

, atom = {type: "atom", style: "atom"}
, punctuation = {type: "punctuation", style: ""}
, punctuation = {type: "punctuation", style: null}
, qualifier = {type: "axis_specifier", style: "qualifier"};

@@ -126,3 +126,3 @@

pushStateStack(state,{ type: "codeblock"});
return ret("", "");
return ret("", null);
}

@@ -132,3 +132,3 @@ // end code block

popStateStack(state);
return ret("", "");
return ret("", null);
}

@@ -170,3 +170,3 @@ // if we're in an XML block

pushStateStack(state, { type: "paren"});
return ret("", "");
return ret("", null);
}

@@ -176,3 +176,3 @@ // close paren

popStateStack(state);
return ret("", "");
return ret("", null);
}

@@ -182,3 +182,3 @@ // open paren

pushStateStack(state, { type: "bracket"});
return ret("", "");
return ret("", null);
}

@@ -188,3 +188,3 @@ // close paren

popStateStack(state);
return ret("", "");
return ret("", null);
}

@@ -353,3 +353,3 @@ else {

if(ch == "=")
return ret("", "");
return ret("", null);
// quoted string

@@ -413,3 +413,2 @@ if (ch == '"' || ch == "'")

function isInXmlAttributeBlock(state) { return isIn(state, "attribute"); }
function isInCodeBlock(state) { return isIn(state, "codeblock"); }
function isInXmlConstructor(state) { return isIn(state, "xmlconstructor"); }

@@ -437,3 +436,3 @@ function isInString(state) { return isIn(state, "string"); }

function popStateStack(state) {
var popped = state.stack.pop();
state.stack.pop();
var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize;

@@ -445,3 +444,3 @@ state.tokenize = reinstateTokenize || tokenBase;

return {
startState: function(basecolumn) {
startState: function() {
return {

@@ -448,0 +447,0 @@ tokenize: tokenBase,

{
"name": "codemirror",
"version":"2.33.0",
"main": "codemirror.js",
"version":"3.11.01",
"main": "lib/codemirror.js",
"description": "In-browser code editing made bearable",

@@ -6,0 +6,0 @@ "licenses": [{"type": "MIT",

@@ -7,3 +7,4 @@ # CodeMirror [![Build Status](https://secure.travis-ci.org/marijnh/CodeMirror.png?branch=master)](http://travis-ci.org/marijnh/CodeMirror)

The project page is http://codemirror.net
The manual is at http://codemirror.net/doc/manual.html
The project page is http://codemirror.net
The manual is at http://codemirror.net/doc/manual.html
The contributing guidelines are in [CONTRIBUTING.md](https://github.com/marijnh/CodeMirror/blob/master/CONTRIBUTING.md)
var tests = [], debug = null, debugUsed = new Array(), allNames = [];
function Failure(why) {this.message = why;}
Failure.prototype.toString = function() { return this.message; };

@@ -34,3 +35,3 @@ function indexOf(collection, elt) {

if ((debug && !successful) || verbose) {
place.style.visibility = "";
place.style.visibility = "visible";
} else {

@@ -51,6 +52,2 @@ place.removeChild(cm.getWrapperElement());

debug = null;
} else {
if (totalTests > debug.length) {
totalTests = debug.length;
}
}

@@ -71,3 +68,3 @@ }

} else {
var wildcardName = test.name.split("_").shift() + "_*";
var wildcardName = test.name.split("_")[0] + "_*";
debugIndex = indexOf(debug, wildcardName);

@@ -80,15 +77,11 @@ if (debugIndex !== -1) {

debugIndex = indexOf(debugUsed, wildcardName);
if (debugIndex !== -1) {
totalTests++;
} else {
return step(i + 1);
}
if (debugIndex == -1) return step(i + 1);
}
}
}
var threw = false;
try {
var message = test.func();
if (expFail) callback("fail", test.name, message);
else callback("ok", test.name, message);
} catch(e) {
threw = true;
if (expFail) callback("expected", test.name);

@@ -101,2 +94,6 @@ else if (e instanceof Failure) callback("fail", test.name, e.message);

}
if (!threw) {
if (expFail) callback("fail", test.name, message || "expected failure, but succeeded");
else callback("ok", test.name, message);
}
if (!quit) { // Run next test

@@ -128,4 +125,4 @@ var delay = 0;

if (a == b) return;
if (a == null) throw new Failure(label("comparing null to " + str(b)));
if (b == null) throw new Failure(label("comparing " + str(a) + " to null"));
if (a == null) throw new Failure(label("comparing null to " + str(b), msg));
if (b == null) throw new Failure(label("comparing " + str(a) + " to null", msg));
if (a.line != b.line || a.ch != b.ch) throw new Failure(label(str(a) + " != " + str(b), msg));

@@ -136,1 +133,13 @@ }

}
function countTests() {
if (!debug) return tests.length;
var sum = 0;
for (var i = 0; i < tests.length; ++i) {
var name = tests[i].name;
if (indexOf(debug, name) != -1 ||
indexOf(debug, name.split("_")[0] + "_*") != -1)
++sum;
}
return sum;
}
/*
Simple linter, based on UglifyJS's [1] parse-js module
Simple linter, based on the Acorn [1] parser module

@@ -12,100 +12,88 @@ All of the existing linters either cramp my style or have huge

[1]: https://github.com/mishoo/UglifyJS/
[1]: https://github.com/marijnh/acorn/
*/
var fs = require("fs"), parse_js = require("./parse-js").parse;
var fs = require("fs"), acorn = require("./acorn.js"), walk = require("./walk.js");
var reserved = {};
"break case catch continue debugger default delete do else false finally for function if in\
instanceof new null return switch throw true try typeof var void while with abstract enum\
int short boolean export interface static byte extends long super char final native\
synchonized class float package throws const goto private transient implements protected\
volatile double import public const".split(" ").forEach(function(word) { reserved[word] = true; });
var scopePasser = walk.make({
ScopeBody: function(node, prev, c) { c(node, node.scope); }
});
function checkVariable(scope, name, pos) {
while (scope) {
if (scope.cur.hasOwnProperty(name)) return;
scope = scope.prev;
function checkFile(fileName) {
var file = fs.readFileSync(fileName, "utf8");
var badChar = file.match(/[\x00-\x08\x0b\x0c\x0e-\x19\uFEFF]/);
if (badChar)
fail("Undesirable character " + badChar[0].charCodeAt(0) + " at position " + badChar.index,
{source: fileName});
try {
var parsed = acorn.parse(file, {
locations: true,
ecmaVersion: 3,
strictSemicolons: true,
allowTrailingCommas: false,
forbidReserved: true,
sourceFile: fileName
});
} catch (e) {
fail(e.message, {source: fileName});
return;
}
fail("Accidental global: " + name, pos);
}
function checkProperty(name, pos) {
if (reserved.hasOwnProperty(name)) {
fail("Using a keyword or reserved word as a property: " + name, pos);
var scopes = [];
walk.simple(parsed, {
ScopeBody: function(node, scope) {
node.scope = scope;
scopes.push(scope);
}
}, walk.scopeVisitor, {vars: Object.create(null)});
var ignoredGlobals = Object.create(null);
function inScope(name, scope) {
for (var cur = scope; cur; cur = cur.prev)
if (name in cur.vars) return true;
}
}
function checkLHS(node, scope) {
if (node.type == "Identifier" && !(node.name in ignoredGlobals) &&
!inScope(node.name, scope)) {
ignoredGlobals[node.name] = true;
fail("Assignment to global variable", node.loc);
}
}
function walk(ast, scope) {
var tp = ast[0];
if (typeof tp != "string") tp = tp.name;
function sub(ast) { if (ast) walk(ast, scope); }
function subn(array) { if (array) array.forEach(sub); }
if (tp == "block" || tp == "splice" || tp == "toplevel" || tp == "array") {
subn(ast[1]);
} else if (tp == "var" || tp == "const") {
ast[1].forEach(function(def) { scope.cur[def[0]] = true; if (def[1]) sub(def[1]); });
} else if (tp == "try") {
subn(ast[1]);
if (ast[2]) { scope.cur[ast[2][0]] = true; subn(ast[2][1]); }
subn(ast[3]);
} else if (tp == "throw" || tp == "return" || tp == "dot" || tp == "stat") {
sub(ast[1]);
} else if (tp == "dot") {
sub(ast[1]);
checkProperty(ast[2], ast[0]);
} else if (tp == "new" || tp == "call") {
sub(ast[1]); subn(ast[2]);
} else if (tp == "switch") {
sub(ast[1]);
ast[2].forEach(function(part) { sub(part[0]); subn(part[1]); });
} else if (tp == "conditional" || tp == "if" || tp == "for" || tp == "for-in") {
sub(ast[1]); sub(ast[2]); sub(ast[3]); sub(ast[4]);
} else if (tp == "assign") {
if (ast[2][0].name == "name") checkVariable(scope, ast[2][1], ast[2][0]);
sub(ast[2]); sub(ast[3]);
} else if (tp == "function" || tp == "defun") {
if (tp == "defun") scope.cur[ast[1]] = true;
var nscope = {prev: scope, cur: {}};
ast[2].forEach(function(arg) { nscope.cur[arg] = true; });
ast[3].forEach(function(ast) { walk(ast, nscope); });
} else if (tp == "while" || tp == "do" || tp == "sub" || tp == "with") {
sub(ast[1]); sub(ast[2]);
} else if (tp == "binary" || tp == "unary-prefix" || tp == "unary-postfix" || tp == "label") {
if (/\+\+|--/.test(ast[1]) && ast[2][0].name == "name") checkVariable(scope, ast[2][1], ast[2][0]);
sub(ast[2]); sub(ast[3]);
} else if (tp == "object") {
ast[1].forEach(function(prop) {
if (prop.type != "string") checkProperty(prop[0], ast[0]);
sub(prop[1]); sub(prop[2]);
});
} else if (tp == "seq") {
subn(ast.slice(1));
} else if (tp == "name") {
if (reserved.hasOwnProperty(ast[1]) && !/^(?:null|true|false)$/.test(ast[1]))
fail("Using reserved word as variable name: " + ast[1], ast[0]);
walk.simple(parsed, {
UpdateExpression: function(node, scope) {checkLHS(node.argument, scope);},
AssignmentExpression: function(node, scope) {checkLHS(node.left, scope);},
Identifier: function(node, scope) {
// Mark used identifiers
for (var cur = scope; cur; cur = cur.prev)
if (node.name in cur.vars) {
cur.vars[node.name].used = true;
return;
}
},
FunctionExpression: function(node) {
if (node.id) fail("Named function expression", node.loc);
}
}, scopePasser);
for (var i = 0; i < scopes.length; ++i) {
var scope = scopes[i];
for (var name in scope.vars) {
var info = scope.vars[name];
if (!info.used && info.type != "catch clause" && info.type != "function name" && name.charAt(0) != "_")
fail("Unused " + info.type + " " + name, info.node.loc);
}
}
}
var failed = false, curFile;
var failed = false;
function fail(msg, pos) {
if (typeof pos == "object") pos = pos.start.line + 1;
console.log(curFile + ": " + msg + (typeof pos == "number" ? " (" + pos + ")" : ""));
if (pos.start) msg += " (" + pos.start.line + ":" + pos.start.column + ")";
console.log(pos.source.match(/[^\/]+$/)[0] + ": " + msg);
failed = true;
}
function checkFile(fileName) {
curFile = fileName.match(/[^\/+]*\.js$/)[0];
var file = fs.readFileSync(fileName, "utf8");
var badChar = file.match(/[\x00-\x08\x0b\x0c\x0e-\x19\uFEFF]/);
if (badChar) fail("Undesirable character " + badChar[0].charCodeAt(0) + " at position " + badChar.index);
if (/^#!/.test(file)) file = file.slice(file.indexOf("\n") + 1);
try {
var parsed = parse_js(file, true, true);
} catch(e) {
fail(e.message, e.line);
return;
}
walk(parsed, {prev: null, cur: {}});
}
function checkDir(dir) {

@@ -112,0 +100,0 @@ fs.readdirSync(dir).forEach(function(file) {

@@ -5,200 +5,189 @@ /**

*
* See test.html in the stex mode for examples.
* Mode tests are registered by calling test.mode(testName, mode,
* tokens), where mode is a mode object as returned by
* CodeMirror.getMode, and tokens is an array of lines that make up
* the test.
*
* These lines are strings, in which styled stretches of code are
* enclosed in brackets `[]`, and prefixed by their style. For
* example, `[keyword if]`. Brackets in the code itself must be
* duplicated to prevent them from being interpreted as token
* boundaries. For example `a[[i]]` for `a[i]`. If a token has
* multiple styles, the styles must be separated by ampersands, for
* example `[tag&error </hmtl>]`.
*
* See the test.js files in the css, markdown, gfm, and stex mode
* directories for examples.
*/
ModeTest = {};
(function() {
function findSingle(str, pos, ch) {
for (;;) {
var found = str.indexOf(ch, pos);
if (found == -1) return null;
if (str.charAt(found + 1) != ch) return found;
pos = found + 2;
}
}
ModeTest.modeOptions = {};
ModeTest.modeName = CodeMirror.defaults.mode;
var styleName = /[\w&-_]+/g;
function parseTokens(strs) {
var tokens = [], plain = "";
for (var i = 0; i < strs.length; ++i) {
if (i) plain += "\n";
var str = strs[i], pos = 0;
while (pos < str.length) {
var style = null, text;
if (str.charAt(pos) == "[" && str.charAt(pos+1) != "[") {
styleName.lastIndex = pos + 1;
var m = styleName.exec(str);
style = m[0].replace(/&/g, " ");
var textStart = pos + style.length + 2;
var end = findSingle(str, textStart, "]");
if (end == null) throw new Error("Unterminated token at " + pos + " in '" + str + "'" + style);
text = str.slice(textStart, end);
pos = end + 1;
} else {
var end = findSingle(str, pos, "[");
if (end == null) end = str.length;
text = str.slice(pos, end);
pos = end;
}
text = text.replace(/\[\[|\]\]/g, function(s) {return s.charAt(0);});
tokens.push(style, text);
plain += text;
}
}
return {tokens: tokens, plain: plain};
}
/* keep track of results for printSummary */
ModeTest.testCount = 0;
ModeTest.passes = 0;
test.mode = function(name, mode, tokens, modeName) {
var data = parseTokens(tokens);
return test((modeName || mode.name) + "_" + name, function() {
return compare(data.plain, data.tokens, mode);
});
};
/**
* Run a test; prettyprints the results using document.write().
*
* @param name Name of test
* @param text String to highlight.
* @param expected Expected styles and tokens: Array(style, token, [style, token,...])
* @param modeName
* @param modeOptions
* @param expectedFail
*/
ModeTest.testMode = function(name, text, expected, modeName, modeOptions, expectedFail) {
ModeTest.testCount += 1;
if (!modeName) modeName = ModeTest.modeName;
if (!modeOptions) modeOptions = ModeTest.modeOptions;
function compare(text, expected, mode) {
var mode = CodeMirror.getMode(modeOptions, modeName);
var expectedOutput = [];
for (var i = 0; i < expected.length; i += 2) {
var sty = expected[i];
if (sty && sty.indexOf(" ")) sty = sty.split(' ').sort().join(' ');
expectedOutput.push(sty, expected[i + 1]);
}
if (expected.length < 0) {
throw "must have text for test (" + name + ")";
}
if (expected.length % 2 != 0) {
throw "must have text for test (" + name + ") plus expected (style, token) pairs";
}
return test(
modeName + "_" + name,
function(){
return ModeTest.compare(text, expected, mode);
},
expectedFail
);
}
var observedOutput = highlight(text, mode);
ModeTest.compare = function (text, arguments, mode) {
var pass, passStyle = "";
pass = highlightOutputsEqual(expectedOutput, observedOutput);
passStyle = pass ? 'mt-pass' : 'mt-fail';
var expectedOutput = [];
for (var i = 0; i < arguments.length; i += 2) {
arguments[i] = (arguments[i] != null ? arguments[i].split(' ').sort().join(' ') : arguments[i]);
expectedOutput.push([arguments[i],arguments[i + 1]]);
var s = '';
if (pass) {
s += '<div class="mt-test ' + passStyle + '">';
s += '<pre>' + text + '</pre>';
s += '<div class="cm-s-default">';
s += prettyPrintOutputTable(observedOutput);
s += '</div>';
s += '</div>';
return s;
} else {
s += '<div class="mt-test ' + passStyle + '">';
s += '<pre>' + text + '</pre>';
s += '<div class="cm-s-default">';
s += 'expected:';
s += prettyPrintOutputTable(expectedOutput);
s += 'observed:';
s += prettyPrintOutputTable(observedOutput);
s += '</div>';
s += '</div>';
throw s;
}
}
var observedOutput = ModeTest.highlight(text, mode)
/**
* Emulation of CodeMirror's internal highlight routine for testing. Multi-line
* input is supported.
*
* @param string to highlight
*
* @param mode the mode that will do the actual highlighting
*
* @return array of [style, token] pairs
*/
function highlight(string, mode) {
var state = mode.startState()
var pass, passStyle = "";
if (expectedOutput.length > 0) {
pass = ModeTest.highlightOutputsEqual(expectedOutput, observedOutput);
passStyle = pass ? 'mt-pass' : 'mt-fail';
ModeTest.passes += pass ? 1 : 0;
}
var lines = string.replace(/\r\n/g,'\n').split('\n');
var st = [], pos = 0;
for (var i = 0; i < lines.length; ++i) {
var line = lines[i], newLine = true;
var stream = new CodeMirror.StringStream(line);
if (line == "" && mode.blankLine) mode.blankLine(state);
/* Start copied code from CodeMirror.highlight */
while (!stream.eol()) {
var style = mode.token(stream, state), substr = stream.current();
if (style && style.indexOf(" ") > -1) style = style.split(' ').sort().join(' ');
var s = '';
if (pass || expectedOutput.length == 0) {
s += '<div class="mt-test ' + passStyle + '">';
s += '<pre>' + ModeTest.htmlEscape(text) + '</pre>';
s += '<div class="cm-s-default">';
s += ModeTest.prettyPrintOutputTable(observedOutput);
s += '</div>';
s += '</div>';
return s;
} else {
s += '<div class="mt-test ' + passStyle + '">';
s += '<pre>' + ModeTest.htmlEscape(text) + '</pre>';
s += '<div class="cm-s-default">';
s += 'expected:';
s += ModeTest.prettyPrintOutputTable(expectedOutput);
s += 'observed:';
s += ModeTest.prettyPrintOutputTable(observedOutput);
s += '</div>';
s += '</div>';
throw s;
}
}
/**
* Emulation of CodeMirror's internal highlight routine for testing. Multi-line
* input is supported.
*
* @param string to highlight
*
* @param mode the mode that will do the actual highlighting
*
* @return array of [style, token] pairs
*/
ModeTest.highlight = function(string, mode) {
var state = mode.startState()
var lines = string.replace(/\r\n/g,'\n').split('\n');
var output = [];
for (var i = 0; i < lines.length; ++i) {
var line = lines[i];
var stream = new CodeMirror.StringStream(line);
if (line == "" && mode.blankLine) mode.blankLine(state);
var pos = 0;
var st = [];
/* Start copied code from CodeMirror.highlight */
while (!stream.eol()) {
var style = mode.token(stream, state), substr = stream.current();
stream.start = stream.pos;
if (pos && st[pos-1] == style) {
st[pos-2] += substr;
} else if (substr) {
st[pos++] = substr; st[pos++] = style;
stream.start = stream.pos;
if (pos && st[pos-2] == style && !newLine) {
st[pos-1] += substr;
} else if (substr) {
st[pos++] = style; st[pos++] = substr;
}
// Give up when line is ridiculously long
if (stream.pos > 5000) {
st[pos++] = null; st[pos++] = this.text.slice(stream.pos);
break;
}
newLine = false;
}
// Give up when line is ridiculously long
if (stream.pos > 5000) {
st[pos++] = this.text.slice(stream.pos); st[pos++] = null;
break;
}
}
/* End copied code from CodeMirror.highlight */
for (var x = 0; x < st.length; x += 2) {
st[x + 1] = (st[x + 1] != null ? st[x + 1].split(' ').sort().join(' ') : st[x + 1]);
output.push([st[x + 1], st[x]]);
}
return st;
}
return output;
}
/**
* Compare two arrays of output from ModeTest.highlight.
*
* @param o1 array of [style, token] pairs
*
* @param o2 array of [style, token] pairs
*
* @return boolean; true iff outputs equal
*/
ModeTest.highlightOutputsEqual = function(o1, o2) {
var eq = (o1.length == o2.length);
if (eq) {
for (var j in o1) {
eq = eq &&
o1[j].length == 2 && o1[j][0] == o2[j][0] && o1[j][1] == o2[j][1];
}
/**
* Compare two arrays of output from highlight.
*
* @param o1 array of [style, token] pairs
*
* @param o2 array of [style, token] pairs
*
* @return boolean; true iff outputs equal
*/
function highlightOutputsEqual(o1, o2) {
if (o1.length != o2.length) return false;
for (var i = 0; i < o1.length; ++i)
if (o1[i] != o2[i]) return false;
return true;
}
return eq;
}
/**
* Print tokens and corresponding styles in a table. Spaces in the token are
* replaced with 'interpunct' dots (&middot;).
*
* @param output array of [style, token] pairs
*
* @return html string
*/
ModeTest.prettyPrintOutputTable = function(output) {
var s = '<table class="mt-output">';
s += '<tr>';
for (var i = 0; i < output.length; ++i) {
var token = output[i];
s +=
/**
* Print tokens and corresponding styles in a table. Spaces in the token are
* replaced with 'interpunct' dots (&middot;).
*
* @param output array of [style, token] pairs
*
* @return html string
*/
function prettyPrintOutputTable(output) {
var s = '<table class="mt-output">';
s += '<tr>';
for (var i = 0; i < output.length; i += 2) {
var style = output[i], val = output[i+1];
s +=
'<td class="mt-token">' +
'<span class="cm-' + String(token[0]).replace(/ +/g, " cm-") + '">' +
ModeTest.htmlEscape(token[1]).replace(/ /g,'&middot;') +
'<span class="cm-' + String(style).replace(/ +/g, " cm-") + '">' +
val.replace(/ /g,'\xb7') +
'</span>' +
'</td>';
'</td>';
}
s += '</tr><tr>';
for (var i = 0; i < output.length; i += 2) {
s += '<td class="mt-style"><span>' + output[i] + '</span></td>';
}
s += '</table>';
return s;
}
s += '</tr><tr>';
for (var i = 0; i < output.length; ++i) {
var token = output[i];
s +=
'<td class="mt-style"><span>' + token[0] + '</span></td>';
}
s += '</table>';
return s;
}
/**
* Print how many tests have run so far and how many of those passed.
*/
ModeTest.printSummary = function() {
ModeTest.runTests(ModeTest.displayTest);
document.write(ModeTest.passes + ' passes for ' + ModeTest.testCount + ' tests');
}
/**
* Basic HTML escaping.
*/
ModeTest.htmlEscape = function(str) {
str = str.toString();
return str.replace(/[<&]/g,
function(str) {return str == "&" ? "&amp;" : "&lt;";});
}
})();

@@ -17,3 +17,4 @@ var page = require('webpage').create();

var output = page.evaluate(function () {
return document.getElementById('status').innerText;
return document.getElementById('output').innerText + "\n" +
document.getElementById('status').innerText;
});

@@ -20,0 +21,0 @@ console.log(output);

@@ -7,2 +7,3 @@ #!/usr/bin/env node

lint.checkDir("lib");
lint.checkDir("addon");

@@ -9,0 +10,0 @@ var ok = lint.success();

@@ -0,1 +1,3 @@

var Pos = CodeMirror.Pos;
function forEach(arr, f) {

@@ -26,2 +28,8 @@ for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);

var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
var mac = /Mac/.test(navigator.platform);
var phantom = /PhantomJS/.test(navigator.userAgent);
var opera = /Opera\/\./.test(navigator.userAgent);
var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/);
if (opera_version) opera_version = Number(opera_version);
var opera_lt10 = opera && (!opera_version || opera_version < 10);

@@ -49,6 +57,6 @@ test("core_fromTextArea", function() {

eq(cm.getLine(-1), null);
eq(cm.getRange({line: 0, ch: 0}, {line: 0, ch: 3}), "123");
eq(cm.getRange({line: 0, ch: -1}, {line: 0, ch: 200}), "1234");
eq(cm.getRange({line: 0, ch: 2}, {line: 1, ch: 2}), "34\n56");
eq(cm.getRange({line: 1, ch: 2}, {line: 100, ch: 0}), "78");
eq(cm.getRange(Pos(0, 0), Pos(0, 3)), "123");
eq(cm.getRange(Pos(0, -1), Pos(0, 200)), "1234");
eq(cm.getRange(Pos(0, 2), Pos(1, 2)), "34\n56");
eq(cm.getRange(Pos(1, 2), Pos(100, 0)), "78");
}, {value: "1234\n5678"});

@@ -58,10 +66,10 @@

eq(cm.getValue(), "");
cm.replaceRange("foo\n", {line: 0, ch: 0});
cm.replaceRange("foo\n", Pos(0, 0));
eq(cm.getValue(), "foo\n");
cm.replaceRange("a\nb", {line: 0, ch: 1});
cm.replaceRange("a\nb", Pos(0, 1));
eq(cm.getValue(), "fa\nboo\n");
eq(cm.lineCount(), 3);
cm.replaceRange("xyzzy", {line: 0, ch: 0}, {line: 1, ch: 1});
cm.replaceRange("xyzzy", Pos(0, 0), Pos(1, 1));
eq(cm.getValue(), "xyzzyoo\n");
cm.replaceRange("abc", {line: 0, ch: 0}, {line: 10, ch: 0});
cm.replaceRange("abc", Pos(0, 0), Pos(10, 0));
eq(cm.getValue(), "abc");

@@ -72,11 +80,11 @@ eq(cm.lineCount(), 1);

testCM("selection", function(cm) {
cm.setSelection({line: 0, ch: 4}, {line: 2, ch: 2});
cm.setSelection(Pos(0, 4), Pos(2, 2));
is(cm.somethingSelected());
eq(cm.getSelection(), "11\n222222\n33");
eqPos(cm.getCursor(false), {line: 2, ch: 2});
eqPos(cm.getCursor(true), {line: 0, ch: 4});
cm.setSelection({line: 1, ch: 0});
eqPos(cm.getCursor(false), Pos(2, 2));
eqPos(cm.getCursor(true), Pos(0, 4));
cm.setSelection(Pos(1, 0));
is(!cm.somethingSelected());
eq(cm.getSelection(), "");
eqPos(cm.getCursor(true), {line: 1, ch: 0});
eqPos(cm.getCursor(true), Pos(1, 0));
cm.replaceSelection("abc");

@@ -87,9 +95,46 @@ eq(cm.getSelection(), "abc");

eq(cm.getSelection(), "");
eqPos(cm.getCursor(true), {line: 1, ch: 3});
cm.setCursor({line: 2, ch: 1});
eqPos(cm.getCursor(true), {line: 2, ch: 1});
eqPos(cm.getCursor(true), Pos(1, 3));
cm.setCursor(Pos(2, 1));
eqPos(cm.getCursor(true), Pos(2, 1));
cm.setCursor(1, 2);
eqPos(cm.getCursor(true), {line: 1, ch: 2});
eqPos(cm.getCursor(true), Pos(1, 2));
}, {value: "111111\n222222\n333333"});
testCM("extendSelection", function(cm) {
cm.setExtending(true);
addDoc(cm, 10, 10);
cm.setSelection(Pos(3, 5));
eqPos(cm.getCursor("head"), Pos(3, 5));
eqPos(cm.getCursor("anchor"), Pos(3, 5));
cm.setSelection(Pos(2, 5), Pos(5, 5));
eqPos(cm.getCursor("head"), Pos(5, 5));
eqPos(cm.getCursor("anchor"), Pos(2, 5));
eqPos(cm.getCursor("start"), Pos(2, 5));
eqPos(cm.getCursor("end"), Pos(5, 5));
cm.setSelection(Pos(5, 5), Pos(2, 5));
eqPos(cm.getCursor("head"), Pos(2, 5));
eqPos(cm.getCursor("anchor"), Pos(5, 5));
eqPos(cm.getCursor("start"), Pos(2, 5));
eqPos(cm.getCursor("end"), Pos(5, 5));
cm.extendSelection(Pos(3, 2));
eqPos(cm.getCursor("head"), Pos(3, 2));
eqPos(cm.getCursor("anchor"), Pos(5, 5));
cm.extendSelection(Pos(6, 2));
eqPos(cm.getCursor("head"), Pos(6, 2));
eqPos(cm.getCursor("anchor"), Pos(5, 5));
cm.extendSelection(Pos(6, 3), Pos(6, 4));
eqPos(cm.getCursor("head"), Pos(6, 4));
eqPos(cm.getCursor("anchor"), Pos(5, 5));
cm.extendSelection(Pos(0, 3), Pos(0, 4));
eqPos(cm.getCursor("head"), Pos(0, 3));
eqPos(cm.getCursor("anchor"), Pos(5, 5));
cm.extendSelection(Pos(4, 5), Pos(6, 5));
eqPos(cm.getCursor("head"), Pos(6, 5));
eqPos(cm.getCursor("anchor"), Pos(4, 5));
cm.setExtending(false);
cm.extendSelection(Pos(0, 3), Pos(0, 4));
eqPos(cm.getCursor("head"), Pos(0, 4));
eqPos(cm.getCursor("anchor"), Pos(0, 3));
});
testCM("lines", function(cm) {

@@ -117,4 +162,4 @@ eq(cm.getLine(0), "111111");

test("core_defaults", function() {
var olddefaults = CodeMirror.defaults, defs = CodeMirror.defaults = {};
for (var opt in olddefaults) defs[opt] = olddefaults[opt];
var defsCopy = {}, defs = CodeMirror.defaults;
for (var opt in defs) defsCopy[opt] = defs[opt];
defs.indentUnit = 5;

@@ -134,3 +179,3 @@ defs.value = "uu";

finally {
CodeMirror.defaults = olddefaults;
for (var opt in defsCopy) defs[opt] = defsCopy[opt];
place.removeChild(cm.getWrapperElement());

@@ -142,11 +187,16 @@ }

eq(cm.lineInfo(-1), null);
var lh = cm.setMarker(1, "FOO", "bar");
var mark = document.createElement("span");
var lh = cm.setGutterMarker(1, "FOO", mark);
var info = cm.lineInfo(1);
eq(info.text, "222222");
eq(info.markerText, "FOO");
eq(info.markerClass, "bar");
eq(info.gutterMarkers.FOO, mark);
eq(info.line, 1);
eq(cm.lineInfo(2).markerText, null);
cm.clearMarker(lh);
eq(cm.lineInfo(1).markerText, null);
eq(cm.lineInfo(2).gutterMarkers, null);
cm.setGutterMarker(lh, "FOO", null);
eq(cm.lineInfo(1).gutterMarkers, null);
cm.setGutterMarker(1, "FOO", mark);
cm.setGutterMarker(0, "FOO", mark);
cm.clearGutter("FOO");
eq(cm.lineInfo(0).gutterMarkers, null);
eq(cm.lineInfo(1).gutterMarkers, null);
}, {value: "111111\n222222\n333333"});

@@ -157,11 +207,11 @@

addDoc(cm, 32, 200);
var top = cm.charCoords({line: 0, ch: 0});
var bot = cm.charCoords({line: 200, ch: 30});
is(top.x < bot.x);
is(top.y < bot.y);
is(top.y < top.yBot);
var top = cm.charCoords(Pos(0, 0));
var bot = cm.charCoords(Pos(200, 30));
is(top.left < bot.left);
is(top.top < bot.top);
is(top.top < top.bottom);
cm.scrollTo(null, 100);
var top2 = cm.charCoords({line: 0, ch: 0});
is(top.y > top2.y);
eq(top.x, top2.x);
var top2 = cm.charCoords(Pos(0, 0));
is(top.top > top2.top);
eq(top.left, top2.left);
});

@@ -174,6 +224,5 @@

cm.setCursor(line, ch);
var coords = cm.charCoords({line: line, ch: ch});
var pos = cm.coordsChar({x: coords.x, y: coords.y + 1});
eq(pos.line, line);
eq(pos.ch, ch);
var coords = cm.charCoords(Pos(line, ch));
var pos = cm.coordsChar({left: coords.left, top: coords.top + 5});
eqPos(pos, Pos(line, ch));
}

@@ -207,3 +256,3 @@ }

eq(cm.indexFromPos(pos), example.index);
}
}
});

@@ -226,4 +275,4 @@

for (var i = 0; i < 20; ++i) {
cm.replaceRange("a", {line: 0, ch: 0});
cm.replaceRange("b", {line: 3, ch: 0});
cm.replaceRange("a", Pos(0, 0));
cm.replaceRange("b", Pos(3, 0));
}

@@ -237,18 +286,65 @@ eq(cm.historySize().undo, 40);

testCM("undoDepth", function(cm) {
cm.replaceRange("d", Pos(0));
cm.replaceRange("e", Pos(0));
cm.replaceRange("f", Pos(0));
cm.undo(); cm.undo(); cm.undo();
eq(cm.getValue(), "abcd");
}, {value: "abc", undoDepth: 2});
testCM("undoDoesntClearValue", function(cm) {
cm.undo();
eq(cm.getValue(), "x");
}, {value: "x"});
testCM("undoMultiLine", function(cm) {
cm.replaceRange("x", {line:0, ch: 0});
cm.replaceRange("y", {line:1, ch: 0});
cm.operation(function() {
cm.replaceRange("x", Pos(0, 0));
cm.replaceRange("y", Pos(1, 0));
});
cm.undo();
eq(cm.getValue(), "abc\ndef\nghi");
cm.replaceRange("y", {line:1, ch: 0});
cm.replaceRange("x", {line:0, ch: 0});
cm.operation(function() {
cm.replaceRange("y", Pos(1, 0));
cm.replaceRange("x", Pos(0, 0));
});
cm.undo();
eq(cm.getValue(), "abc\ndef\nghi");
cm.replaceRange("y", {line:2, ch: 0});
cm.replaceRange("x", {line:1, ch: 0});
cm.replaceRange("z", {line:2, ch: 0});
cm.operation(function() {
cm.replaceRange("y", Pos(2, 0));
cm.replaceRange("x", Pos(1, 0));
cm.replaceRange("z", Pos(2, 0));
});
cm.undo();
eq(cm.getValue(), "abc\ndef\nghi");
eq(cm.getValue(), "abc\ndef\nghi", 3);
}, {value: "abc\ndef\nghi"});
testCM("undoComposite", function(cm) {
cm.replaceRange("y", Pos(1));
cm.operation(function() {
cm.replaceRange("x", Pos(0));
cm.replaceRange("z", Pos(2));
});
eq(cm.getValue(), "ax\nby\ncz\n");
cm.undo();
eq(cm.getValue(), "a\nby\nc\n");
cm.undo();
eq(cm.getValue(), "a\nb\nc\n");
cm.redo(); cm.redo();
eq(cm.getValue(), "ax\nby\ncz\n");
}, {value: "a\nb\nc\n"});
testCM("undoSelection", function(cm) {
cm.setSelection(Pos(0, 2), Pos(0, 4));
cm.replaceSelection("");
cm.setCursor(Pos(1, 0));
cm.undo();
eqPos(cm.getCursor(true), Pos(0, 2));
eqPos(cm.getCursor(false), Pos(0, 4));
cm.setCursor(Pos(1, 0));
cm.redo();
eqPos(cm.getCursor(true), Pos(0, 2));
eqPos(cm.getCursor(false), Pos(0, 2));
}, {value: "abcdefgh\n"});
testCM("markTextSingleLine", function(cm) {

@@ -270,4 +366,4 @@ forEach([{a: 0, b: 1, c: "", f: 2, t: 5},

cm.setValue("1234567890");
var r = cm.markText({line: 0, ch: 3}, {line: 0, ch: 6}, "foo");
cm.replaceRange(test.c, {line: 0, ch: test.a}, {line: 0, ch: test.b});
var r = cm.markText(Pos(0, 3), Pos(0, 6), {className: "foo"});
cm.replaceRange(test.c, Pos(0, test.a), Pos(0, test.b));
var f = r.find();

@@ -279,3 +375,3 @@ eq(f && f.from.ch, test.f); eq(f && f.to.ch, test.t);

testCM("markTextMultiLine", function(cm) {
function p(v) { return v && {line: v[0], ch: v[1]}; }
function p(v) { return v && Pos(v[0], v[1]); }
forEach([{a: [0, 0], b: [0, 5], c: "", f: [0, 0], t: [2, 5]},

@@ -297,3 +393,4 @@ {a: [0, 0], b: [0, 5], c: "foo\n", f: [1, 0], t: [3, 5]},

cm.setValue("aaaaaaaaaa\nbbbbbbbbbb\ncccccccccc\ndddddddd\n");
var r = cm.markText({line: 0, ch: 5}, {line: 2, ch: 5}, "CodeMirror-matchingbracket");
var r = cm.markText(Pos(0, 5), Pos(2, 5),
{className: "CodeMirror-matchingbracket"});
cm.replaceRange(test.c, p(test.a), p(test.b));

@@ -306,27 +403,65 @@ var f = r.find();

testCM("markTextUndo", function(cm) {
var marker1 = cm.markText({line: 0, ch: 1}, {line: 0, ch: 3}, "CodeMirror-matchingbracket");
var marker2 = cm.markText({line: 0, ch: 0}, {line: 2, ch: 1}, "CodeMirror-matchingbracket");
var bookmark = cm.setBookmark({line: 1, ch: 5});
cm.replaceRange("foo", {line: 0, ch: 2});
cm.replaceRange("bar\baz\bug\n", {line: 2, ch: 0}, {line: 3, ch: 0});
var marker1, marker2, bookmark;
marker1 = cm.markText(Pos(0, 1), Pos(0, 3),
{className: "CodeMirror-matchingbracket"});
marker2 = cm.markText(Pos(0, 0), Pos(2, 1),
{className: "CodeMirror-matchingbracket"});
bookmark = cm.setBookmark(Pos(1, 5));
cm.operation(function(){
cm.replaceRange("foo", Pos(0, 2));
cm.replaceRange("bar\nbaz\nbug\n", Pos(2, 0), Pos(3, 0));
});
var v1 = cm.getValue();
cm.setValue("");
eq(marker1.find(), null); eq(marker2.find(), null); eq(bookmark.find(), null);
cm.undo();
eqPos(bookmark.find(), {line: 1, ch: 5});
cm.undo(); cm.undo();
eqPos(bookmark.find(), Pos(1, 5), "still there");
cm.undo();
var m1Pos = marker1.find(), m2Pos = marker2.find();
eqPos(m1Pos.from, {line: 0, ch: 1}); eqPos(m1Pos.to, {line: 0, ch: 3});
eqPos(m2Pos.from, {line: 0, ch: 0}); eqPos(m2Pos.to, {line: 2, ch: 1});
eqPos(bookmark.find(), {line: 1, ch: 5});
eqPos(m1Pos.from, Pos(0, 1)); eqPos(m1Pos.to, Pos(0, 3));
eqPos(m2Pos.from, Pos(0, 0)); eqPos(m2Pos.to, Pos(2, 1));
eqPos(bookmark.find(), Pos(1, 5));
cm.redo(); cm.redo();
eq(bookmark.find(), null);
cm.undo();
eqPos(bookmark.find(), Pos(1, 5));
eq(cm.getValue(), v1);
}, {value: "1234\n56789\n00\n"});
testCM("markTextStayGone", function(cm) {
var m1 = cm.markText(Pos(0, 0), Pos(0, 1));
cm.replaceRange("hi", Pos(0, 2));
m1.clear();
cm.undo();
eq(m1.find(), null);
}, {value: "hello"});
testCM("undoPreservesNewMarks", function(cm) {
cm.markText(Pos(0, 3), Pos(0, 4));
cm.markText(Pos(1, 1), Pos(1, 3));
cm.replaceRange("", Pos(0, 3), Pos(3, 1));
var mBefore = cm.markText(Pos(0, 0), Pos(0, 1));
var mAfter = cm.markText(Pos(0, 5), Pos(0, 6));
var mAround = cm.markText(Pos(0, 2), Pos(0, 4));
cm.undo();
eqPos(mBefore.find().from, Pos(0, 0));
eqPos(mBefore.find().to, Pos(0, 1));
eqPos(mAfter.find().from, Pos(3, 3));
eqPos(mAfter.find().to, Pos(3, 4));
eqPos(mAround.find().from, Pos(0, 2));
eqPos(mAround.find().to, Pos(3, 2));
var found = cm.findMarksAt(Pos(2, 2));
eq(found.length, 1);
eq(found[0], mAround);
}, {value: "aaaa\nbbbb\ncccc\ndddd"});
testCM("markClearBetween", function(cm) {
cm.setValue("aaa\nbbb\nccc\nddd\n");
cm.markText({line: 0, ch: 0}, {line: 2}, "foo");
cm.replaceRange("aaa\nbbb\nccc", {line: 0, ch: 0}, {line: 2});
eq(cm.findMarksAt({line: 1, ch: 1}).length, 0);
cm.markText(Pos(0, 0), Pos(2));
cm.replaceRange("aaa\nbbb\nccc", Pos(0, 0), Pos(2));
eq(cm.findMarksAt(Pos(1, 1)).length, 0);
});
testCM("bookmark", function(cm) {
function p(v) { return v && {line: v[0], ch: v[1]}; }
function p(v) { return v && Pos(v[0], v[1]); }
forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]},

@@ -341,3 +476,3 @@ {a: [1, 1], b: [1, 1], c: "xx", d: [1, 7]},

cm.setValue("1234567890\n1234567890\n1234567890");
var b = cm.setBookmark(p(test.bm) || {line: 1, ch: 5});
var b = cm.setBookmark(p(test.bm) || Pos(1, 5));
cm.replaceRange(test.c, p(test.a), p(test.b));

@@ -348,2 +483,29 @@ eqPos(b.find(), p(test.d));

testCM("bookmarkInsertLeft", function(cm) {
var br = cm.setBookmark(Pos(0, 2), {insertLeft: false});
var bl = cm.setBookmark(Pos(0, 2), {insertLeft: true});
cm.setCursor(Pos(0, 2));
cm.replaceSelection("hi");
eqPos(br.find(), Pos(0, 2));
eqPos(bl.find(), Pos(0, 4));
cm.replaceRange("", Pos(0, 4), Pos(0, 5));
cm.replaceRange("", Pos(0, 2), Pos(0, 4));
cm.replaceRange("", Pos(0, 1), Pos(0, 2));
// Verify that deleting next to bookmarks doesn't kill them
eqPos(br.find(), Pos(0, 1));
eqPos(bl.find(), Pos(0, 1));
}, {value: "abcdef"});
testCM("getAllMarks", function(cm) {
addDoc(cm, 10, 10);
var m1 = cm.setBookmark(Pos(0, 2));
var m2 = cm.markText(Pos(0, 2), Pos(3, 2));
var m3 = cm.markText(Pos(1, 2), Pos(1, 8));
var m4 = cm.markText(Pos(8, 0), Pos(9, 0));
eq(cm.getAllMarks().length, 4);
m1.clear();
m3.clear();
eq(cm.getAllMarks().length, 2);
});
testCM("bug577", function(cm) {

@@ -359,20 +521,21 @@ cm.setValue("a\nb");

addDoc(cm, 200, 200);
cm.setCursor({line: 100, ch: 180});
cm.setCursor(Pos(100, 180));
var info = cm.getScrollInfo();
is(info.x > 0 && info.y > 0);
cm.setCursor({line: 0, ch: 0});
is(info.left > 0 && info.top > 0);
cm.setCursor(Pos(0, 0));
info = cm.getScrollInfo();
is(info.x == 0 && info.y == 0, "scrolled clean to top");
cm.setCursor({line: 100, ch: 180});
cm.setCursor({line: 199, ch: 0});
is(info.left == 0 && info.top == 0, "scrolled clean to top");
cm.setCursor(Pos(100, 180));
cm.setCursor(Pos(199, 0));
info = cm.getScrollInfo();
is(info.x == 0 && info.y > info.height - 100, "scrolled clean to bottom");
is(info.left == 0 && info.top + 2 > info.height - cm.getScrollerElement().clientHeight, "scrolled clean to bottom");
});
testCM("selectionPos", function(cm) {
if (phantom) return;
cm.setSize(100, 100);
addDoc(cm, 200, 100);
cm.setSelection({line: 1, ch: 100}, {line: 98, ch: 100});
var lineWidth = cm.charCoords({line: 0, ch: 200}, "local").x;
var lineHeight = cm.charCoords({line: 1}).y - cm.charCoords({line: 0}).y;
cm.setSelection(Pos(1, 100), Pos(98, 100));
var lineWidth = cm.charCoords(Pos(0, 200), "local").left;
var lineHeight = (cm.charCoords(Pos(99)).top - cm.charCoords(Pos(0)).top) / 100;
cm.scrollTo(0, 0);

@@ -389,3 +552,3 @@ var selElt = byClassName(cm.getWrapperElement(), "CodeMirror-selected");

sawMiddle = true;
is(box.bottom - box.top > 95 * lineHeight, "middle high");
is(box.bottom - box.top > 90 * lineHeight, "middle high");
is(width > .9 * lineWidth, "middle wide");

@@ -400,3 +563,3 @@ } else {

sawTop = true;
is(box.top - outer.top < 2 * lineHeight, "top above");
is(box.top - outer.top < 2.1 * lineHeight, "top above");
}

@@ -406,8 +569,8 @@ }

is(sawTop && sawBottom && sawMiddle, "all parts");
}, null, ie_lt8);
}, null);
testCM("restoreHistory", function(cm) {
cm.setValue("abc\ndef");
cm.compoundChange(function() {cm.setLine(1, "hello");});
cm.compoundChange(function() {cm.setLine(0, "goop");});
cm.setLine(1, "hello");
cm.setLine(0, "goop");
cm.undo();

@@ -433,6 +596,7 @@ var storedVal = cm.getValue(), storedHist = cm.getHistory();

document.body.removeChild(dummy);
if (scrollbarWidth < 2) return;
cm.setSize(null, 100);
addDoc(cm, 1, 300);
var wrap = cm.getWrapperElement();
is(wrap.offsetWidth - byClassName(wrap, "CodeMirror-lines")[0].offsetWidth <= scrollbarWidth);
is(wrap.offsetWidth - byClassName(wrap, "CodeMirror-lines")[0].offsetWidth <= scrollbarWidth * 1.5);
});

@@ -450,48 +614,195 @@

cm.setSize(100, 100);
is(cm.getWrapperElement().offsetWidth, 100);
is(cm.getWrapperElement().offsetHeight, 100);
var wrap = cm.getWrapperElement();
is(wrap.offsetWidth, 100);
is(wrap.offsetHeight, 100);
cm.setSize("100%", "3em");
is(cm.getWrapperElement().style.width, "100%");
is(cm.getScrollerElement().style.height, "3em");
is(wrap.style.width, "100%");
is(wrap.style.height, "3em");
cm.setSize(null, 40);
is(cm.getWrapperElement().style.width, "100%");
is(cm.getScrollerElement().style.height, "40px");
is(wrap.style.width, "100%");
is(wrap.style.height, "40px");
});
testCM("hiddenLines", function(cm) {
function foldLines(cm, start, end, autoClear) {
return cm.markText(Pos(start, 0), Pos(end - 1), {
inclusiveLeft: true,
inclusiveRight: true,
collapsed: true,
clearOnEnter: autoClear
});
}
testCM("collapsedLines", function(cm) {
addDoc(cm, 4, 10);
cm.hideLine(4);
cm.setCursor({line: 3, ch: 0});
var range = foldLines(cm, 4, 5), cleared = 0;
CodeMirror.on(range, "clear", function() {cleared++;});
cm.setCursor(Pos(3, 0));
CodeMirror.commands.goLineDown(cm);
eqPos(cm.getCursor(), {line: 5, ch: 0});
eqPos(cm.getCursor(), Pos(5, 0));
cm.setLine(3, "abcdefg");
cm.setCursor({line: 3, ch: 6});
cm.setCursor(Pos(3, 6));
CodeMirror.commands.goLineDown(cm);
eqPos(cm.getCursor(), {line: 5, ch: 4});
eqPos(cm.getCursor(), Pos(5, 4));
cm.setLine(3, "ab");
cm.setCursor({line: 3, ch: 2});
cm.setCursor(Pos(3, 2));
CodeMirror.commands.goLineDown(cm);
eqPos(cm.getCursor(), {line: 5, ch: 2});
eqPos(cm.getCursor(), Pos(5, 2));
cm.operation(function() {range.clear(); range.clear();});
eq(cleared, 1);
});
testCM("collapsedRangeCoordsChar", function(cm) {
var pos_1_3 = cm.charCoords(Pos(1, 3));
pos_1_3.left += 2; pos_1_3.top += 2;
var opts = {collapsed: true, inclusiveLeft: true, inclusiveRight: true};
var m1 = cm.markText(Pos(0, 0), Pos(2, 0), opts);
eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
m1.clear();
var m1 = cm.markText(Pos(0, 0), Pos(1, 1), opts);
var m2 = cm.markText(Pos(1, 1), Pos(2, 0), opts);
eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
m1.clear(); m2.clear();
var m1 = cm.markText(Pos(0, 0), Pos(1, 6), opts);
eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
}, {value: "123456\nabcdef\nghijkl\nmnopqr\n"});
testCM("hiddenLinesAutoUnfold", function(cm) {
var range = foldLines(cm, 1, 3, true), cleared = 0;
CodeMirror.on(range, "clear", function() {cleared++;});
cm.setCursor(Pos(3, 0));
eq(cleared, 0);
cm.execCommand("goCharLeft");
eq(cleared, 1);
range = foldLines(cm, 1, 3, true);
CodeMirror.on(range, "clear", function() {cleared++;});
eqPos(cm.getCursor(), Pos(3, 0));
cm.setCursor(Pos(0, 3));
cm.execCommand("goCharRight");
eq(cleared, 2);
}, {value: "abc\ndef\nghi\njkl"});
testCM("hiddenLinesSelectAll", function(cm) { // Issue #484
addDoc(cm, 4, 20);
for (var i = 0; i < 20; ++i)
if (i != 10) cm.hideLine(i);
foldLines(cm, 0, 10);
foldLines(cm, 11, 20);
CodeMirror.commands.selectAll(cm);
eqPos(cm.getCursor(true), {line: 10, ch: 0});
eqPos(cm.getCursor(false), {line: 10, ch: 4});
eqPos(cm.getCursor(true), Pos(10, 0));
eqPos(cm.getCursor(false), Pos(10, 4));
});
testCM("everythingFolded", function(cm) {
addDoc(cm, 2, 2);
function enterPress() {
cm.triggerOnKeyDown({type: "keydown", keyCode: 13, preventDefault: function(){}, stopPropagation: function(){}});
}
var fold = foldLines(cm, 0, 2);
enterPress();
eq(cm.getValue(), "xx\nxx");
fold.clear();
fold = foldLines(cm, 0, 2, true);
eq(fold.find(), null);
enterPress();
eq(cm.getValue(), "\nxx\nxx");
});
testCM("structuredFold", function(cm) {
addDoc(cm, 4, 8);
var range = cm.markText(Pos(1, 2), Pos(6, 2), {
replacedWith: document.createTextNode("Q")
});
cm.setCursor(0, 3);
CodeMirror.commands.goLineDown(cm);
eqPos(cm.getCursor(), Pos(6, 2));
CodeMirror.commands.goCharLeft(cm);
eqPos(cm.getCursor(), Pos(1, 2));
CodeMirror.commands.delCharAfter(cm);
eq(cm.getValue(), "xxxx\nxxxx\nxxxx");
addDoc(cm, 4, 8);
range = cm.markText(Pos(1, 2), Pos(6, 2), {
replacedWith: document.createTextNode("x"),
clearOnEnter: true
});
var cleared = 0;
CodeMirror.on(range, "clear", function(){++cleared;});
cm.setCursor(0, 3);
CodeMirror.commands.goLineDown(cm);
eqPos(cm.getCursor(), Pos(6, 2));
CodeMirror.commands.goCharLeft(cm);
eqPos(cm.getCursor(), Pos(6, 1));
eq(cleared, 1);
range.clear();
eq(cleared, 1);
range = cm.markText(Pos(1, 2), Pos(6, 2), {
replacedWith: document.createTextNode("Q"),
clearOnEnter: true
});
range.clear();
cm.setCursor(1, 2);
CodeMirror.commands.goCharRight(cm);
eqPos(cm.getCursor(), Pos(1, 3));
}, null);
testCM("nestedFold", function(cm) {
addDoc(cm, 10, 3);
function fold(ll, cl, lr, cr) {
return cm.markText(Pos(ll, cl), Pos(lr, cr), {collapsed: true});
}
var inner1 = fold(0, 6, 1, 3), inner2 = fold(0, 2, 1, 8), outer = fold(0, 1, 2, 3), inner0 = fold(0, 5, 0, 6);
cm.setCursor(0, 1);
CodeMirror.commands.goCharRight(cm);
eqPos(cm.getCursor(), Pos(2, 3));
inner0.clear();
CodeMirror.commands.goCharLeft(cm);
eqPos(cm.getCursor(), Pos(0, 1));
outer.clear();
CodeMirror.commands.goCharRight(cm);
eqPos(cm.getCursor(), Pos(0, 2));
CodeMirror.commands.goCharRight(cm);
eqPos(cm.getCursor(), Pos(1, 8));
inner2.clear();
CodeMirror.commands.goCharLeft(cm);
eqPos(cm.getCursor(), Pos(1, 7));
cm.setCursor(0, 5);
CodeMirror.commands.goCharRight(cm);
eqPos(cm.getCursor(), Pos(0, 6));
CodeMirror.commands.goCharRight(cm);
eqPos(cm.getCursor(), Pos(1, 3));
});
testCM("badNestedFold", function(cm) {
addDoc(cm, 4, 4);
cm.markText(Pos(0, 2), Pos(3, 2), {collapsed: true});
var caught;
try {cm.markText(Pos(0, 1), Pos(0, 3), {collapsed: true});}
catch(e) {caught = e;}
is(caught instanceof Error, "no error");
is(/overlap/i.test(caught.message), "wrong error");
});
testCM("inlineWidget", function(cm) {
var w = cm.setBookmark(Pos(0, 2), {widget: document.createTextNode("uu")});
cm.setCursor(0, 2);
CodeMirror.commands.goLineDown(cm);
eqPos(cm.getCursor(), Pos(1, 4));
cm.setCursor(0, 2);
cm.replaceSelection("hi");
eqPos(w.find(), Pos(0, 2));
cm.setCursor(0, 1);
cm.replaceSelection("ay");
eqPos(w.find(), Pos(0, 4));
eq(cm.getLine(0), "uayuhiuu");
}, {value: "uuuu\nuuuuuu"});
testCM("wrappingAndResizing", function(cm) {
cm.setSize(null, "auto");
cm.setOption("lineWrapping", true);
var wrap = cm.getWrapperElement(), h0 = wrap.offsetHeight, w = 50;
var wrap = cm.getWrapperElement(), h0 = wrap.offsetHeight;
var doc = "xxx xxx xxx xxx xxx";
cm.setValue(doc);
for (var step = 10;; w += step) {
for (var step = 10, w = cm.charCoords(Pos(0, 18), "div").right;; w += step) {
cm.setSize(w);
if (wrap.offsetHeight == h0) {
if (wrap.offsetHeight <= h0 * (opera_lt10 ? 1.2 : 1.5)) {
if (step == 10) { w -= 10; step = 1; }
else { w--; break; }
else break;
}

@@ -501,6 +812,6 @@ }

// line doesn't cause wrapping to happen.
cm.setCursor({line: 0, ch: doc.length});
cm.setCursor(Pos(0, doc.length));
eq(wrap.offsetHeight, h0);
cm.replaceSelection("x");
is(wrap.offsetHeight > h0);
is(wrap.offsetHeight > h0, "wrapping happens");
// Now add a max-height and, in a document consisting of

@@ -510,8 +821,8 @@ // almost-wrapped lines, go over it so that a scrollbar appears.

cm.getScrollerElement().style.maxHeight = "100px";
cm.replaceRange("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n!\n", {line: 2, ch: 0});
forEach([{line: 0, ch: doc.length}, {line: 0, ch: doc.length - 1},
{line: 0, ch: 0}, {line: 1, ch: doc.length}, {line: 1, ch: doc.length - 1}],
cm.replaceRange("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n!\n", Pos(2, 0));
forEach([Pos(0, doc.length), Pos(0, doc.length - 1),
Pos(0, 0), Pos(1, doc.length), Pos(1, doc.length - 1)],
function(pos) {
var coords = cm.charCoords(pos);
eqPos(pos, cm.coordsChar({x: coords.x + 2, y: coords.y + 2}));
eqPos(pos, cm.coordsChar({left: coords.left + 2, top: coords.top + 5}));
});

@@ -523,17 +834,17 @@ }, null, ie_lt8);

var inner = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild;
var w = 20, lh = inner.offsetHeight;
for (var step = 10;; w += step) {
var lh = inner.offsetHeight;
for (var step = 10, w = cm.charCoords(Pos(0, 7), "div").right;; w += step) {
cm.setSize(w);
if (inner.offsetHeight < 2.5 * lh) {
if (step == 10) { w -= 10; step = 1; }
else { break; }
else break;
}
}
cm.setValue(cm.getValue() + "\n\n");
var endPos = cm.charCoords({line: 0, ch: 18}, "local");
is(endPos.y > lh * .8, "not at top");
is(endPos.x > w - 20, "not at right");
endPos = cm.charCoords({line: 0, ch: 18});
eqPos(cm.coordsChar({x: endPos.x, y: endPos.y + 2}), {line: 0, ch: 18});
}, {mode: "text/html", value: "<!-- foo barrr -->", lineWrapping: true}, ie_lt8);
var endPos = cm.charCoords(Pos(0, 18), "local");
is(endPos.top > lh * .8, "not at top");
is(endPos.left > w - 20, "not at right");
endPos = cm.charCoords(Pos(0, 18));
eqPos(cm.coordsChar({left: endPos.left, top: endPos.top + 5}), Pos(0, 18));
}, {mode: "text/html", value: "<!-- foo barrr -->", lineWrapping: true}, ie_lt8 || opera_lt10);

@@ -544,3 +855,3 @@ testCM("scrollVerticallyAndHorizontally", function(cm) {

cm.setCursor(39);
var wrap = cm.getWrapperElement(), bar = byClassName(wrap, "CodeMirror-scrollbar")[0];
var wrap = cm.getWrapperElement(), bar = byClassName(wrap, "CodeMirror-vscrollbar")[0];
is(bar.offsetHeight < wrap.offsetHeight, "vertical scrollbar limited by horizontal one");

@@ -551,21 +862,21 @@ var cursorBox = byClassName(wrap, "CodeMirror-cursor")[0].getBoundingClientRect();

"bottom line visible");
}, {gutter: true});
}, {lineNumbers: true});
testCM("moveV stuck", function(cm) {
testCM("moveVstuck", function(cm) {
var lines = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild, h0 = lines.offsetHeight;
var val = "fooooooooooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar\n";
cm.setValue(val);
for (var w = 50;; w += 5) {
for (var w = cm.charCoords(Pos(0, 26), "div").right * 2.8;; w += 5) {
cm.setSize(w);
if (lines.offsetHeight <= 3 * h0) break;
if (lines.offsetHeight <= 3.5 * h0) break;
}
cm.setCursor({line: 0, ch: val.length - 1});
cm.setCursor(Pos(0, val.length - 1));
cm.moveV(-1, "line");
eqPos(cm.getCursor(), {line: 0, ch: 26});
}, {lineWrapping: true}, ie_lt8);
eqPos(cm.getCursor(), Pos(0, 26));
}, {lineWrapping: true}, ie_lt8 || opera_lt10);
testCM("clickTab", function(cm) {
var p0 = cm.charCoords({line: 0, ch: 0}), p1 = cm.charCoords({line: 0, ch: 1});
eqPos(cm.coordsChar({x: p0.x + 5, y: p0.y + 5}), {line: 0, ch: 0});
eqPos(cm.coordsChar({x: p1.x - 5, y: p1.y + 5}), {line: 0, ch: 1});
var p0 = cm.charCoords(Pos(0, 0));
eqPos(cm.coordsChar({left: p0.left + 5, top: p0.top + 5}), Pos(0, 0));
eqPos(cm.coordsChar({left: p0.right - 5, top: p0.top + 5}), Pos(0, 1));
}, {value: "\t\n\n", lineWrapping: true, tabSize: 8});

@@ -618,48 +929,76 @@

fakeKey(null, 9);
});
}, null, window.opera && mac);
testCM("wordMovementCommands", function(cm) {
cm.execCommand("goWordLeft");
eqPos(cm.getCursor(), {line: 0, ch: 0});
eqPos(cm.getCursor(), Pos(0, 0));
cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
eqPos(cm.getCursor(), {line: 0, ch: 7});
eqPos(cm.getCursor(), Pos(0, 7));
cm.execCommand("goWordLeft");
eqPos(cm.getCursor(), {line: 0, ch: 5});
eqPos(cm.getCursor(), Pos(0, 5));
cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
eqPos(cm.getCursor(), {line: 0, ch: 12});
eqPos(cm.getCursor(), Pos(0, 12));
cm.execCommand("goWordLeft");
eqPos(cm.getCursor(), {line: 0, ch: 9});
eqPos(cm.getCursor(), Pos(0, 9));
cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
eqPos(cm.getCursor(), {line: 1, ch: 1});
eqPos(cm.getCursor(), Pos(0, 24));
cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
eqPos(cm.getCursor(), Pos(1, 9));
cm.execCommand("goWordRight");
eqPos(cm.getCursor(), {line: 1, ch: 9});
cm.execCommand("goWordRight");
eqPos(cm.getCursor(), {line: 1, ch: 13});
eqPos(cm.getCursor(), Pos(1, 13));
cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
eqPos(cm.getCursor(), {line: 2, ch: 0});
eqPos(cm.getCursor(), Pos(2, 0));
}, {value: "this is (the) firstline.\na foo12\u00e9\u00f8\u00d7bar\n"});
testCM("groupMovementCommands", function(cm) {
cm.execCommand("goGroupLeft");
eqPos(cm.getCursor(), Pos(0, 0));
cm.execCommand("goGroupRight");
eqPos(cm.getCursor(), Pos(0, 4));
cm.execCommand("goGroupRight");
eqPos(cm.getCursor(), Pos(0, 7));
cm.execCommand("goGroupRight");
eqPos(cm.getCursor(), Pos(0, 10));
cm.execCommand("goGroupLeft");
eqPos(cm.getCursor(), Pos(0, 7));
cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");
eqPos(cm.getCursor(), Pos(0, 15));
cm.setCursor(Pos(0, 17));
cm.execCommand("goGroupLeft");
eqPos(cm.getCursor(), Pos(0, 16));
cm.execCommand("goGroupLeft");
eqPos(cm.getCursor(), Pos(0, 14));
cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");
eqPos(cm.getCursor(), Pos(0, 20));
cm.execCommand("goGroupRight");
eqPos(cm.getCursor(), Pos(1, 5));
cm.execCommand("goGroupLeft"); cm.execCommand("goGroupLeft");
eqPos(cm.getCursor(), Pos(1, 0));
cm.execCommand("goGroupLeft");
eqPos(cm.getCursor(), Pos(0, 16));
}, {value: "booo ba---quux. ffff\n abc d"});
testCM("charMovementCommands", function(cm) {
cm.execCommand("goCharLeft"); cm.execCommand("goColumnLeft");
eqPos(cm.getCursor(), {line: 0, ch: 0});
eqPos(cm.getCursor(), Pos(0, 0));
cm.execCommand("goCharRight"); cm.execCommand("goCharRight");
eqPos(cm.getCursor(), {line: 0, ch: 2});
cm.setCursor({line: 1, ch: 0});
eqPos(cm.getCursor(), Pos(0, 2));
cm.setCursor(Pos(1, 0));
cm.execCommand("goColumnLeft");
eqPos(cm.getCursor(), {line: 1, ch: 0});
eqPos(cm.getCursor(), Pos(1, 0));
cm.execCommand("goCharLeft");
eqPos(cm.getCursor(), {line: 0, ch: 5});
eqPos(cm.getCursor(), Pos(0, 5));
cm.execCommand("goColumnRight");
eqPos(cm.getCursor(), {line: 0, ch: 5});
eqPos(cm.getCursor(), Pos(0, 5));
cm.execCommand("goCharRight");
eqPos(cm.getCursor(), {line: 1, ch: 0});
eqPos(cm.getCursor(), Pos(1, 0));
cm.execCommand("goLineEnd");
eqPos(cm.getCursor(), {line: 1, ch: 5});
eqPos(cm.getCursor(), Pos(1, 5));
cm.execCommand("goLineStartSmart");
eqPos(cm.getCursor(), {line: 1, ch: 1});
eqPos(cm.getCursor(), Pos(1, 1));
cm.execCommand("goLineStartSmart");
eqPos(cm.getCursor(), {line: 1, ch: 0});
cm.setCursor({line: 2, ch: 0});
eqPos(cm.getCursor(), Pos(1, 0));
cm.setCursor(Pos(2, 0));
cm.execCommand("goCharRight"); cm.execCommand("goColumnRight");
eqPos(cm.getCursor(), {line: 2, ch: 0});
eqPos(cm.getCursor(), Pos(2, 0));
}, {value: "line1\n ine2\n"});

@@ -669,20 +1008,21 @@

cm.execCommand("goLineUp");
eqPos(cm.getCursor(), {line: 0, ch: 0});
eqPos(cm.getCursor(), Pos(0, 0));
cm.execCommand("goLineDown");
eqPos(cm.getCursor(), {line: 1, ch: 0});
cm.setCursor({line: 1, ch: 12});
if (!phantom) // This fails in PhantomJS, though not in a real Webkit
eqPos(cm.getCursor(), Pos(1, 0));
cm.setCursor(Pos(1, 12));
cm.execCommand("goLineDown");
eqPos(cm.getCursor(), {line: 2, ch: 5});
eqPos(cm.getCursor(), Pos(2, 5));
cm.execCommand("goLineDown");
eqPos(cm.getCursor(), {line: 3, ch: 0});
eqPos(cm.getCursor(), Pos(3, 0));
cm.execCommand("goLineUp");
eqPos(cm.getCursor(), {line: 2, ch: 5});
eqPos(cm.getCursor(), Pos(2, 5));
cm.execCommand("goLineUp");
eqPos(cm.getCursor(), {line: 1, ch: 12});
eqPos(cm.getCursor(), Pos(1, 12));
cm.execCommand("goPageDown");
eqPos(cm.getCursor(), {line: 5, ch: 0});
eqPos(cm.getCursor(), Pos(5, 0));
cm.execCommand("goPageDown"); cm.execCommand("goLineDown");
eqPos(cm.getCursor(), {line: 5, ch: 0});
eqPos(cm.getCursor(), Pos(5, 0));
cm.execCommand("goPageUp");
eqPos(cm.getCursor(), {line: 0, ch: 0});
eqPos(cm.getCursor(), Pos(0, 0));
}, {value: "line1\nlong long line2\nline3\n\nline5\n"});

@@ -692,3 +1032,3 @@

cm.setSize(120);
cm.setCursor({line: 0, ch: 5});
cm.setCursor(Pos(0, 5));
cm.execCommand("goLineDown");

@@ -706,1 +1046,389 @@ eq(cm.getCursor().line, 0);

lineWrapping: true});
testCM("rtlMovement", function(cm) {
forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج",
"خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر"], function(line) {
var inv = line.charAt(0) == "خ";
cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart");
var cursor = byClassName(cm.getWrapperElement(), "CodeMirror-cursor")[0];
var prevX = cursor.offsetLeft, prevY = cursor.offsetTop;
for (var i = 0; i <= line.length; ++i) {
cm.execCommand("goCharRight");
if (i == line.length) is(cursor.offsetTop > prevY, "next line");
else is(cursor.offsetLeft > prevX, "moved right");
prevX = cursor.offsetLeft; prevY = cursor.offsetTop;
}
cm.setCursor(0, 0); cm.execCommand(inv ? "goLineStart" : "goLineEnd");
prevX = cursor.offsetLeft;
for (var i = 0; i < line.length; ++i) {
cm.execCommand("goCharLeft");
is(cursor.offsetLeft < prevX, "moved left");
prevX = cursor.offsetLeft;
}
});
}, {rtlMoveVisually: true});
// Verify that updating a line clears its bidi ordering
testCM("bidiUpdate", function(cm) {
cm.setCursor(Pos(0, 2));
cm.replaceSelection("خحج", "start");
cm.execCommand("goCharRight");
eqPos(cm.getCursor(), Pos(0, 4));
}, {value: "abcd\n"});
testCM("movebyTextUnit", function(cm) {
cm.setValue("בְּרֵאשִ\ńéée\n");
cm.execCommand("goLineEnd");
for (var i = 0; i < 4; ++i) cm.execCommand("goCharRight");
eqPos(cm.getCursor(), Pos(0, 0));
cm.execCommand("goCharRight");
eqPos(cm.getCursor(), Pos(1, 0));
cm.execCommand("goCharRight");
cm.execCommand("goCharRight");
eqPos(cm.getCursor(), Pos(1, 3));
cm.execCommand("goCharRight");
cm.execCommand("goCharRight");
eqPos(cm.getCursor(), Pos(1, 6));
});
testCM("lineChangeEvents", function(cm) {
addDoc(cm, 3, 5);
var log = [], want = ["ch 0", "ch 1", "del 2", "ch 0", "ch 0", "del 1", "del 3", "del 4"];
for (var i = 0; i < 5; ++i) {
CodeMirror.on(cm.getLineHandle(i), "delete", function(i) {
return function() {log.push("del " + i);};
}(i));
CodeMirror.on(cm.getLineHandle(i), "change", function(i) {
return function() {log.push("ch " + i);};
}(i));
}
cm.replaceRange("x", Pos(0, 1));
cm.replaceRange("xy", Pos(1, 1), Pos(2));
cm.replaceRange("foo\nbar", Pos(0, 1));
cm.replaceRange("", Pos(0, 0), Pos(cm.lineCount()));
eq(log.length, want.length, "same length");
for (var i = 0; i < log.length; ++i)
eq(log[i], want[i]);
});
testCM("scrollEntirelyToRight", function(cm) {
if (phantom) return;
addDoc(cm, 500, 2);
cm.setCursor(Pos(0, 500));
var wrap = cm.getWrapperElement(), cur = byClassName(wrap, "CodeMirror-cursor")[0];
is(wrap.getBoundingClientRect().right > cur.getBoundingClientRect().left);
});
testCM("lineWidgets", function(cm) {
addDoc(cm, 500, 3);
var last = cm.charCoords(Pos(2, 0));
var node = document.createElement("div");
node.innerHTML = "hi";
var widget = cm.addLineWidget(1, node);
is(last.top < cm.charCoords(Pos(2, 0)).top, "took up space");
cm.setCursor(Pos(1, 1));
cm.execCommand("goLineDown");
eqPos(cm.getCursor(), Pos(2, 1));
cm.execCommand("goLineUp");
eqPos(cm.getCursor(), Pos(1, 1));
});
testCM("lineWidgetFocus", function(cm) {
var place = document.getElementById("testground");
place.className = "offscreen";
try {
addDoc(cm, 500, 10);
var node = document.createElement("input");
var widget = cm.addLineWidget(1, node);
node.focus();
eq(document.activeElement, node);
cm.replaceRange("new stuff", Pos(1, 0));
eq(document.activeElement, node);
} finally {
place.className = "";
}
});
testCM("getLineNumber", function(cm) {
addDoc(cm, 2, 20);
var h1 = cm.getLineHandle(1);
eq(cm.getLineNumber(h1), 1);
cm.replaceRange("hi\nbye\n", Pos(0, 0));
eq(cm.getLineNumber(h1), 3);
cm.setValue("");
eq(cm.getLineNumber(h1), null);
});
testCM("jumpTheGap", function(cm) {
var longLine = "abcdef ghiklmnop qrstuvw xyz ";
longLine += longLine; longLine += longLine; longLine += longLine;
cm.setLine(2, longLine);
cm.setSize("200px", null);
cm.getWrapperElement().style.lineHeight = 2;
cm.refresh();
cm.setCursor(Pos(0, 1));
cm.execCommand("goLineDown");
eqPos(cm.getCursor(), Pos(1, 1));
cm.execCommand("goLineDown");
eqPos(cm.getCursor(), Pos(2, 1));
cm.execCommand("goLineDown");
eq(cm.getCursor().line, 2);
is(cm.getCursor().ch > 1);
cm.execCommand("goLineUp");
eqPos(cm.getCursor(), Pos(2, 1));
cm.execCommand("goLineUp");
eqPos(cm.getCursor(), Pos(1, 1));
var node = document.createElement("div");
node.innerHTML = "hi"; node.style.height = "30px";
cm.addLineWidget(0, node);
cm.addLineWidget(1, node.cloneNode(true), {above: true});
cm.setCursor(Pos(0, 2));
cm.execCommand("goLineDown");
eqPos(cm.getCursor(), Pos(1, 2));
cm.execCommand("goLineUp");
eqPos(cm.getCursor(), Pos(0, 2));
}, {lineWrapping: true, value: "abc\ndef\nghi\njkl\n"});
testCM("addLineClass", function(cm) {
function cls(line, text, bg, wrap) {
var i = cm.lineInfo(line);
eq(i.textClass, text);
eq(i.bgClass, bg);
eq(i.wrapClass, wrap);
}
cm.addLineClass(0, "text", "foo");
cm.addLineClass(0, "text", "bar");
cm.addLineClass(1, "background", "baz");
cm.addLineClass(1, "wrap", "foo");
cls(0, "foo bar", null, null);
cls(1, null, "baz", "foo");
var lines = cm.display.lineDiv;
eq(byClassName(lines, "foo").length, 2);
eq(byClassName(lines, "bar").length, 1);
eq(byClassName(lines, "baz").length, 1);
cm.removeLineClass(0, "text", "foo");
cls(0, "bar", null, null);
cm.removeLineClass(0, "text", "foo");
cls(0, "bar", null, null);
cm.removeLineClass(0, "text", "bar");
cls(0, null, null, null);
cm.addLineClass(1, "wrap", "quux");
cls(1, null, "baz", "foo quux");
cm.removeLineClass(1, "wrap");
cls(1, null, "baz", null);
}, {value: "hohoho\n"});
testCM("atomicMarker", function(cm) {
addDoc(cm, 10, 10);
function atom(ll, cl, lr, cr, li, ri) {
return cm.markText(Pos(ll, cl), Pos(lr, cr),
{atomic: true, inclusiveLeft: li, inclusiveRight: ri});
}
var m = atom(0, 1, 0, 5);
cm.setCursor(Pos(0, 1));
cm.execCommand("goCharRight");
eqPos(cm.getCursor(), Pos(0, 5));
cm.execCommand("goCharLeft");
eqPos(cm.getCursor(), Pos(0, 1));
m.clear();
m = atom(0, 0, 0, 5, true);
eqPos(cm.getCursor(), Pos(0, 5), "pushed out");
cm.execCommand("goCharLeft");
eqPos(cm.getCursor(), Pos(0, 5));
m.clear();
m = atom(8, 4, 9, 10, false, true);
cm.setCursor(Pos(9, 8));
eqPos(cm.getCursor(), Pos(8, 4), "set");
cm.execCommand("goCharRight");
eqPos(cm.getCursor(), Pos(8, 4), "char right");
cm.execCommand("goLineDown");
eqPos(cm.getCursor(), Pos(8, 4), "line down");
cm.execCommand("goCharLeft");
eqPos(cm.getCursor(), Pos(8, 3));
m.clear();
m = atom(1, 1, 3, 8);
cm.setCursor(Pos(2, 0));
eqPos(cm.getCursor(), Pos(3, 8));
cm.execCommand("goCharLeft");
eqPos(cm.getCursor(), Pos(1, 1));
cm.execCommand("goCharRight");
eqPos(cm.getCursor(), Pos(3, 8));
cm.execCommand("goLineUp");
eqPos(cm.getCursor(), Pos(1, 1));
cm.execCommand("goLineDown");
eqPos(cm.getCursor(), Pos(3, 8));
cm.execCommand("delCharBefore");
eq(cm.getValue().length, 80, "del chunk");
m = atom(3, 0, 5, 5);
cm.setCursor(Pos(3, 0));
cm.execCommand("delWordAfter");
eq(cm.getValue().length, 53, "del chunk");
});
testCM("readOnlyMarker", function(cm) {
function mark(ll, cl, lr, cr, at) {
return cm.markText(Pos(ll, cl), Pos(lr, cr),
{readOnly: true, atomic: at});
}
var m = mark(0, 1, 0, 4);
cm.setCursor(Pos(0, 2));
cm.replaceSelection("hi", "end");
eqPos(cm.getCursor(), Pos(0, 2));
eq(cm.getLine(0), "abcde");
cm.execCommand("selectAll");
cm.replaceSelection("oops");
eq(cm.getValue(), "oopsbcd");
cm.undo();
eqPos(m.find().from, Pos(0, 1));
eqPos(m.find().to, Pos(0, 4));
m.clear();
cm.setCursor(Pos(0, 2));
cm.replaceSelection("hi");
eq(cm.getLine(0), "abhicde");
eqPos(cm.getCursor(), Pos(0, 4));
m = mark(0, 2, 2, 2, true);
cm.setSelection(Pos(1, 1), Pos(2, 4));
cm.replaceSelection("t", "end");
eqPos(cm.getCursor(), Pos(2, 3));
eq(cm.getLine(2), "klto");
cm.execCommand("goCharLeft");
cm.execCommand("goCharLeft");
eqPos(cm.getCursor(), Pos(0, 2));
cm.setSelection(Pos(0, 1), Pos(0, 3));
cm.replaceSelection("xx");
eqPos(cm.getCursor(), Pos(0, 3));
eq(cm.getLine(0), "axxhicde");
}, {value: "abcde\nfghij\nklmno\n"});
testCM("dirtyBit", function(cm) {
eq(cm.isClean(), true);
cm.replaceSelection("boo");
eq(cm.isClean(), false);
cm.undo();
eq(cm.isClean(), true);
cm.replaceSelection("boo");
cm.replaceSelection("baz");
cm.undo();
eq(cm.isClean(), false);
cm.markClean();
eq(cm.isClean(), true);
cm.undo();
eq(cm.isClean(), false);
cm.redo();
eq(cm.isClean(), true);
});
testCM("addKeyMap", function(cm) {
function sendKey(code) {
cm.triggerOnKeyDown({type: "keydown", keyCode: code,
preventDefault: function(){}, stopPropagation: function(){}});
}
sendKey(39);
eqPos(cm.getCursor(), Pos(0, 1));
var test = 0;
var map1 = {Right: function() { ++test; }}, map2 = {Right: function() { test += 10; }}
cm.addKeyMap(map1);
sendKey(39);
eqPos(cm.getCursor(), Pos(0, 1));
eq(test, 1);
cm.addKeyMap(map2, true);
sendKey(39);
eq(test, 2);
cm.removeKeyMap(map1);
sendKey(39);
eq(test, 12);
cm.removeKeyMap(map2);
sendKey(39);
eq(test, 12);
eqPos(cm.getCursor(), Pos(0, 2));
cm.addKeyMap({Right: function() { test = 55; }, name: "mymap"});
sendKey(39);
eq(test, 55);
cm.removeKeyMap("mymap");
sendKey(39);
eqPos(cm.getCursor(), Pos(0, 3));
}, {value: "abc"});
testCM("findPosH", function(cm) {
forEach([{from: Pos(0, 0), to: Pos(0, 1), by: 1},
{from: Pos(0, 0), to: Pos(0, 0), by: -1, hitSide: true},
{from: Pos(0, 0), to: Pos(0, 4), by: 1, unit: "word"},
{from: Pos(0, 0), to: Pos(0, 8), by: 2, unit: "word"},
{from: Pos(0, 0), to: Pos(2, 0), by: 20, unit: "word", hitSide: true},
{from: Pos(0, 7), to: Pos(0, 5), by: -1, unit: "word"},
{from: Pos(0, 4), to: Pos(0, 8), by: 1, unit: "word"},
{from: Pos(1, 0), to: Pos(1, 18), by: 3, unit: "word"},
{from: Pos(1, 22), to: Pos(1, 5), by: -3, unit: "word"},
{from: Pos(1, 15), to: Pos(1, 10), by: -5},
{from: Pos(1, 15), to: Pos(1, 10), by: -5, unit: "column"},
{from: Pos(1, 15), to: Pos(1, 0), by: -50, unit: "column", hitSide: true},
{from: Pos(1, 15), to: Pos(1, 24), by: 50, unit: "column", hitSide: true},
{from: Pos(1, 15), to: Pos(2, 0), by: 50, hitSide: true}], function(t) {
var r = cm.findPosH(t.from, t.by, t.unit || "char");
eqPos(r, t.to);
eq(!!r.hitSide, !!t.hitSide);
});
}, {value: "line one\nline two.something.other\n"});
testCM("beforeChange", function(cm) {
cm.on("beforeChange", function(cm, change) {
var text = [];
for (var i = 0; i < change.text.length; ++i)
text.push(change.text[i].replace(/\s/g, "_"));
change.update(null, null, text);
});
cm.setValue("hello, i am a\nnew document\n");
eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");
CodeMirror.on(cm.getDoc(), "beforeChange", function(doc, change) {
if (change.from.line == 0) change.cancel();
});
cm.setValue("oops"); // Canceled
eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");
cm.replaceRange("hey hey hey", Pos(1, 0), Pos(2, 0));
eq(cm.getValue(), "hello,_i_am_a\nhey_hey_hey");
}, {value: "abcdefghijk"});
testCM("beforeSelectionChange", function(cm) {
function notAtEnd(cm, pos) {
var len = cm.getLine(pos.line).length;
if (!len || pos.ch == len) return Pos(pos.line, pos.ch - 1);
return pos;
}
cm.on("beforeSelectionChange", function(cm, sel) {
sel.head = notAtEnd(cm, sel.head);
sel.anchor = notAtEnd(cm, sel.anchor);
});
addDoc(cm, 10, 10);
cm.execCommand("goLineEnd");
eqPos(cm.getCursor(), Pos(0, 9));
cm.execCommand("selectAll");
eqPos(cm.getCursor("start"), Pos(0, 0));
eqPos(cm.getCursor("end"), Pos(9, 9));
});
testCM("change_removedText", function(cm) {
cm.setValue("abc\ndef");
var removedText;
cm.on("change", function(cm, change) {
removedText = [change.removed, change.next && change.next.removed];
});
cm.operation(function() {
cm.replaceRange("xyz", Pos(0, 0), Pos(1,1));
cm.replaceRange("123", Pos(0,0));
});
eq(removedText[0].join("\n"), "abc\nd");
eq(removedText[1].join("\n"), "");
cm.undo();
eq(removedText[0].join("\n"), "123");
eq(removedText[1].join("\n"), "xyz");
cm.redo();
eq(removedText[0].join("\n"), "abc\nd");
eq(removedText[1].join("\n"), "");
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc