@@ -1,68 +1,19 @@
(function() {
var mode = CodeMirror.getMode({tabSize: 1}, "css");
var mode = CodeMirror.getMode({indentUnit: 2}, "css");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1)); }

// Requires at least one media query
MT("atMediaEmpty",
"[def @media] [error {] }");

MT("atMediaMultiple",
"[def @media] [keyword not] [attribute screen] [operator and] ([property color]), [keyword not] [attribute print] [operator and] ([property color]) { }");

MT("atMediaCheckStack",
"[def @media] [attribute screen] { } [tag foo] { }");

MT("atMediaCheckStack",
"[def @media] [attribute screen] ([property color]) { } [tag foo] { }");

MT("atMediaPropertyOnly",
"[def @media] ([property color]) { } [tag foo] { }");

MT("atMediaCheckStackInvalidAttribute",
"[def @media] [attribute&error foobarhello] { [tag foo] { } }");

MT("atMediaCheckStackInvalidAttribute",
"[def @media] [attribute&error foobarhello] { } [tag foo] { }");

// 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("atMediaInvalidAnd",
"[def @media] [error and] [attribute screen] { }");

// 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("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("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("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("atMediaInvalidProperty",
"[def @media] [attribute screen] [operator and] ([error print]) { }");
"[def @media] [attribute screen] [keyword and] [error foobarhello] { }");

// Soft error, because "foobarhello" is not a known property or type.
MT("atMediaUnknownProperty",
"[def @media] [attribute screen] [operator and] ([property&error foobarhello]) { }");
"[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }");

// Make sure nesting works with media queries
MT("atMediaMaxWidthNested",
"[def @media] [attribute screen] [operator and] ([property max-width][operator :] [number 25px]) { [tag foo] { } }");
"[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }");

MT("tagSelector",
"[tag foo] { }");
@@ -74,69 +25,95 @@
"[builtin #foo] { [error #foo] }");

MT("tagSelectorUnclosed",
"[tag foo] { [property margin][operator :] [number 0] } [tag bar] { }");
"[tag foo] { [property margin]: [number 0] } [tag bar] { }");

MT("tagStringNoQuotes",
"[tag foo] { [property font-family][operator :] [variable-2 hello] [variable-2 world]; }");
"[tag foo] { [property font-family]: [variable hello] [variable world]; }");

MT("tagStringDouble",
"[tag foo] { [property font-family][operator :] [string \"hello world\"]; }");
"[tag foo] { [property font-family]: [string \"hello world\"]; }");

MT("tagStringSingle",
"[tag foo] { [property font-family][operator :] [string 'hello world']; }");
"[tag foo] { [property font-family]: [string 'hello world']; }");

MT("tagColorKeyword",
"[tag foo] {" +
"[property color][operator :] [keyword black];" +
"[property color][operator :] [keyword navy];" +
"[property color][operator :] [keyword yellow];" +
"}");
"[tag foo] {",
" [property color]: [keyword black];",
" [property color]: [keyword navy];",
" [property color]: [keyword yellow];",
"}");

MT("tagColorHex3",
"[tag foo] { [property background][operator :] [atom #fff]; }");
"[tag foo] { [property background]: [atom #fff]; }");

MT("tagColorHex6",
"[tag foo] { [property background][operator :] [atom #ffffff]; }");
"[tag foo] { [property background]: [atom #ffffff]; }");

MT("tagColorHex4",
"[tag foo] { [property background][operator :] [atom&error #ffff]; }");
"[tag foo] { [property background]: [atom&error #ffff]; }");

MT("tagColorHexInvalid",
"[tag foo] { [property background][operator :] [atom&error #ffg]; }");
"[tag foo] { [property background]: [atom&error #ffg]; }");

MT("tagNegativeNumber",
"[tag foo] { [property margin][operator :] [number -5px]; }");
"[tag foo] { [property margin]: [number -5px]; }");

MT("tagPositiveNumber",
"[tag foo] { [property padding][operator :] [number 5px]; }");
"[tag foo] { [property padding]: [number 5px]; }");

MT("tagVendor",
"[tag foo] { [meta -foo-][property box-sizing][operator :] [meta -foo-][string-2 border-box]; }");
"[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }");

MT("tagBogusProperty",
"[tag foo] { [property&error barhelloworld][operator :] [number 0]; }");
"[tag foo] { [property&error barhelloworld]: [number 0]; }");

MT("tagTwoProperties",
"[tag foo] { [property margin][operator :] [number 0]; [property padding][operator :] [number 0]; }");
"[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }");

MT("tagTwoPropertiesURL",
"[tag foo] { [property background][operator :] [string-2 url]([string //example.com/foo.png]); [property padding][operator :] [number 0]; }");
"[tag foo] { [property background]: [atom url]([string //example.com/foo.png]); [property padding]: [number 0]; }");

MT("commentSGML",
"[comment <!--comment-->]");

IT("tagSelector",
"strong, em [1 { background][2 : rgba][3 (255, 255, 0, .2][2 )][1 ;]}");

IT("atMedia",
"[1 @media { foo ][2 { ][1 } ]}");

IT("comma",
"foo [1 { font-family][2 : verdana, sans-serif][1 ; ]}");

IT("parentheses",
"foo [1 { background][2 : url][3 (\"bar\"][2 )][1 ; ]}");

IT("pseudo",
"foo:before [1 { ]}");
MT("commentSGML2",
"[comment <!--comment]",
"[comment -->] [tag div] {}");

MT("indent_tagSelector",
"[tag strong], [tag em] {",
" [property background]: [atom rgba](",
" [number 255], [number 255], [number 0], [number .2]",
" );",
"}");

MT("indent_atMedia",
"[def @media] {",
" [tag foo] {",
" [property color]:",
" [keyword yellow];",
" }",
"}");

MT("indent_comma",
"[tag foo] {",
" [property font-family]: [variable verdana],",
" [atom sans-serif];",
"}");

MT("indent_parentheses",
"[tag foo]:[variable-3 before] {",
" [property background]: [atom url](",
"[string blahblah]",
"[string etc]",
"[string ]) [keyword !important];",
"}");

MT("font_face",
"[def @font-face] {",
" [property font-family]: [string 'myfont'];",
" [error nonsense]: [string 'abc'];",
" [property src]: [atom url]([string http://blah]),",
" [atom url]([string http://foo]);",
"}");
})();

Large diffs are not rendered by default.

@@ -51,11 +51,12 @@ <h2>Erlang mode</h2>
case tuple_size(Tup) of
L when L < 1 -> Tup;
L ->
try Fields = M:rec_info(element(1,Tup)),
L = length(Fields)+1,
lists:zip(Fields,expand_recs(M,tl(tuple_to_list(Tup))))
catch _:_ ->
list_to_tuple(expand_recs(M,tuple_to_list(Tup)))
try
Fields = M:rec_info(element(1,Tup)),
L = length(Fields)+1,
lists:zip(Fields,expand_recs(M,tl(tuple_to_list(Tup))))
catch
_:_ -> list_to_tuple(expand_recs(M,tuple_to_list(Tup)))
end
end;
expand_recs(_,Term) ->
@@ -1,4 +1,4 @@
CodeMirror.defineMode("gfm", function(config) {
CodeMirror.defineMode("gfm", function(config, modeConfig) {
var codeDepth = 0;
function blankLine(state) {
state.code = false;
@@ -75,7 +75,7 @@ CodeMirror.defineMode("gfm", function(config) {
return "link";
}
}
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) &&
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) &&
stream.string.slice(stream.start - 2, stream.start) != "](") {
// URLs
// Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
@@ -87,11 +87,16 @@ CodeMirror.defineMode("gfm", function(config) {
},
blankLine: blankLine
};
CodeMirror.defineMIME("gfmBase", {
name: "markdown",

var markdownConfig = {
underscoresBreakWords: false,
taskLists: true,
fencedCodeBlocks: true
});
};
for (var attr in modeConfig) {
markdownConfig[attr] = modeConfig[attr];
}
markdownConfig.name = "markdown";
CodeMirror.defineMIME("gfmBase", markdownConfig);
return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);
}, "markdown");
@@ -1,6 +1,23 @@
(function() {
var mode = CodeMirror.getMode({tabSize: 4}, "gfm");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "gfm", highlightFormatting: true});
function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }

FT("codeBackticks",
"[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");

FT("doubleBackticks",
"[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");

FT("codeBlock",
"[comment&formatting&formatting-code-block ```css]",
"[tag foo]",
"[comment&formatting&formatting-code-block ```]");

FT("taskList",
"[variable-2&formatting&formatting-list&formatting-list-ul - ][meta&formatting&formatting-task [ ]]][variable-2 foo]",
"[variable-2&formatting&formatting-list&formatting-list-ul - ][property&formatting&formatting-task [x]]][variable-2 foo]");

MT("emInWordAsterisk",
"foo[em *bar*]hello");
@@ -97,7 +114,7 @@

MT("notALink",
"[comment ```css]",
"[tag foo] {[property color][operator :][keyword black];}",
"[tag foo] {[property color]:[keyword black];}",
"[comment ```][link http://www.example.com/]");

MT("notALink",
@@ -18,31 +18,40 @@ CodeMirror.defineMode("gherkin", function () {
startState: function () {
return {
lineNumber: 0,
tableHeaderLine: null,
tableHeaderLine: false,
allowFeature: true,
allowBackground: false,
allowScenario: false,
allowSteps: false,
allowPlaceholders: false,
inMultilineArgument: false,
allowMultilineArgument: false,
inMultilineString: false,
inMultilineTable: false
inMultilineTable: false,
inKeywordLine: false
};
},
token: function (stream, state) {
if (stream.sol()) {
state.lineNumber++;
state.inKeywordLine = false;
if (state.inMultilineTable) {
state.tableHeaderLine = false;
if (!stream.match(/\s*\|/, false)) {
state.allowMultilineArgument = false;
state.inMultilineTable = false;
}
}
}

stream.eatSpace();

// INSIDE OF MULTILINE ARGUMENTS
if (state.inMultilineArgument) {
if (state.allowMultilineArgument) {

// STRING
if (state.inMultilineString) {
if (stream.match('"""')) {
state.inMultilineString = false;
state.inMultilineArgument = false;
state.allowMultilineArgument = false;
} else {
stream.match(/.*/);
}
@@ -51,19 +60,11 @@ CodeMirror.defineMode("gherkin", function () {

// TABLE
if (state.inMultilineTable) {
// New table, assume first row is headers
if (state.tableHeaderLine === null) {
state.tableHeaderLine = state.lineNumber;
}

if (stream.match(/\|\s*/)) {
if (stream.eol()) {
state.inMultilineTable = false;
}
return "bracket";
} else {
stream.match(/[^\|]*/);
return state.tableHeaderLine === state.lineNumber ? "property" : "string";
return state.tableHeaderLine ? "header" : "string";
}
}

@@ -75,92 +76,86 @@ CodeMirror.defineMode("gherkin", function () {
} else if (stream.match("|")) {
// Table
state.inMultilineTable = true;
state.tableHeaderLine = true;
return "bracket";
} else {
// Or abort
state.inMultilineArgument = false;
state.tableHeaderLine = null;
}


return null;
}

// LINE COMMENT
if (stream.match(/#.*/)) {
return "comment";

// TAG
} else if (stream.match(/@\S+/)) {
return "def";
} else if (!state.inKeywordLine && stream.match(/@\S+/)) {
return "tag";

// FEATURE
} else if (state.allowFeature && stream.match(/Feature:/)) {
} else if (!state.inKeywordLine && state.allowFeature && stream.match(/(機能|功能|フィーチャ|기능|โครงหลัก|ความสามารถ|ความต้องการทางธุรกิจ|ಹೆಚ್ಚಳ|గుణము|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ|ਖਾਸੀਅਤ|रूप लेख|وِیژگی|خاصية|תכונה|Функціонал|Функция|Функционалност|Функционал|Үзенчәлеклелек|Свойство|Особина|Мөмкинлек|Могућност|Λειτουργία|Δυνατότητα|Właściwość|Vlastnosť|Trajto|Tính năng|Savybė|Pretty much|Požiadavka|Požadavek|Potrzeba biznesowa|Özellik|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Hwæt|Hwaet|Funzionalità|Funktionalitéit|Funktionalität|Funkcja|Funkcionalnost|Funkcionalitāte|Funkcia|Fungsi|Functionaliteit|Funcționalitate|Funcţionalitate|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Fīča|Feature|Eiginleiki|Egenskap|Egenskab|Característica|Caracteristica|Business Need|Aspekt|Arwedd|Ahoy matey!|Ability):/)) {
state.allowScenario = true;
state.allowBackground = true;
state.allowPlaceholders = false;
state.allowSteps = false;
state.allowMultilineArgument = false;
state.inKeywordLine = true;
return "keyword";

// BACKGROUND
} else if (state.allowBackground && stream.match("Background:")) {
} else if (!state.inKeywordLine && state.allowBackground && stream.match(/(背景|배경|แนวคิด|ಹಿನ್ನೆಲೆ|నేపథ్యం|ਪਿਛੋਕੜ|पृष्ठभूमि|زمینه|الخلفية|רקע|Тарих|Предыстория|Предистория|Позадина|Передумова|Основа|Контекст|Кереш|Υπόβαθρο|Założenia|Yo\-ho\-ho|Tausta|Taust|Situācija|Rerefons|Pozadina|Pozadie|Pozadí|Osnova|Latar Belakang|Kontext|Konteksts|Kontekstas|Kontekst|Háttér|Hannergrond|Grundlage|Geçmiş|Fundo|Fono|First off|Dis is what went down|Dasar|Contexto|Contexte|Context|Contesto|Cenário de Fundo|Cenario de Fundo|Cefndir|Bối cảnh|Bakgrunnur|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|Ær|Aer|Achtergrond):/)) {
state.allowPlaceholders = false;
state.allowSteps = true;
state.allowBackground = false;
state.allowMultilineArgument = false;
state.inKeywordLine = true;
return "keyword";

// SCENARIO OUTLINE
} else if (state.allowScenario && stream.match("Scenario Outline:")) {
} else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景大綱|场景大纲|劇本大綱|剧本大纲|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|시나리오 개요|สรุปเหตุการณ์|โครงสร้างของเหตุการณ์|ವಿವರಣೆ|కథనం|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਟਕਥਾ ਢਾਂਚਾ|परिदृश्य रूपरेखा|سيناريو مخطط|الگوی سناریو|תבנית תרחיש|Сценарийның төзелеше|Сценарий структураси|Структура сценарію|Структура сценария|Структура сценарија|Скица|Рамка на сценарий|Концепт|Περιγραφή Σεναρίου|Wharrimean is|Template Situai|Template Senario|Template Keadaan|Tapausaihio|Szenariogrundriss|Szablon scenariusza|Swa hwær swa|Swa hwaer swa|Struktura scenarija|Structură scenariu|Structura scenariu|Skica|Skenario konsep|Shiver me timbers|Senaryo taslağı|Schema dello scenario|Scenariomall|Scenariomal|Scenario Template|Scenario Outline|Scenario Amlinellol|Scenārijs pēc parauga|Scenarijaus šablonas|Reckon it's like|Raamstsenaarium|Plang vum Szenario|Plan du Scénario|Plan du scénario|Osnova scénáře|Osnova Scenára|Náčrt Scenáru|Náčrt Scénáře|Náčrt Scenára|MISHUN SRSLY|Menggariskan Senario|Lýsing Dæma|Lýsing Atburðarásar|Konturo de la scenaro|Koncept|Khung tình huống|Khung kịch bản|Forgatókönyv vázlat|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Esbozo do escenario|Delineação do Cenário|Delineacao do Cenario|All y'all|Abstrakt Scenario|Abstract Scenario):/)) {
state.allowPlaceholders = true;
state.allowSteps = true;
state.allowMultilineArgument = false;
state.inKeywordLine = true;
return "keyword";

// EXAMPLES
} else if (state.allowScenario && stream.match("Examples:")) {
} else if (state.allowScenario && stream.match(/(例子||サンプル||ชุดของเหตุการณ์|ชุดของตัวอย่าง|ಉದಾಹರಣೆಗಳು|ఉదాహరణలు|ਉਦਾਹਰਨਾਂ|उदाहरण|نمونه ها|امثلة|דוגמאות|Үрнәкләр|Сценарији|Примеры|Примери|Приклади|Мисоллар|Мисаллар|Σενάρια|Παραδείγματα|You'll wanna|Voorbeelden|Variantai|Tapaukset|Se þe|Se the|Se ðe|Scenarios|Scenariji|Scenarijai|Przykłady|Primjeri|Primeri|Příklady|Príklady|Piemēri|Példák|Pavyzdžiai|Paraugs|Örnekler|Juhtumid|Exemplos|Exemples|Exemple|Exempel|EXAMPLZ|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|Dữ liệu|Dead men tell no tales|Dæmi|Contoh|Cenários|Cenarios|Beispiller|Beispiele|Atburðarásir):/)) {
state.allowPlaceholders = false;
state.allowSteps = true;
state.allowBackground = false;
state.inMultilineArgument = true;
state.allowMultilineArgument = true;
return "keyword";

// SCENARIO
} else if (state.allowScenario && stream.match(/Scenario:/)) {
} else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景|场景|劇本|剧本|シナリオ|시나리오|เหตุการณ์|ಕಥಾಸಾರಾಂಶ|సన్నివేశం|ਪਟਕਥਾ|परिदृश्य|سيناريو|سناریو|תרחיש|Сценарій|Сценарио|Сценарий|Пример|Σενάριο|Tình huống|The thing of it is|Tapaus|Szenario|Swa|Stsenaarium|Skenario|Situai|Senaryo|Senario|Scenaro|Scenariusz|Scenariu|Scénario|Scenario|Scenarijus|Scenārijs|Scenarij|Scenarie|Scénář|Scenár|Primer|MISHUN|Kịch bản|Keadaan|Heave to|Forgatókönyv|Escenario|Escenari|Cenário|Cenario|Awww, look mate|Atburðarás):/)) {
state.allowPlaceholders = false;
state.allowSteps = true;
state.allowBackground = false;
state.allowMultilineArgument = false;
state.inKeywordLine = true;
return "keyword";

// STEPS
} else if (state.allowSteps && stream.match(/(Given|When|Then|And|But)/)) {
} else if (!state.inKeywordLine && state.allowSteps && stream.match(/(那麼|那么|而且|||并且|同時|同时|前提|假设|假設|假定|假如|但是|但し|並且|もし|ならば|ただし|しかし|かつ|하지만|조건|먼저|만일|만약||그리고|그러면|และ |เมื่อ |แต่ |ดังนั้น |กำหนดให้ |ಸ್ಥಿತಿಯನ್ನು |ಮತ್ತು |ನೀಡಿದ |ನಂತರ |ಆದರೆ |మరియు |చెప్పబడినది |కాని |ఈ పరిస్థితిలో |అప్పుడు |ਪਰ |ਤਦ |ਜੇਕਰ |ਜਿਵੇਂ ਕਿ |ਜਦੋਂ |ਅਤੇ |यदि |परन्तु |पर |तब |तदा |तथा |जब |चूंकि |किन्तु |कदा |और |अगर |و |هنگامی |متى |لكن |عندما |ثم |بفرض |با فرض |اما |اذاً |آنگاه |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Һәм |Унда |Тоді |Тогда |То |Также |Та |Пусть |Припустимо, що |Припустимо |Онда |Но |Нехай |Нәтиҗәдә |Лекин |Ләкин |Коли |Когда |Когато |Када |Кад |К тому же |І |И |Задато |Задати |Задате |Если |Допустим |Дано |Дадено |Вә |Ва |Бирок |Әмма |Әйтик |Әгәр |Аммо |Али |Але |Агар |А також |А |Τότε |Όταν |Και |Δεδομένου |Αλλά |Þurh |Þegar |Þa þe |Þá |Þa |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Za předpokladu |Za predpokladu |Youse know when youse got |Youse know like when |Yna |Yeah nah |Y'know |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |wann |Ve ||Und |Un |ugeholl |Too right |Thurh |Thì |Then y'all |Then |Tha the |Tha |Tetapi |Tapi |Tak |Tada |Tad |Stel |Soit |Siis |Și |Şi |Si |Sed |Se ||Quando |Quand |Quan |Pryd |Potom |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Niin |Nhưng |När |Når |Mutta |Men |Mas |Maka |Majd |Mając |Mais |Maar ||Ma |Lorsque |Lorsqu'|Logo |Let go and haul |Kun |Kuid |Kui |Kiedy |Khi |Ketika |Kemudian |Keď |Když |Kaj |Kai |Kada |Kad |Jeżeli |Jeśli |Ja |It's just unbelievable |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben seien |Gegeben sei |Gdy |Gangway! |Fakat |Étant donnés |Etant donnés |Étant données |Etant données |Étant donnée |Etant donnée |Étant donné |Etant donné |Et |És |Entonces |Entón |Então |Entao |En |Eğer ki |Ef |Eeldades |E |Ðurh |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Diberi |Dengan |Den youse gotta |DEN |De |Dato |Dați fiind |Daţi fiind |Dati fiind |Dati |Date fiind |Date |Data |Dat fiind |Dar |Dann |dann |Dan |Dados |Dado |Dadas |Dada |Ða ðe |Ða |Cuando |Cho |Cando |Când |Cand |Cal |But y'all |But at the end of the day I reckon |BUT |But |Buh |Blimey! |Biết |Bet |Bagi |Aye |awer |Avast! |Atunci |Atesa |Atès |Apabila |Anrhegedig a |Angenommen |And y'all |And |AN |An |an |Amikor |Amennyiben |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Ak |Adott |Ac |Aber |A zároveň |A tiež |A taktiež |A také |A |a |7 |\* )/)) {
state.inStep = true;
state.allowPlaceholders = true;
state.allowMultilineArgument = true;
state.inKeywordLine = true;
return "keyword";

// INLINE STRING
} else if (!state.inMultilineArgument && stream.match(/"/)) {
stream.match(/.*?"/);
} else if (stream.match(/"[^"]*"?/)) {
return "string";

// MULTILINE ARGUMENTS
} else if (state.allowSteps && stream.eat(":")) {
if (stream.match(/\s*$/)) {
state.inMultilineArgument = true;
return "keyword";
} else {
return null;
}

} else if (state.allowSteps && stream.match("<")) {
if (stream.match(/.*?>/)) {
return "property";
} else {
return null;
}
// PLACEHOLDER
} else if (state.allowPlaceholders && stream.match(/<[^>]*>?/)) {
return "variable";

// Fall through
} else {
stream.eatWhile(/[^":<]/);
stream.next();
stream.eatWhile(/[^@"<#]/);
return null;
}

return null;
}
};
});
@@ -141,10 +141,6 @@
style = null;
}
return style;
},

indent: function(state) {
return state.indented;
}
};
}, "htmlmixed", "ruby");
@@ -1,5 +1,5 @@
(function() {
var mode = CodeMirror.getMode({tabSize: 4}, "haml");
var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }

// Requires at least one media query
@@ -8,7 +8,7 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) {
// These should all be Unicode extended, as per the Haskell 2010 report
var smallRE = /[a-z_]/;
var largeRE = /[A-Z]/;
var digitRE = /[0-9]/;
var digitRE = /\d/;
var hexitRE = /[0-9A-Fa-f]/;
var octitRE = /[0-7]/;
var idRE = /[a-z_A-Z0-9']/;
@@ -76,9 +76,8 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) {
}
source.eatWhile(digitRE);
var t = "number";
if (source.eat('.')) {
if (source.match(/^\.\d+/)) {
t = "number";
source.eatWhile(digitRE); // should require at least 1
}
if (source.eat(/[eE]/)) {
t = "number";
@@ -88,6 +87,9 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) {
return t;
}

if (ch == "." && source.eat("."))
return "keyword";

if (symbolRE.test(ch)) {
if (ch == '-' && source.eat(/-/)) {
source.eatWhile(/-/);
@@ -58,8 +58,6 @@ CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
};
},

electricChars: "/{}:",

innerMode: function(state) {
if (state.token == scriptingDispatch) return {state: state.scriptState, mode: scriptingMode};
else return {state: state.htmlState, mode: htmlMixedMode};
@@ -93,8 +93,6 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
return CodeMirror.Pass;
},

electricChars: "/{}:",

innerMode: function(state) {
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
}
@@ -46,6 +46,7 @@ <h2>Language modes</h2>
<li><a href="eiffel/index.html">Eiffel</a></li>
<li><a href="erlang/index.html">Erlang</a></li>
<li><a href="fortran/index.html">Fortran</a></li>
<li><a href="mllike/index.html">F#</a></li>
<li><a href="gas/index.html">Gas</a> (AT&amp;T-style assembly)</li>
<li><a href="gherkin/index.html">Gherkin</a></li>
<li><a href="go/index.html">Go</a></li>
@@ -61,14 +62,14 @@ <h2>Language modes</h2>
<li><a href="javascript/index.html">JavaScript</a></li>
<li><a href="jinja2/index.html">Jinja2</a></li>
<li><a href="julia/index.html">Julia</a></li>
<li><a href="less/index.html">LESS</a></li>
<li><a href="css/less.html">LESS</a></li>
<li><a href="livescript/index.html">LiveScript</a></li>
<li><a href="lua/index.html">Lua</a></li>
<li><a href="markdown/index.html">Markdown</a> (<a href="gfm/index.html">GitHub-flavour</a>)</li>
<li><a href="mirc/index.html">mIRC</a></li>
<li><a href="nginx/index.html">Nginx</a></li>
<li><a href="ntriples/index.html">NTriples</a></li>
<li><a href="ocaml/index.html">OCaml</a></li>
<li><a href="mllike/index.html">OCaml</a></li>
<li><a href="octave/index.html">Octave</a> (MATLAB)</li>
<li><a href="pascal/index.html">Pascal</a></li>
<li><a href="pegjs/index.html">PEG.js</a></li>
@@ -15,7 +15,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {

var jsKeywords = {
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
"var": kw("var"), "const": kw("var"), "let": kw("var"),
"function": kw("function"), "catch": kw("catch"),
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
@@ -54,14 +54,16 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {

var isOperatorChar = /[+\-*&%=<>!?|~^]/;

function nextUntilUnescaped(stream, end) {
var escaped = false, next;
function readRegexp(stream) {
var escaped = false, next, inSet = false;
while ((next = stream.next()) != null) {
if (next == end && !escaped)
return false;
if (!escaped) {
if (next == "/" && !inSet) return;
if (next == "[") inSet = true;
else if (inSet && next == "]") inSet = false;
}
escaped = !escaped && next == "\\";
}
return escaped;
}

// Used as scratch variables to communicate multiple values without
@@ -83,7 +85,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
return ret(ch);
} else if (ch == "=" && stream.eat(">")) {
return ret("=>");
return ret("=>", "operator");
} else if (ch == "0" && stream.eat(/x/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
@@ -99,12 +101,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return ret("comment", "comment");
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
nextUntilUnescaped(stream, "/");
readRegexp(stream);
stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
return ret("regexp", "string-2");
} else {
stream.eatWhile(isOperatorChar);
return ret("operator", null, stream.current());
return ret("operator", "operator", stream.current());
}
} else if (ch == "`") {
state.tokenize = tokenQuasi;
@@ -114,7 +116,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return ret("error", "error");
} else if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
return ret("operator", null, stream.current());
return ret("operator", "operator", stream.current());
} else {
stream.eatWhile(/[\w\$_]/);
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
@@ -125,8 +127,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {

function tokenString(quote) {
return function(stream, state) {
if (!nextUntilUnescaped(stream, quote))
state.tokenize = tokenBase;
var escaped = false, next;
while ((next = stream.next()) != null) {
if (next == quote && !escaped) break;
escaped = !escaped && next == "\\";
}
if (!escaped) state.tokenize = tokenBase;
return ret("string", "string");
};
}
@@ -304,7 +310,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == ";") return cont();
if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse);
if (type == "function") return cont(functiondef);
if (type == "for") return cont(pushlex("form"), forspec, poplex, statement, poplex);
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
if (type == "variable") return cont(pushlex("stat"), maybelabel);
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
block, poplex, poplex);
@@ -327,7 +333,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function expressionInner(type, noComma) {
if (cx.state.fatArrowAt == cx.stream.start) {
var body = noComma ? arrowBodyNoComma : arrowBody;
if (type == "(") return cont(pushcontext, commasep(pattern, ")"), expect("=>"), body, popcontext);
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
}

@@ -337,8 +343,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
if (type == "[") return cont(pushlex("]"), expressionNoComma, maybeArrayComprehension, poplex, maybeop);
if (type == "{") return cont(commasep(objprop, "}"), maybeop);
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
return cont();
}
function maybeexpression(type) {
@@ -365,12 +371,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
if (type == "quasi") { cx.cc.push(me); return quasi(value); }
if (type == ";") return;
if (type == "(") return cont(commasep(expressionNoComma, ")", "call"), me);
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
if (type == ".") return cont(property, me);
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
}
function quasi(value) {
if (!value) debugger;
if (value.slice(value.length - 2) != "${") return cont();
return cont(expression, continueQuasi);
}
@@ -418,7 +423,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == ":") return cont(expressionNoComma);
if (type == "(") return pass(functiondef);
}
function commasep(what, end, info) {
function commasep(what, end) {
function proceed(type) {
if (type == ",") {
var lex = cx.state.lexical;
@@ -430,10 +435,14 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
return function(type) {
if (type == end) return cont();
if (info === false) return pass(what, proceed);
return pass(pushlex(end, info), what, proceed, poplex);
return pass(what, proceed);
};
}
function contCommasep(what, end, info) {
for (var i = 3; i < arguments.length; i++)
cx.cc.push(arguments[i]);
return cont(pushlex(end, info), commasep(what, end), poplex);
}
function block(type) {
if (type == "}") return cont();
return pass(statement, block);
@@ -449,8 +458,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function pattern(type, value) {
if (type == "variable") { register(value); return cont(); }
if (type == "[") return cont(commasep(pattern, "]"));
if (type == "{") return cont(commasep(proppattern, "}"));
if (type == "[") return contCommasep(pattern, "]");
if (type == "{") return contCommasep(proppattern, "}");
}
function proppattern(type, value) {
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
@@ -470,7 +479,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex);
}
function forspec(type) {
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"));
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
}
function forspec1(type) {
if (type == "var") return cont(vardef, expect(";"), forspec2);
@@ -493,7 +502,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function functiondef(type, value) {
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
if (type == "variable") {register(value); return cont(functiondef);}
if (type == "(") return cont(pushcontext, commasep(funarg, ")"), statement, popcontext);
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
}
function funarg(type) {
if (type == "spread") return cont(funarg);
@@ -506,7 +515,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (value == "extends") return cont(expression);
}
function objlit(type) {
if (type == "{") return cont(commasep(objprop, "}"));
if (type == "{") return contCommasep(objprop, "}");
}
function afterModule(type, value) {
if (type == "string") return cont(statement);
@@ -522,17 +531,21 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return pass(importSpec, maybeFrom);
}
function importSpec(type, value) {
if (type == "{") return cont(commasep(importSpec, "}"));
if (type == "{") return contCommasep(importSpec, "}");
if (type == "variable") register(value);
return cont();
}
function maybeFrom(_type, value) {
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
}
function arrayLiteral(type) {
if (type == "]") return cont();
return pass(expressionNoComma, maybeArrayComprehension);
}
function maybeArrayComprehension(type) {
if (type == "for") return pass(comprehension);
if (type == ",") return cont(commasep(expressionNoComma, "]", false));
return pass(commasep(expressionNoComma, "]", false));
if (type == "for") return pass(comprehension, expect("]"));
if (type == ",") return cont(commasep(expressionNoComma, "]"));
return pass(commasep(expressionNoComma, "]"));
}
function comprehension(type) {
if (type == "for") return cont(forspec, comprehension);
@@ -3,29 +3,29 @@
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }

MT("locals",
"[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] = [number 10]; [keyword return] [variable-2 a] + [variable-2 c] + [variable d]; }");
"[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }");

MT("comma-and-binop",
"[keyword function](){ [keyword var] [def x] = [number 1] + [number 2], [def y]; }");
"[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }");

MT("destructuring",
"([keyword function]([def a], [[[def b], [def c] ]]) {",
" [keyword let] {[def d], [property foo]: [def c]=[number 10], [def x]} = [variable foo]([variable-2 a]);",
" [[[variable-2 c], [variable y] ]] = [variable-2 c];",
" [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);",
" [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];",
"})();");

MT("class",
"[keyword class] [variable Point] [keyword extends] [variable SuperThing] {",
" [[ [string-2 /expr/] ]]: [number 24],",
" [property constructor]([def x], [def y]) {",
" [keyword super]([string 'something']);",
" [keyword this].[property x] = [variable-2 x];",
" [keyword this].[property x] [operator =] [variable-2 x];",
" }",
"}");

MT("module",
"[keyword module] [string 'foo'] {",
" [keyword export] [keyword let] [def x] = [number 42];",
" [keyword export] [keyword let] [def x] [operator =] [number 42];",
" [keyword export] [keyword *] [keyword from] [string 'somewhere'];",
"}");

@@ -38,22 +38,22 @@

MT("const",
"[keyword function] [variable f]() {",
" [keyword const] [[ [def a], [def b] ]] = [[ [number 1], [number 2] ]];",
" [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];",
"}");

MT("for/of",
"[keyword for]([keyword let] [variable of] [keyword of] [variable something]) {}");

MT("generator",
"[keyword function*] [variable repeat]([def n]) {",
" [keyword for]([keyword var] [def i] = [number 0]; [variable-2 i] < [variable-2 n]; ++[variable-2 i])",
" [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])",
" [keyword yield] [variable-2 i];",
"}");

MT("fatArrow",
"[variable array].[property filter]([def a] => [variable-2 a] + [number 1]);",
"[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);",
"[variable a];", // No longer in scope
"[keyword let] [variable f] = ([[ [def a], [def b] ]], [def c]) => [variable-2 a] + [variable-2 c];",
"[keyword let] [variable f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];",
"[variable c];");

MT("spread",
@@ -63,10 +63,51 @@

MT("comprehension",
"[keyword function] [variable f]() {",
" [[ [variable x] + [number 1] [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];",
" ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] === [string 'blue']));",
" [[([variable x] [operator +] [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];",
" ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] [operator ===] [string 'blue']));",
"}");

MT("quasi",
"[variable re][string-2 `fofdlakj${][variable x] + ([variable re][string-2 `foo`]) + [number 1][string-2 }fdsa`] + [number 2]");
"[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");

MT("indent_statement",
"[keyword var] [variable x] [operator =] [number 10]",
"[variable x] [operator +=] [variable y] [operator +]",
" [atom Infinity]",
"[keyword debugger];");

MT("indent_if",
"[keyword if] ([number 1])",
" [keyword break];",
"[keyword else] [keyword if] ([number 2])",
" [keyword continue];",
"[keyword else]",
" [number 10];",
"[keyword if] ([number 1]) {",
" [keyword break];",
"} [keyword else] [keyword if] ([number 2]) {",
" [keyword continue];",
"} [keyword else] {",
" [number 10];",
"}");

MT("indent_for",
"[keyword for] ([keyword var] [variable i] [operator =] [number 0];",
" [variable i] [operator <] [number 100];",
" [variable i][operator ++])",
" [variable doSomething]([variable i]);",
"[keyword debugger];");

MT("indent_c_style",
"[keyword function] [variable foo]()",
"{",
" [keyword debugger];",
"}");

MT("multilinestring",
"[keyword var] [variable x] [operator =] [string 'foo\\]",
"[string bar'];");

MT("scary_regexp",
"[string-2 /foo[[/]]bar/];");
})();
@@ -1,7 +1,17 @@
CodeMirror.defineMode("jinja2", function() {
var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",
"loop", "none", "self", "super", "if", "as", "not", "and",
"else", "import", "with", "without", "context"];
var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif",
"extends", "filter", "endfilter", "firstof", "for",
"endfor", "if", "endif", "ifchanged", "endifchanged",
"ifequal", "endifequal", "ifnotequal",
"endifnotequal", "in", "include", "load", "not", "now", "or",
"parsed", "regroup", "reversed", "spaceless",
"endspaceless", "ssi", "templatetag", "openblock",
"closeblock", "openvariable", "closevariable",
"openbrace", "closebrace", "opencomment",
"closecomment", "widthratio", "url", "with", "endwith",
"get_current_language", "trans", "noop", "blocktrans",
"endblocktrans", "get_available_languages",
"get_current_language_bidi", "plural"];
keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");

function tokenBase (stream, state) {
@@ -71,7 +71,7 @@ CodeMirror.defineMode("less", function(config) {
if(stream.peek() === " ")stream.eatSpace();
if(stream.peek() === ")" || type === ":")return ret("number", "unit");//rgba(0,0,0,.25);
else if(stream.current().length >1){
if(state.stack[state.stack.length-1] === "rule" && stream.peek().match(/{|,|\+|\(/) === null)return ret("number", "unit");
if(state.stack[state.stack.length-1] === "rule" && !stream.match(/^[{,+(]/, false)) return ret("number", "unit");
}
return ret("tag", "tag");
} else if (ch == "#") {
@@ -170,7 +170,7 @@ CodeMirror.defineMode("less", function(config) {
} else if(type == "compare" || type == "a" || type == "("){
return ret("string", "string");
} else if(type == "|" || stream.current() == "-" || type == "["){
if(type == "|" && stream.peek().match(/\]|=|\~/) !== null)return ret("number", stream.current());
if (type == "|" && stream.match(/^[\]=~]/, false)) return ret("number", stream.current());
else if(type == "|" )return ret("tag", "tag");
else if(type == "["){
stream.eatWhile(/\w\-/);
@@ -201,7 +201,7 @@ CodeMirror.defineMode("less", function(config) {

//else if((type === ")" && state.stack[state.stack.length-1] === "rule") || (state.stack[state.stack.length-2] === "{" && state.stack[state.stack.length-1] === "rule" && type === "variable"))return ret(null, stream.current());

else if(/\^|\$/.test(stream.current()) && stream.peek().match(/\~|=/) !== null)return ret("string", "string");//att^=val
else if (/\^|\$/.test(stream.current()) && stream.match(/^[~=]/, false)) return ret("string", "string");//att^=val

else if(type === "unit" && state.stack[state.stack.length-1] === "rule")return ret(null, "unit");
else if(type === "unit" && state.stack[state.stack.length-1] === ";")return ret(null, "unit");
@@ -210,12 +210,13 @@ CodeMirror.defineMode("less", function(config) {
//else if(type === "unit" && state.stack[state.stack.length-1] === "rule")return ret(null, stream.current());

else if((type === ";" || type === "}" || type === ",") && state.stack[state.stack.length-1] === ";")return ret("tag", stream.current());
else if((type === ";" && stream.peek() !== undefined && stream.peek().match(/{|./) === null) || (type === ";" && stream.eatSpace() && stream.peek().match(/{|./) === null))return ret("variable", stream.current());
else if((type === ";" && stream.peek() !== undefined && !stream.match(/^[{\.]/, false)) ||
(type === ";" && stream.eatSpace() && !stream.match(/^[{\.]/))) return ret("variable", stream.current());
else if((type === "@media" && state.stack[state.stack.length-1] === "@media") || type === "@namespace")return ret("tag", stream.current());

else if(type === "{" && state.stack[state.stack.length-1] === ";" && stream.peek() === "{")return ret("tag", "tag");
else if((type === "{" || type === ":") && state.stack[state.stack.length-1] === ";")return ret(null, stream.current());
else if((state.stack[state.stack.length-1] === "{" && stream.eatSpace() && stream.peek().match(/.|#/) === null) || type === "select-op" || (state.stack[state.stack.length-1] === "rule" && type === ",") )return ret("tag", "tag");
else if((state.stack[state.stack.length-1] === "{" && stream.eatSpace() && !stream.match(/^[\.#]/)) || type === "select-op" || (state.stack[state.stack.length-1] === "rule" && type === ",") )return ret("tag", "tag");
else if(type === "variable" && state.stack[state.stack.length-1] === "rule")return ret("tag", "tag");
else if((stream.eatSpace() && stream.peek() === "{") || stream.eol() || stream.peek() === "{")return ret("tag", "tag");
//this one messes up indentation
@@ -227,7 +228,7 @@ CodeMirror.defineMode("less", function(config) {
else if(stream.sol())return ret("tag", "tag");
else if((stream.eatSpace() && stream.peek() === "#") || stream.peek() === "#")return ret("tag", "tag");
else if(state.stack.length === 0)return ret("tag", "tag");
else if(type === ";" && stream.peek() !== undefined && stream.peek().match(/^[.|\#]/g) !== null)return ret("tag", "tag");
else if(type === ";" && stream.peek() !== undefined && stream.match(/^[\.|#]/g)) return ret("tag", "tag");

else if(type === ":"){stream.eatSpace();return ret(null, stream.current());}

Large diffs are not rendered by default.

@@ -1,6 +1,57 @@
(function() {
var mode = CodeMirror.getMode({tabSize: 4}, "markdown");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "markdown", highlightFormatting: true});
function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); }

FT("formatting_emAsterisk",
"[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]");

FT("formatting_emUnderscore",
"[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]");

FT("formatting_strongAsterisk",
"[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]");

FT("formatting_strongUnderscore",
"[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]");

FT("formatting_codeBackticks",
"[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]");

FT("formatting_doubleBackticks",
"[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]");

FT("formatting_atxHeader",
"[header&header1&formatting&formatting-header&formatting-header1 #][header&header1 foo # bar ][header&header1&formatting&formatting-header&formatting-header1 #]");

FT("formatting_setextHeader",
"foo",
"[header&header1&formatting&formatting-header&formatting-header1 =]");

FT("formatting_blockquote",
"[quote&quote-1&formatting&formatting-quote&formatting-quote-1 > ][quote&quote-1 foo]");

FT("formatting_list",
"[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]");
FT("formatting_list",
"[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]");

FT("formatting_link",
"[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string (][string http://example.com/][string&formatting&formatting-link-string )]");

FT("formatting_linkReference",
"[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string [][string bar][string&formatting&formatting-link-string ]]]",
"[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string http://example.com/]");

FT("formatting_linkWeb",
"[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]");

FT("formatting_linkEmail",
"[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]");

FT("formatting_escape",
"[formatting&formatting-escape \\]*");

MT("plainText",
"foo");
@@ -142,50 +193,50 @@

// Single-line blockquote with trailing space
MT("blockquoteSpace",
"[atom > foo]");
"[quote&quote-1 > foo]");

// Single-line blockquote
MT("blockquoteNoSpace",
"[atom >foo]");
"[quote&quote-1 >foo]");

// No blank line before blockquote
MT("blockquoteNoBlankLine",
"foo",
"[atom > bar]");
"[quote&quote-1 > bar]");

// Nested blockquote
MT("blockquoteSpace",
"[atom > foo]",
"[number > > foo]",
"[atom > > > foo]");
"[quote&quote-1 > foo]",
"[quote&quote-1 >][quote&quote-2 > foo]",
"[quote&quote-1 >][quote&quote-2 >][quote&quote-3 > foo]");

// Single-line blockquote followed by normal paragraph
MT("blockquoteThenParagraph",
"[atom >foo]",
"[quote&quote-1 >foo]",
"",
"bar");

// Multi-line blockquote (lazy mode)
MT("multiBlockquoteLazy",
"[atom >foo]",
"[atom bar]");
"[quote&quote-1 >foo]",
"[quote&quote-1 bar]");

// Multi-line blockquote followed by normal paragraph (lazy mode)
MT("multiBlockquoteLazyThenParagraph",
"[atom >foo]",
"[atom bar]",
"[quote&quote-1 >foo]",
"[quote&quote-1 bar]",
"",
"hello");

// Multi-line blockquote (non-lazy mode)
MT("multiBlockquote",
"[atom >foo]",
"[atom >bar]");
"[quote&quote-1 >foo]",
"[quote&quote-1 >bar]");

// Multi-line blockquote followed by normal paragraph (non-lazy mode)
MT("multiBlockquoteThenParagraph",
"[atom >foo]",
"[atom >bar]",
"[quote&quote-1 >foo]",
"[quote&quote-1 >bar]",
"",
"hello");

@@ -225,6 +276,11 @@
"1. bar",
"2. hello");

// List after header
MT("listAfterHeader",
"[header&header1 # foo]",
"[variable-2 - bar]");

// Formatting in lists (*)
MT("listAsteriskFormatting",
"[variable-2 * ][variable-2&em *foo*][variable-2 bar]",
@@ -310,7 +366,7 @@
"",
"[variable-2 * bar]",
"",
" [variable-2&atom > hello]");
" [variable-2&quote&quote-1 > hello]");

// Code block
MT("blockquoteCode",
@@ -368,7 +424,7 @@
"",
" [variable-3 + bar]",
"",
" [atom&variable-3 > hello]");
" [quote&quote-1&variable-3 > hello]");

MT("listCode",
"[variable-2 * foo]",
@@ -651,6 +707,10 @@
MT("doubleEscapeHash",
"\\\\# foo");

MT("escapeNewline",
"\\",
"[em *foo*]");


// Tests to make sure GFM-specific things aren't getting through

@@ -18,6 +18,7 @@ CodeMirror.modeInfo = [
{name: 'Eiffel', mime: 'text/x-eiffel', mode: 'eiffel'},
{name: 'Erlang', mime: 'text/x-erlang', mode: 'erlang'},
{name: 'Fortran', mime: 'text/x-fortran', mode: 'fortran'},
{name: 'F#', mime: 'text/x-fsharp', mode: 'mllike'},
{name: 'Gas', mime: 'text/x-gas', mode: 'gas'},
{name: 'Gherkin', mime: 'text/x-feature', mode: 'gherkin'},
{name: 'GitHub Flavored Markdown', mime: 'text/x-gfm', mode: 'gfm'},
@@ -45,7 +46,7 @@ CodeMirror.modeInfo = [
{name: 'mIRC', mime: 'text/mirc', mode: 'mirc'},
{name: 'Nginx', mime: 'text/x-nginx-conf', mode: 'nginx'},
{name: 'NTriples', mime: 'text/n-triples', mode: 'ntriples'},
{name: 'OCaml', mime: 'text/x-ocaml', mode: 'ocaml'},
{name: 'OCaml', mime: 'text/x-ocaml', mode: 'mllike'},
{name: 'Octave', mime: 'text/x-octave', mode: 'octave'},
{name: 'Pascal', mime: 'text/x-pascal', mode: 'pascal'},
{name: 'PEG.js', mime: null, mode: 'pegjs'},
@@ -1,13 +1,13 @@
<!doctype html>

<title>CodeMirror: OCaml mode</title>
<title>CodeMirror: ML-like mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">

<link rel=stylesheet href=../../lib/codemirror.css>
<script src=../../lib/codemirror.js></script>
<script src=../../addon/edit/matchbrackets.js></script>
<script src=ocaml.js></script>
<script src=mllike.js></script>
<style type=text/css>
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
</style>
@@ -21,15 +21,15 @@
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">OCaml</a>
<li><a class=active href="#">ML-like</a>
</ul>
</div>

<article>
<h2>OCaml mode</h2>


<textarea id=code>
<textarea id="ocamlCode">
(* Summing a list of integers *)
let rec sum xs =
match xs with
@@ -89,7 +89,7 @@ <h2>OCaml mode</h2>

and insert elem = function
| [] -&gt; [elem]
| x :: l -&gt;
| x :: l -&gt;
if elem &lt; x then elem :: x :: l else x :: insert elem l;;

(* Imperative features *)
@@ -134,13 +134,46 @@ <h2>OCaml mode</h2>
(* OCaml page on Wikipedia - http://en.wikipedia.org/wiki/OCaml *)
</textarea>

<h2>F# mode</h2>
<textarea id="fsharpCode">
module CodeMirror.FSharp

let rec fib = function
| 0 -> 0
| 1 -> 1
| n -> fib (n - 1) + fib (n - 2)

type Point =
{
x : int
y : int
}

type Color =
| Red
| Green
| Blue

[0 .. 10]
|> List.map ((+) 2)
|> List.fold (fun x y -> x + y) 0
|> printf "%i"
</textarea>


<script>
var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
mode: 'ocaml',
var ocamlEditor = CodeMirror.fromTextArea(document.getElementById('ocamlCode'), {
mode: 'text/x-ocaml',
lineNumbers: true,
matchBrackets: true
});

var fsharpEditor = CodeMirror.fromTextArea(document.getElementById('fsharpCode'), {
mode: 'text/x-fsharp',
lineNumbers: true,
matchBrackets: true
});
</script>

<p><strong>MIME types defined:</strong> <code>text/x-ocaml</code>.</p>
<p><strong>MIME types defined:</strong> <code>text/x-ocaml</code> (OCaml) and <code>text/x-fsharp</code> (F#).</p>
</article>
@@ -1,14 +1,11 @@
CodeMirror.defineMode('ocaml', function() {
CodeMirror.defineMode('mllike', function(_config, parserConfig) {

var words = {
'true': 'atom',
'false': 'atom',
'let': 'keyword',
'rec': 'keyword',
'in': 'keyword',
'of': 'keyword',
'and': 'keyword',
'succ': 'keyword',
'if': 'keyword',
'then': 'keyword',
'else': 'keyword',
@@ -25,17 +22,19 @@ CodeMirror.defineMode('ocaml', function() {
'match': 'keyword',
'with': 'keyword',
'try': 'keyword',
'raise': 'keyword',
'begin': 'keyword',
'end': 'keyword',
'open': 'builtin',
'trace': 'builtin',
'ignore': 'builtin',
'exit': 'builtin',
'print_string': 'builtin',
'print_endline': 'builtin'
'begin': 'keyword',
'end': 'keyword'
};

var extraWords = parserConfig.extraWords || {};
for (var prop in extraWords) {
if (extraWords.hasOwnProperty(prop)) {
words[prop] = parserConfig.extraWords[prop];
}
}

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

@@ -58,6 +57,10 @@ CodeMirror.defineMode('ocaml', function() {
stream.eatWhile(/\w/);
return 'quote';
}
if (ch === '/' && parserConfig.slashComments && stream.eat('/')) {
stream.skipToEnd();
return 'comment';
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\d]/);
if (stream.eat('.')) {
@@ -109,8 +112,80 @@ CodeMirror.defineMode('ocaml', function() {
},

blockCommentStart: "(*",
blockCommentEnd: "*)"
blockCommentEnd: "*)",
lineComment: parserConfig.slashComments ? "//" : null
};
});

CodeMirror.defineMIME('text/x-ocaml', 'ocaml');
CodeMirror.defineMIME('text/x-ocaml', {
name: 'mllike',
extraWords: {
'succ': 'keyword',
'trace': 'builtin',
'exit': 'builtin',
'print_string': 'builtin',
'print_endline': 'builtin',
'true': 'atom',
'false': 'atom',
'raise': 'keyword'
}
});

CodeMirror.defineMIME('text/x-fsharp', {
name: 'mllike',
extraWords: {
'abstract': 'keyword',
'as': 'keyword',
'assert': 'keyword',
'base': 'keyword',
'class': 'keyword',
'default': 'keyword',
'delegate': 'keyword',
'downcast': 'keyword',
'downto': 'keyword',
'elif': 'keyword',
'exception': 'keyword',
'extern': 'keyword',
'finally': 'keyword',
'global': 'keyword',
'inherit': 'keyword',
'inline': 'keyword',
'interface': 'keyword',
'internal': 'keyword',
'lazy': 'keyword',
'let!': 'keyword',
'member' : 'keyword',
'module': 'keyword',
'namespace': 'keyword',
'new': 'keyword',
'null': 'keyword',
'override': 'keyword',
'private': 'keyword',
'public': 'keyword',
'return': 'keyword',
'return!': 'keyword',
'select': 'keyword',
'static': 'keyword',
'struct': 'keyword',
'upcast': 'keyword',
'use': 'keyword',
'use!': 'keyword',
'val': 'keyword',
'when': 'keyword',
'yield': 'keyword',
'yield!': 'keyword',

'List': 'builtin',
'Seq': 'builtin',
'Map': 'builtin',
'Set': 'builtin',
'int': 'builtin',
'string': 'builtin',
'raise': 'builtin',
'failwith': 'builtin',
'not': 'builtin',
'true': 'builtin',
'false': 'builtin'
},
slashComments: true
});
@@ -54,15 +54,11 @@ CodeMirror.defineMode("pegjs", function (config) {
}
return "comment";
} else if (state.inChracterClass) {
if (stream.match(/^[^\]\\]+/)) {
return;
} else if (stream.match(/^\\./)) {
return;
} else {
stream.next();
state.inChracterClass = false;
return 'bracket';
}
while (state.inChracterClass && !stream.eol()) {
if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) {
state.inChracterClass = false;
}
}
} else if (stream.peek() === '[') {
stream.next();
state.inChracterClass = true;
13 mode/php/php.js 100755 → 100644
@@ -56,26 +56,26 @@

function dispatch(stream, state) {
var isPHP = state.curMode == phpMode;
if (stream.sol() && state.pending != '"') state.pending = null;
if (stream.sol() && state.pending && state.pending != '"' && state.pending != "'") state.pending = null;
if (!isPHP) {
if (stream.match(/^<\?\w*/)) {
state.curMode = phpMode;
state.curState = state.php;
return "meta";
}
if (state.pending == '"') {
while (!stream.eol() && stream.next() != '"') {}
if (state.pending == '"' || state.pending == "'") {
while (!stream.eol() && stream.next() != state.pending) {}
var style = "string";
} else if (state.pending && stream.pos < state.pending.end) {
stream.pos = state.pending.end;
var style = state.pending.style;
} else {
var style = htmlMode.token(stream, state.curState);
}
state.pending = null;
var cur = stream.current(), openPHP = cur.search(/<\?/);
if (state.pending) state.pending = null;
var cur = stream.current(), openPHP = cur.search(/<\?/), m;
if (openPHP != -1) {
if (style == "string" && /\"$/.test(cur) && !/\?>/.test(cur)) state.pending = '"';
if (style == "string" && (m = cur.match(/[\'\"]$/)) && !/\?>/.test(cur)) state.pending = m[0];
else state.pending = {end: stream.pos, style: style};
stream.backUp(cur.length - openPHP);
}
@@ -117,7 +117,6 @@
return state.curMode.indent(state.curState, textAfter);
},

electricChars: "/{}:",
blockCommentStart: "/*",
blockCommentEnd: "*/",
lineComment: "//",
@@ -168,6 +168,7 @@ <h2>Configuration Options for Python mode:</h2>
<ul>
<li>version - 2/3 - The version of Python to recognize. Default is 2.</li>
<li>singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.</li>
<li>hangingIndent - int - If you want to write long arguments to a function starting on a new line, how much that line should be indented. Defaults to one normal indentation unit.</li>
</ul>
<h2>Advanced Configuration Options:</h2>
<p>Usefull for superset of python syntax like Enthought enaml, IPython magics and questionmark help</p>
@@ -11,6 +11,7 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
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]*");
var hangingIndent = parserConf.hangingIndent || parserConf.indentUnit;

var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']);
var commonkeywords = ['as', 'assert', 'break', 'class', 'continue',
@@ -211,6 +212,11 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
break;
}
}
} else if (stream.match(/\s*($|#)/, false)) {
// An open paren/bracket/brace with only space or comments after it
// on the line will indent the next line a fixed amount, to make it
// easier to put arguments, list items, etc. on their own lines.
indentUnit = stream.indentation() + hangingIndent;
} else {
indentUnit = stream.column() + stream.current().length;
}
@@ -36,7 +36,11 @@ CodeMirror.defineMode("r", function(config) {
var word = stream.current();
if (atoms.propertyIsEnumerable(word)) return "atom";
if (keywords.propertyIsEnumerable(word)) {
if (blockkeywords.propertyIsEnumerable(word)) curPunc = "block";
// Block keywords start new blocks, except 'else if', which only starts
// one new block for the 'if', no block for the 'else'.
if (blockkeywords.propertyIsEnumerable(word) &&
!stream.match(/\s*if(\s+|$)/, false))
curPunc = "block";
return "keyword";
}
if (builtins.propertyIsEnumerable(word)) return "builtin";
@@ -4,7 +4,7 @@ CodeMirror.defineMode("spec", function() {
var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;

var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/;
var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preun|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros
var control_flow_simple = /^%(else|endif)/; // rpm control flow macros
var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros
@@ -12,7 +12,7 @@ CodeMirror.defineMode("ruby", function(config) {
"caller", "lambda", "proc", "public", "protected", "private", "require", "load",
"require_relative", "extend", "autoload", "__END__", "__FILE__", "__LINE__", "__dir__"
]);
var indentWords = wordObj(["def", "class", "case", "for", "while", "do", "module", "then",
var indentWords = wordObj(["def", "class", "case", "for", "while", "module", "then",
"catch", "loop", "proc", "begin"]);
var dedentWords = wordObj(["end", "until"]);
var matching = {"[": "]", "{": "}", "(": ")"};
@@ -214,6 +214,8 @@ CodeMirror.defineMode("ruby", function(config) {
else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())
kwtype = "indent";
else if (word == "do" && state.context.indented < state.indented)
kwtype = "indent";
}
if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style;
if (curPunc == "|") state.varList = !state.varList;
@@ -40,8 +40,10 @@ CodeMirror.defineMode('smalltalk', function(config) {
stream.next();
token = nextSymbol(stream, new Context(nextSymbol, context));
} else {
stream.eatWhile(/[^ .\[\]()]/);
token.name = 'string-2';
if (stream.eatWhile(/[^ .{}\[\]()]/))
token.name = 'string-2';
else
token.name = 'meta';
}

} else if (aChar === '$') {
2 mode/smartymixed/smartymixed.js 100755 → 100644
@@ -159,8 +159,6 @@ CodeMirror.defineMode("smartymixed", function(config) {
return htmlMixedMode.indent(state.htmlMixedState, textAfter);
},

electricChars: "/{}:",

innerMode: function(state) {
return {
state: state.localState || state.htmlMixedState,
@@ -177,9 +177,10 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {

indent: function(state, textAfter) {
var cx = state.context;
if (!cx) return CodeMirror.Pass;
if (cx.align) return cx.col + (textAfter.charAt(0) == cx.type ? 0 : 1);
else return cx.indent + config.indentUnit;
if (!cx) return 0;
var closing = textAfter.charAt(0) == cx.type;
if (cx.align) return cx.col + (closing ? 0 : 1);
else return cx.indent + (closing ? 0 : config.indentUnit);
},

blockCommentStart: "/*",
@@ -326,7 +327,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
name: "sql",
client: set("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"),
keywords: set("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"),
builtin: set("bfile blob character clob dec float int integer mlslabel natural naturaln nchar nclob number numeric nvarchar2 real rowtype signtype smallint string varchar varchar2 abs acos add_months ascii asin atan atan2 average bfilename ceil chartorowid chr concat convert cos cosh count decode deref dual dump dup_val_on_index empty error exp false floor found glb greatest hextoraw initcap instr instrb isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mod months_between new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null nvl others power rawtohex reftohex round rowcount rowidtochar rpad rtrim sign sin sinh soundex sqlcode sqlerrm sqrt stddev substr substrb sum sysdate tan tanh to_char to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid upper user userenv variance vsize"),
builtin: set("abs acos add_months ascii asin atan atan2 average bfile bfilename bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid upper user userenv varchar varchar2 variance varying vsize xml"),
operatorChars: /^[*+\-%<>!=~]/,
dateSQL: set("date time timestamp"),
support: set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber")
@@ -45,7 +45,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
var alignCDATA = parserConfig.alignCDATA;

// Return variables for tokenizers
var tagName, type;
var tagName, type, setStyle;

function inText(stream, state) {
function chain(parser) {
@@ -110,6 +110,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
return null;
} else if (ch == "<") {
state.tokenize = inText;
state.state = baseState;
state.tagName = state.tagStart = null;
var next = state.tokenize(stream, state);
return next ? next + " error" : "error";
} else if (/[\'\"]/.test(ch)) {
@@ -169,139 +171,124 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
};
}

var curState, curStream, setStyle;
function pass() {
for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
function Context(state, tagName, startOfLine) {
this.prev = state.context;
this.tagName = tagName;
this.indent = state.indented;
this.startOfLine = startOfLine;
if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
this.noIndent = true;
}
function cont() {
pass.apply(null, arguments);
return true;
function popContext(state) {
if (state.context) state.context = state.context.prev;
}

function pushContext(tagName, startOfLine) {
var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);
curState.context = {
prev: curState.context,
tagName: tagName,
indent: curState.indented,
startOfLine: startOfLine,
noIndent: noIndent
};
}
function popContext() {
if (curState.context) curState.context = curState.context.prev;
function maybePopContext(state, nextTagName) {
var parentTagName;
while (true) {
if (!state.context) {
return;
}
parentTagName = state.context.tagName.toLowerCase();
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
return;
}
popContext(state);
}
}

function element(type) {
function baseState(type, stream, state) {
if (type == "openTag") {
curState.tagName = tagName;
curState.tagStart = curStream.column();
return cont(attributes, endtag(curState.startOfLine));
state.tagName = tagName;
state.tagStart = stream.column();
return attrState;
} else if (type == "closeTag") {
var err = false;
if (curState.context) {
if (curState.context.tagName != tagName) {
if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
popContext();
}
err = !curState.context || curState.context.tagName != tagName;
if (state.context) {
if (state.context.tagName != tagName) {
if (Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName.toLowerCase()))
popContext(state);
err = !state.context || state.context.tagName != tagName;
}
} else {
err = true;
}
if (err) setStyle = "error";
return cont(endclosetag(err));
return err ? closeStateErr : closeState;
} else {
return baseState;
}
return cont();
}
function endtag(startOfLine) {
return function(type) {
var tagName = curState.tagName;
curState.tagName = curState.tagStart = null;
if (type == "selfcloseTag" ||
(type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))) {
maybePopContext(tagName.toLowerCase());
return cont();
}
if (type == "endTag") {
maybePopContext(tagName.toLowerCase());
pushContext(tagName, startOfLine);
return cont();
}
return cont();
};
}
function endclosetag(err) {
return function(type) {
if (err) setStyle = "error";
if (type == "endTag") { popContext(); return cont(); }
function closeState(type, _stream, state) {
if (type != "endTag") {
setStyle = "error";
return cont(arguments.callee);
};
}
function maybePopContext(nextTagName) {
var parentTagName;
while (true) {
if (!curState.context) {
return;
}
parentTagName = curState.context.tagName.toLowerCase();
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
return;
}
popContext();
return closeState;
}
popContext(state);
return baseState;
}
function closeStateErr(type, stream, state) {
setStyle = "error";
return closeState(type, stream, state);
}

function attributes(type) {
if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
if (type == "endTag" || type == "selfcloseTag") return pass();
function attrState(type, _stream, state) {
if (type == "word") {
setStyle = "attribute";
return attrEqState;
} else if (type == "endTag" || type == "selfcloseTag") {
var tagName = state.tagName, tagStart = state.tagStart;
state.tagName = state.tagStart = null;
if (type == "selfcloseTag" ||
Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase())) {
maybePopContext(state, tagName.toLowerCase());
} else {
maybePopContext(state, tagName.toLowerCase());
state.context = new Context(state, tagName, tagStart == state.indented);
}
return baseState;
}
setStyle = "error";
return cont(attributes);
return attrState;
}
function attribute(type) {
if (type == "equals") return cont(attvalue, attributes);
function attrEqState(type, stream, state) {
if (type == "equals") return attrValueState;
if (!Kludges.allowMissing) setStyle = "error";
else if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
return attrState(type, stream, state);
}
function attvalue(type) {
if (type == "string") return cont(attvaluemaybe);
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
function attrValueState(type, stream, state) {
if (type == "string") return attrContinuedState;
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
setStyle = "error";
return (type == "endTag" || type == "selfCloseTag") ? pass() : cont();
return attrState(type, stream, state);
}
function attvaluemaybe(type) {
if (type == "string") return cont(attvaluemaybe);
else return pass();
function attrContinuedState(type, stream, state) {
if (type == "string") return attrContinuedState;
return attrState(type, stream, state);
}

return {
startState: function() {
return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, tagStart: null, context: null};
return {tokenize: inText,
state: baseState,
indented: 0,
tagName: null, tagStart: null,
context: null};
},

token: function(stream, state) {
if (!state.tagName && stream.sol()) {
state.startOfLine = true;
if (!state.tagName && stream.sol())
state.indented = stream.indentation();
}
if (stream.eatSpace()) return null;

setStyle = type = tagName = null;
if (stream.eatSpace()) return null;
tagName = type = null;
var style = state.tokenize(stream, state);
state.type = type;
if ((style || type) && style != "comment") {
curState = state; curStream = stream;
while (true) {
var comb = state.cc.pop() || element;
if (comb(type || style)) break;
}
setStyle = null;
state.state = state.state(type || style, stream, state);
if (setStyle)
style = setStyle == "error" ? style + " error" : setStyle;
}
state.startOfLine = false;
if (setStyle)
style = setStyle == "error" ? style + " error" : setStyle;
return style;
},

@@ -311,8 +298,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
if (state.tokenize.isInAttribute) {
return state.stringStartCol + 1;
}
if ((state.tokenize != inTag && state.tokenize != inText) ||
context && context.noIndent)
if (context && context.noIndent) return CodeMirror.Pass;
if (state.tokenize != inTag && state.tokenize != inText)
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
// Indent the starts of attribute names.
if (state.tagName) {
@@ -1,19 +1,20 @@
{
"name": "codemirror",
"version":"3.20.0",
"version":"3.21.0",
"main": "lib/codemirror.js",
"description": "In-browser code editing made bearable",
"licenses": [{"type": "MIT",
"url": "http://codemirror.net/LICENSE"}],
"directories": {"lib": "./lib"},
"scripts": {"test": "node ./test/run.js"},
"devDependencies": {"node-static": "0.6.0"},
"devDependencies": {"node-static": "0.6.0",
"phantomjs": "1.9.2-5"},
"bugs": "http://github.com/marijnh/CodeMirror/issues",
"keywords": ["JavaScript", "CodeMirror", "Editor"],
"homepage": "http://codemirror.net",
"maintainers":[{"name": "Marijn Haverbeke",
"email": "marijnh@gmail.com",
"web": "http://marijnhaverbeke.nl"}],
"repository": {"type": "git",
"url": "http://marijnhaverbeke.nl/git/codemirror"}
"url": "https://github.com/marijnh/CodeMirror.git"}
}
@@ -48,4 +48,16 @@ namespace = "comment_";
cm.setCursor(1);
cm.execCommand("toggleComment");
}, "a;\n\nb;", "a;\n// \nb;");

test("dontMessWithStrings", "javascript", function(cm) {
cm.execCommand("toggleComment");
}, "console.log(\"/*string*/\");", "// console.log(\"/*string*/\");");

test("dontMessWithStrings2", "javascript", function(cm) {
cm.execCommand("toggleComment");
}, "console.log(\"// string\");", "// console.log(\"// string\");");

test("dontMessWithStrings3", "javascript", function(cm) {
cm.execCommand("toggleComment");
}, "// console.log(\"// string\");", "console.log(\"// string\");");
})();
@@ -57,7 +57,7 @@
run.apply(null, editors);
successful = true;
} finally {
if ((debug && !successful) || verbose) {
if (!successful || verbose) {
place.style.visibility = "visible";
} else {
for (var i = 0; i < editors.length; ++i)
@@ -1,4 +1,4 @@
var tests = [], debug = null, debugUsed = new Array(), allNames = [];
var tests = [], filters = [], allNames = [];

function Failure(why) {this.message = why;}
Failure.prototype.toString = function() { return this.message; };
@@ -32,7 +32,7 @@ function testCM(name, run, opts, expectedFail) {
run(cm);
successful = true;
} finally {
if ((debug && !successful) || verbose) {
if (!successful || verbose) {
place.style.visibility = "visible";
} else {
place.removeChild(cm.getWrapperElement());
@@ -42,39 +42,23 @@ function testCM(name, run, opts, expectedFail) {
}

function runTests(callback) {
if (debug) {
if (indexOf(debug, "verbose") === 0) {
verbose = true;
debug.splice(0, 1);
}
if (debug.length < 1) {
debug = null;
}
}
var totalTime = 0;
function step(i) {
if (i === tests.length){
running = false;
return callback("done");
}
}
var test = tests[i], expFail = test.expectedFail, startTime = +new Date;
if (debug !== null) {
var debugIndex = indexOf(debug, test.name);
if (debugIndex !== -1) {
// Remove from array for reporting incorrect tests later
debug.splice(debugIndex, 1);
} else {
var wildcardName = test.name.split("_")[0] + "_*";
debugIndex = indexOf(debug, wildcardName);
if (debugIndex !== -1) {
// Remove from array for reporting incorrect tests later
debug.splice(debugIndex, 1);
debugUsed.push(wildcardName);
} else {
debugIndex = indexOf(debugUsed, wildcardName);
if (debugIndex == -1) return step(i + 1);
if (filters.length) {
for (var j = 0; j < filters.length; j++) {
if (test.name.match(filters[j])) {
break;
}
}
if (j == filters.length) {
callback("skipped", test.name, message);
return step(i + 1);
}
}
var threw = false;
try {
@@ -127,13 +111,21 @@ function is(a, msg) {
}

function countTests() {
if (!debug) return tests.length;
if (!filters.length) 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;
for (var j = 0; j < filters.length; j++) {
if (name.match(filters[j])) {
++sum;
break;
}
}
}
return sum;
}

function parseTestFilter(s) {
if (/_\*$/.test(s)) return new RegExp("^" + s.slice(0, s.length - 2), "i");
else return new RegExp(s, "i");
}
@@ -125,6 +125,9 @@
sim("transposeExpr", "do foo[bar] dah",
Pos(0, 6), "Ctrl-Alt-T", txt("do [bar]foo dah"));

sim("clearMark", "abcde", Pos(0, 2), "Ctrl-Space", "Ctrl-F", "Ctrl-F",
"Ctrl-G", "Ctrl-W", txt("abcde"));

testCM("save", function(cm) {
var saved = false;
CodeMirror.commands.save = function(cm) { saved = cm.getValue(); };
@@ -72,11 +72,13 @@ <h2>Test Suite</h2>
<script src="test.js"></script>
<script src="doc_test.js"></script>
<script src="comment_test.js"></script>
<script src="search_test.js"></script>
<script src="mode_test.js"></script>
<script src="../mode/javascript/test.js"></script>
<script src="../mode/css/css.js"></script>
<script src="../mode/css/test.js"></script>
<script src="../mode/css/scss_test.js"></script>
<script src="../mode/css/less_test.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../mode/htmlmixed/htmlmixed.js"></script>
<script src="../mode/ruby/ruby.js"></script>
@@ -107,10 +109,11 @@ <h2>Test Suite</h2>
progressTotal = document.getElementById("progress_total").childNodes[0];
var count = 0,
failed = 0,
skipped = 0,
bad = "",
running = false, // Flag that states tests are running
quit = false, // Flag to quit tests ASAP
verbose = false; // Adds message for *every* test to output
quit = false, // Flag to quit tests ASAP
verbose = false; // Adds message for *every* test to output

function runHarness(){
if (running) {
@@ -119,19 +122,25 @@ <h2>Test Suite</h2>
setTimeout(function(){runHarness();}, 500);
return;
}
filters = [];
verbose = false;
if (window.location.hash.substr(1)){
debug = window.location.hash.substr(1).split(",");
} else {
debug = null;
var strings = window.location.hash.substr(1).split(",");
while (strings.length) {
var s = strings.shift();
if (s === "verbose")
verbose = true;
else
filters.push(parseTestFilter(decodeURIComponent(s)));;
}
}
quit = false;
running = true;
setStatus("Loading tests...");
count = 0;
failed = 0;
skipped = 0;
bad = "";
verbose = false;
debugUsed = Array();
totalTests = countTests();
progressTotal.nodeValue = " of " + totalTests;
progressRan.nodeValue = count;
@@ -164,12 +173,16 @@ <h2>Test Suite</h2>
}
function displayTest(type, name, customMessage) {
var message = "???";
if (type != "done") ++count;
if (type != "done" && type != "skipped") ++count;
progress.style.width = (count * (progress.parentNode.clientWidth - 2) / totalTests) + "px";
progressRan.nodeValue = count;
if (type == "ok") {
message = "Test '" + name + "' succeeded";
if (!verbose) customMessage = false;
} else if (type == "skipped") {
message = "Test '" + name + "' skipped";
++skipped;
if (!verbose) customMessage = false;
} else if (type == "expected") {
message = "Test '" + name + "' failed as expected";
if (!verbose) customMessage = false;
@@ -187,15 +200,11 @@ <h2>Test Suite</h2>
} else {
type += " ok";
message = "All passed";
if (skipped) {
message += " (" + skipped + " skipped)";
}
}
if (debug && debug.length) {
var bogusTests = totalTests - count;
message += " — " + bogusTests + " nonexistent test" +
(bogusTests > 1 ? "s" : "") + " requested by location.hash: " +
"`" + debug.join("`, `") + "`";
} else {
progressTotal.nodeValue = '';
}
progressTotal.nodeValue = '';
customMessage = true; // Hack to avoid adding to output
}
if (verbose && !customMessage) customMessage = message;
@@ -59,21 +59,18 @@
return {tokens: tokens, plain: plain};
}

test.indentation = function(name, mode, tokens, modeName) {
var data = parseTokens(tokens);
return test((modeName || mode.name) + "_indent_" + name, function() {
return compare(data.plain, data.tokens, mode, true);
});
};

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);
});
};

function compare(text, expected, mode, compareIndentation) {
function esc(str) {
return str.replace('&', '&amp;').replace('<', '&lt;');
}

function compare(text, expected, mode) {

var expectedOutput = [];
for (var i = 0; i < expected.length; i += 2) {
@@ -82,61 +79,49 @@
expectedOutput.push(sty, expected[i + 1]);
}

var observedOutput = highlight(text, mode, compareIndentation);

var pass, passStyle = "";
pass = highlightOutputsEqual(expectedOutput, observedOutput);
passStyle = pass ? 'mt-pass' : 'mt-fail';
var observedOutput = highlight(text, mode);

var s = '';
if (pass) {
s += '<div class="mt-test ' + passStyle + '">';
s += '<pre>' + text.replace('&', '&amp;').replace('<', '&lt;') + '</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.replace('&', '&amp;').replace('<', '&lt;') + '</pre>';
var s = "";
var diff = highlightOutputsDifferent(expectedOutput, observedOutput);
if (diff != null) {
s += '<div class="mt-test mt-fail">';
s += '<pre>' + esc(text) + '</pre>';
s += '<div class="cm-s-default">';
s += 'expected:';
s += prettyPrintOutputTable(expectedOutput);
s += prettyPrintOutputTable(expectedOutput, diff);
s += 'observed:';
s += prettyPrintOutputTable(observedOutput);
s += prettyPrintOutputTable(observedOutput, diff);
s += '</div>';
s += '</div>';
throw s;
}
if (observedOutput.indentFailures) {
for (var i = 0; i < observedOutput.indentFailures.length; i++)
s += "<div class='mt-test mt-fail'>" + esc(observedOutput.indentFailures[i]) + "</div>";
}
if (s) throw new Failure(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
*/
function highlight(string, mode, compareIndentation) {
function highlight(string, mode) {
var state = mode.startState()

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;
if (mode.indent) {
var ws = line.match(/^\s*/)[0];
var indent = mode.indent(state, line.slice(ws.length));
if (indent != CodeMirror.Pass && indent != ws.length)
(st.indentFailures || (st.indentFailures = [])).push(
"Indentation of line " + (i + 1) + " is " + indent + " (expected " + ws.length + ")");
}
var stream = new CodeMirror.StringStream(line);
if (line == "" && mode.blankLine) mode.blankLine(state);
/* Start copied code from CodeMirror.highlight */
while (!stream.eol()) {
var compare = mode.token(stream, state), substr = stream.current();
if(compareIndentation) compare = mode.indent(state) || null;
else if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' ');

stream.start = stream.pos;
var compare = mode.token(stream, state), substr = stream.current();
if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' ');
stream.start = stream.pos;
if (pos && st[pos-2] == compare && !newLine) {
st[pos-1] += substr;
} else if (substr) {
@@ -154,39 +139,22 @@
return st;
}

/**
* 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;
function highlightOutputsDifferent(o1, o2) {
var minLen = Math.min(o1.length, o2.length);
for (var i = 0; i < minLen; ++i)
if (o1[i] != o2[i]) return i >> 1;
if (o1.length > minLen || o2.length > minLen) return minLen;
}

/**
* 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) {
function prettyPrintOutputTable(output, diffAt) {
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(style).replace(/ +/g, " cm-") + '">' +
val.replace(/ /g,'\xb7').replace('&', '&amp;').replace('<', '&lt;') +
'<td class="mt-token"' + (i == diffAt * 2 ? " style='background: pink'" : "") + '>' +
'<span class="cm-' + esc(String(style)) + '">' +
esc(val.replace(/ /g,'\xb7')) +
'</span>' +
'</td>';
}
@@ -9,26 +9,30 @@ lint.checkDir("keymap");

var ok = lint.success();

var files = new (require('node-static').Server)('.');
var files = new (require('node-static').Server)();

var server = require('http').createServer(function (req, res) {
req.addListener('end', function () {
files.serve(req, res);
});
files.serve(req, res, function (err/*, result */) {
if (err) {
console.error(err);
process.exit(1);
}
});
}).resume();
}).addListener('error', function (err) {
throw err;
}).listen(3000, function () {
var child_process = require('child_process');
child_process.exec("which phantomjs", function (err) {
if (err) {
console.error("PhantomJS is not installed. Download from http://phantomjs.org");
process.exit(1);
}
var cmd = 'phantomjs test/phantom_driver.js';
child_process.exec(cmd, function (err, stdout) {
server.close();
console.log(stdout);
process.exit(err || !ok ? 1 : 0);
});
var childProcess = require('child_process');
var phantomjs = require("phantomjs");
var childArgs = [
require("path").join(__dirname, 'phantom_driver.js')
];
childProcess.execFile(phantomjs.path, childArgs, function (err, stdout, stderr) {
server.close();
console.log(stdout);
if (err) console.error(err);
if (stderr) console.error(stderr);
process.exit(err || stderr || !ok ? 1 : 0);
});
});