diff options
Diffstat (limited to 'codemirror_ui/lib/CodeMirror-2.3/mode/xquery')
9 files changed, 897 insertions, 0 deletions
diff --git a/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/index.html b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/index.html new file mode 100644 index 0000000..82f00d2 --- /dev/null +++ b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/index.html @@ -0,0 +1,222 @@ +<!doctype html> +<html> +<!-- +/* +Copyright (C) 2011 by MarkLogic Corporation +Author: Mike Brevoort <mike@brevoort.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +--> + <head> + <title>CodeMirror 2: JavaScript mode</title> + <link rel="stylesheet" href="../../lib/codemirror.css"> + <script src="http://codemirror.net/lib/codemirror.js"></script> + <script src="xquery.js"></script> + <link rel="stylesheet" href="../../doc/docs.css"> + <link rel="stylesheet" href="../../theme/xq-dark.css"> + <style type="text/css"> + .CodeMirror { + border-top: 1px solid black; border-bottom: 1px solid black; + } + .CodeMirror-scroll { + height:400px; + } + </style> + </head> + <body> + <h1>CodeMirror 2: XQuery mode</h1> + +<div class="cm-s-default"> + <textarea id="code" name="code"> +xquery version "1.0-ml"; +(: this is + : a + "comment" :) +let $let := <x attr="value">"test"<func>function() $var {function()} {$var}</func></x> +let $joe:=1 +return element element { + attribute attribute { 1 }, + element test { 'a' }, + attribute foo { "bar" }, + fn:doc()[ foo/@bar eq $let ], + //x } + +(: a more 'evil' test :) +(: Modified Blakeley example (: with nested comment :) ... :) +declare private function local:declare() {()}; +declare private function local:private() {()}; +declare private function local:function() {()}; +declare private function local:local() {()}; +let $let := <let>let $let := "let"</let> +return element element { + attribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } }, + attribute fn:doc { "bar" castable as xs:string }, + element text { text { "text" } }, + fn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ], + //fn:doc +} + + + +xquery version "1.0-ml"; + +(: Copyright 2006-2010 Mark Logic Corporation. :) + +(: + : Licensed under the Apache License, Version 2.0 (the "License"); + : you may not use this file except in compliance with the License. + : You may obtain a copy of the License at + : + : http://www.apache.org/licenses/LICENSE-2.0 + : + : Unless required by applicable law or agreed to in writing, software + : distributed under the License is distributed on an "AS IS" BASIS, + : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + : See the License for the specific language governing permissions and + : limitations under the License. + :) + +module namespace json = "http://marklogic.com/json"; +declare default function namespace "http://www.w3.org/2005/xpath-functions"; + +(: Need to backslash escape any double quotes, backslashes, and newlines :) +declare function json:escape($s as xs:string) as xs:string { + let $s := replace($s, "\\", "\\\\") + let $s := replace($s, """", "\\""") + let $s := replace($s, codepoints-to-string((13, 10)), "\\n") + let $s := replace($s, codepoints-to-string(13), "\\n") + let $s := replace($s, codepoints-to-string(10), "\\n") + return $s +}; + +declare function json:atomize($x as element()) as xs:string { + if (count($x/node()) = 0) then 'null' + else if ($x/@type = "number") then + let $castable := $x castable as xs:float or + $x castable as xs:double or + $x castable as xs:decimal + return + if ($castable) then xs:string($x) + else error(concat("Not a number: ", xdmp:describe($x))) + else if ($x/@type = "boolean") then + let $castable := $x castable as xs:boolean + return + if ($castable) then xs:string(xs:boolean($x)) + else error(concat("Not a boolean: ", xdmp:describe($x))) + else concat('"', json:escape($x), '"') +}; + +(: Print the thing that comes after the colon :) +declare function json:print-value($x as element()) as xs:string { + if (count($x/*) = 0) then + json:atomize($x) + else if ($x/@quote = "true") then + concat('"', json:escape(xdmp:quote($x/node())), '"') + else + string-join(('{', + string-join(for $i in $x/* return json:print-name-value($i), ","), + '}'), "") +}; + +(: Print the name and value both :) +declare function json:print-name-value($x as element()) as xs:string? { + let $name := name($x) + let $first-in-array := + count($x/preceding-sibling::*[name(.) = $name]) = 0 and + (count($x/following-sibling::*[name(.) = $name]) > 0 or $x/@array = "true") + let $later-in-array := count($x/preceding-sibling::*[name(.) = $name]) > 0 + return + + if ($later-in-array) then + () (: I was handled previously :) + else if ($first-in-array) then + string-join(('"', json:escape($name), '":[', + string-join((for $i in ($x, $x/following-sibling::*[name(.) = $name]) return json:print-value($i)), ","), + ']'), "") + else + string-join(('"', json:escape($name), '":', json:print-value($x)), "") +}; + +(:~ + Transforms an XML element into a JSON string representation. See http://json.org. + <p/> + Sample usage: + <pre> + xquery version "1.0-ml"; + import module namespace json="http://marklogic.com/json" at "json.xqy"; + json:serialize(&lt;foo&gt;&lt;bar&gt;kid&lt;/bar&gt;&lt;/foo&gt;) + </pre> + Sample transformations: + <pre> + &lt;e/&gt; becomes {"e":null} + &lt;e&gt;text&lt;/e&gt; becomes {"e":"text"} + &lt;e&gt;quote " escaping&lt;/e&gt; becomes {"e":"quote \" escaping"} + &lt;e&gt;backslash \ escaping&lt;/e&gt; becomes {"e":"backslash \\ escaping"} + &lt;e&gt;&lt;a&gt;text1&lt;/a&gt;&lt;b&gt;text2&lt;/b&gt;&lt;/e&gt; becomes {"e":{"a":"text1","b":"text2"}} + &lt;e&gt;&lt;a&gt;text1&lt;/a&gt;&lt;a&gt;text2&lt;/a&gt;&lt;/e&gt; becomes {"e":{"a":["text1","text2"]}} + &lt;e&gt;&lt;a array="true"&gt;text1&lt;/a&gt;&lt;/e&gt; becomes {"e":{"a":["text1"]}} + &lt;e&gt;&lt;a type="boolean"&gt;false&lt;/a&gt;&lt;/e&gt; becomes {"e":{"a":false}} + &lt;e&gt;&lt;a type="number"&gt;123.5&lt;/a&gt;&lt;/e&gt; becomes {"e":{"a":123.5}} + &lt;e quote="true"&gt;&lt;div attrib="value"/&gt;&lt;/e&gt; becomes {"e":"&lt;div attrib=\"value\"/&gt;"} + </pre> + <p/> + Namespace URIs are ignored. Namespace prefixes are included in the JSON name. + <p/> + Attributes are ignored, except for the special attribute @array="true" that + indicates the JSON serialization should write the node, even if single, as an + array, and the attribute @type that can be set to "boolean" or "number" to + dictate the value should be written as that type (unquoted). There's also + an @quote attribute that when set to true writes the inner content as text + rather than as structured JSON, useful for sending some XHTML over the + wire. + <p/> + Text nodes within mixed content are ignored. + + @param $x Element node to convert + @return String holding JSON serialized representation of $x + + @author Jason Hunter + @version 1.0.1 + + Ported to xquery 1.0-ml; double escaped backslashes in json:escape +:) +declare function json:serialize($x as element()) as xs:string { + string-join(('{', json:print-name-value($x), '}'), "") +}; + </textarea> +</div> + + <script> + var editor = CodeMirror.fromTextArea(document.getElementById("code"), { + lineNumbers: true, + matchBrackets: true, + theme: "xq-dark" + }); + </script> + + <p><strong>MIME types defined:</strong> <code>application/xquery</code>.</p> + + <p>Development of the CodeMirror XQuery mode was sponsored by + <a href="http://marklogic.com">MarkLogic</a> and developed by + <a href="https://twitter.com/mbrevoort">Mike Brevoort</a>. + </p> + + </body> +</html> diff --git a/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/index.html b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/index.html new file mode 100644 index 0000000..ba82e54 --- /dev/null +++ b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/index.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html> + <head> + <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css"/> + <script src="http://code.jquery.com/jquery-latest.js"> </script> + <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-git.js"></script> + + <script src="../../../lib/codemirror.js"></script> + <script src="../xquery.js"></script> + + <script type="text/javascript" src="testBase.js"></script> + <script type="text/javascript" src="testMultiAttr.js"></script> + <script type="text/javascript" src="testQuotes.js"></script> + <script type="text/javascript" src="testEmptySequenceKeyword.js"></script> + <script type="text/javascript" src="testProcessingInstructions.js"></script> + <script type="text/javascript" src="testNamespaces.js"></script> + </head> + <body> + <h1 id="qunit-header">XQuery CodeMirror Mode</h1> + <h2 id="qunit-banner"></h2> + <h2 id="qunit-userAgent"></h2> + <ol id="qunit-tests"> + </ol> + <div id="sandbox" style="right:5000px; position:absolute; "></div> + </body> +</html> diff --git a/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testBase.js b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testBase.js new file mode 100644 index 0000000..d40e9ee --- /dev/null +++ b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testBase.js @@ -0,0 +1,42 @@ + $(document).ready(function(){ + module("testBase"); + test("eviltest", function() { + expect(1); + + var input = 'xquery version "1.0-ml";\ + (: this is\ + : a \ + "comment" :)\ + let $let := <x attr="value">"test"<func>function() $var {function()} {$var}</func></x>\ + let $joe:=1\ + return element element {\ + attribute attribute { 1 },\ + element test { 'a' }, \ + attribute foo { "bar" },\ + fn:doc()[ foo/@bar eq $let ],\ + //x } \ + \ + (: a more \'evil\' test :)\ + (: Modified Blakeley example (: with nested comment :) ... :)\ + declare private function local:declare() {()};\ + declare private function local:private() {()};\ + declare private function local:function() {()};\ + declare private function local:local() {()};\ + let $let := <let>let $let := "let"</let>\ + return element element {\ + attribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } },\ + attribute fn:doc { "bar" castable as xs:string },\ + element text { text { "text" } },\ + fn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ],\ + //fn:doc\ + }'; + var expected = '<span class="cm-keyword">xquery</span> <span class="cm-keyword">version</span> <span class="cm-string">"1.0-ml"</span><span class="cm-variable cm-def">;</span> <span class="cm-comment">(: this is : a "comment" :)</span> <span class="cm-keyword">let</span> <span class="cm-variable">$let</span> <span class="cm-keyword">:=</span> <span class="cm-tag"><x </span><span class="cm-attribute">attr</span>=<span class="cm-string">"value"</span><span class="cm-tag">></span><span class="cm-word">"test"</span><span class="cm-tag"><func></span><span class="cm-word">function()</span> <span class="cm-word">$var</span> {<span class="cm-keyword">function</span>()} {<span class="cm-variable">$var</span>}<span class="cm-tag"></func></x></span> <span class="cm-keyword">let</span> <span class="cm-variable">$joe</span><span class="cm-keyword">:=</span><span class="cm-atom">1</span> <span class="cm-keyword">return</span> <span class="cm-keyword">element</span> <span class="cm-word">element</span> { <span class="cm-keyword">attribute</span> <span class="cm-word">attribute</span> { <span class="cm-atom">1</span> }, <span class="cm-keyword">element</span> <span class="cm-word">test</span> { <span class="cm-string">\'a\'</span> }, <span class="cm-keyword">attribute</span> <span class="cm-word">foo</span> { <span class="cm-string">"bar"</span> }, <span class="cm-variable cm-def">fn:doc</span>()[ <span class="cm-word">foo</span><span class="cm-keyword">/</span><span class="cm-word">@bar</span> <span class="cm-keyword">eq</span> <span class="cm-variable">$let</span> ], <span class="cm-keyword">//</span><span class="cm-word">x</span> } <span class="cm-comment">(: a more \'evil\' test :)</span> <span class="cm-comment">(: Modified Blakeley example (: with nested comment :) ... :)</span> <span class="cm-keyword">declare</span> <span class="cm-keyword">private</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">local:declare</span>() {()}<span class="cm-word">;</span> <span class="cm-keyword">declare</span> <span class="cm-keyword">private</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">local:private</span>() {()}<span class="cm-word">;</span> <span class="cm-keyword">declare</span> <span class="cm-keyword">private</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">local:function</span>() {()}<span class="cm-word">;</span> <span class="cm-keyword">declare</span> <span class="cm-keyword">private</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">local:local</span>() {()}<span class="cm-word">;</span> <span class="cm-keyword">let</span> <span class="cm-variable">$let</span> <span class="cm-keyword">:=</span> <span class="cm-tag"><let></span><span class="cm-word">let</span> <span class="cm-word">$let</span> <span class="cm-word">:=</span> <span class="cm-word">"let"</span><span class="cm-tag"></let></span> <span class="cm-keyword">return</span> <span class="cm-keyword">element</span> <span class="cm-word">element</span> { <span class="cm-keyword">attribute</span> <span class="cm-word">attribute</span> { <span class="cm-keyword">try</span> { <span class="cm-variable cm-def">xdmp:version</span>() } <span class="cm-keyword">catch</span>(<span class="cm-variable">$e</span>) { <span class="cm-variable cm-def">xdmp:log</span>(<span class="cm-variable">$e</span>) } }, <span class="cm-keyword">attribute</span> <span class="cm-word">fn:doc</span> { <span class="cm-string">"bar"</span> <span class="cm-word">castable</span> <span class="cm-keyword">as</span> <span class="cm-atom">xs:string</span> }, <span class="cm-keyword">element</span> <span class="cm-word">text</span> { <span class="cm-keyword">text</span> { <span class="cm-string">"text"</span> } }, <span class="cm-variable cm-def">fn:doc</span>()[ <span class="cm-qualifier">child::</span><span class="cm-word">eq</span><span class="cm-keyword">/</span>(<span class="cm-word">@bar</span> <span class="cm-keyword">|</span> <span class="cm-qualifier">attribute::</span><span class="cm-word">attribute</span>) <span class="cm-keyword">eq</span> <span class="cm-variable">$let</span> ], <span class="cm-keyword">//</span><span class="cm-word">fn:doc</span> }'; + + $("#sandbox").html('<textarea id="editor">' + input + '</textarea>'); + var editor = CodeMirror.fromTextArea($("#editor")[0]); + var result = $(".CodeMirror-lines div div pre")[0].innerHTML; + + equal(result, expected); + $("#editor").html(""); + }); + }); diff --git a/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testEmptySequenceKeyword.js b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testEmptySequenceKeyword.js new file mode 100644 index 0000000..39ed090 --- /dev/null +++ b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testEmptySequenceKeyword.js @@ -0,0 +1,16 @@ +$(document).ready(function(){ + module("testEmptySequenceKeyword"); + test("testEmptySequenceKeyword", function() { + expect(1); + + var input = '"foo" instance of empty-sequence()'; + var expected = '<span class="cm-string">"foo"</span> <span class="cm-keyword">instance</span> <span class="cm-keyword">of</span> <span class="cm-keyword">empty-sequence</span>()'; + + $("#sandbox").html('<textarea id="editor">' + input + '</textarea>'); + var editor = CodeMirror.fromTextArea($("#editor")[0]); + var result = $(".CodeMirror-lines div div pre")[0].innerHTML; + + equal(result, expected); + $("#editor").html(""); + }); +}); diff --git a/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testMultiAttr.js b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testMultiAttr.js new file mode 100644 index 0000000..8e98c47 --- /dev/null +++ b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testMultiAttr.js @@ -0,0 +1,16 @@ + $(document).ready(function(){ + module("testMultiAttr"); + test("test1", function() { + expect(1); + + var expected = '<span class="cm-tag"><p </span><span class="cm-attribute">a1</span>=<span class="cm-string">"foo"</span> <span class="cm-attribute">a2</span>=<span class="cm-string">"bar"</span><span class="cm-tag">></span><span class="cm-word">hello</span> <span class="cm-word">world</span><span class="cm-tag"></p></span>'; + + $("#sandbox").html('<textarea id="editor"></textarea>'); + $("#editor").html('<p a1="foo" a2="bar">hello world</p>'); + var editor = CodeMirror.fromTextArea($("#editor")[0]); + var result = $(".CodeMirror-lines div div pre")[0].innerHTML; + + equal(result, expected); + $("#editor").html(""); + }); + });
\ No newline at end of file diff --git a/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testNamespaces.js b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testNamespaces.js new file mode 100644 index 0000000..4efea63 --- /dev/null +++ b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testNamespaces.js @@ -0,0 +1,91 @@ +$(document).ready(function(){ + module("test namespaces"); + +// -------------------------------------------------------------------------------- +// this test is based on this: +//http://mbrevoort.github.com/CodeMirror2/#!exprSeqTypes/PrologExpr/VariableProlog/ExternalVariablesWith/K2-ExternalVariablesWith-10.xq +// -------------------------------------------------------------------------------- + test("test namespaced variable", function() { + expect(1); + + var input = 'declare namespace e = "http://example.com/ANamespace";\ +declare variable $e:exampleComThisVarIsNotRecognized as element(*) external;'; + + var expected = '<span class="cm-keyword">declare</span> <span class="cm-keyword">namespace</span> <span class="cm-word">e</span> <span class="cm-keyword">=</span> <span class="cm-string">"http://example.com/ANamespace"</span><span class="cm-word">;declare</span> <span class="cm-keyword">variable</span> <span class="cm-variable">$e:exampleComThisVarIsNotRecognized</span> <span class="cm-keyword">as</span> <span class="cm-keyword">element</span>(<span class="cm-keyword">*</span>) <span class="cm-word">external;</span>'; + + $("#sandbox").html('<textarea id="editor">' + input + '</textarea>'); + var editor = CodeMirror.fromTextArea($("#editor")[0]); + var result = $(".CodeMirror-lines div div pre")[0].innerHTML; + + equal(result, expected); + $("#editor").html(""); + }); + + +// -------------------------------------------------------------------------------- +// this test is based on: +// http://mbrevoort.github.com/CodeMirror2/#!Basics/EQNames/eqname-002.xq +// -------------------------------------------------------------------------------- + test("test EQName variable", function() { + expect(1); + + var input = 'declare variable $"http://www.example.com/ns/my":var := 12;\ +<out>{$"http://www.example.com/ns/my":var}</out>'; + + var expected = '<span class="cm-keyword">declare</span> <span class="cm-keyword">variable</span> <span class="cm-variable">$"http://www.example.com/ns/my":var</span> <span class="cm-keyword">:=</span> <span class="cm-atom">12</span><span class="cm-word">;</span><span class="cm-tag"><out></span>{<span class="cm-variable">$"http://www.example.com/ns/my":var</span>}<span class="cm-tag"></out></span>'; + + $("#sandbox").html('<textarea id="editor">' + input + '</textarea>'); + var editor = CodeMirror.fromTextArea($("#editor")[0]); + var result = $(".CodeMirror-lines div div pre")[0].innerHTML; + + equal(result, expected); + $("#editor").html(""); + }); + +// -------------------------------------------------------------------------------- +// this test is based on: +// http://mbrevoort.github.com/CodeMirror2/#!Basics/EQNames/eqname-003.xq +// -------------------------------------------------------------------------------- + test("test EQName function", function() { + expect(1); + + var input = 'declare function "http://www.example.com/ns/my":fn ($a as xs:integer) as xs:integer {\ + $a + 2\ +};\ +<out>{"http://www.example.com/ns/my":fn(12)}</out>'; + + var expected = '<span class="cm-keyword">declare</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">"http://www.example.com/ns/my":fn</span> (<span class="cm-variable">$a</span> <span class="cm-keyword">as</span> <span class="cm-atom">xs:integer</span>) <span class="cm-keyword">as</span> <span class="cm-atom">xs:integer</span> { <span class="cm-variable">$a</span> <span class="cm-keyword">+</span> <span class="cm-atom">2</span>}<span class="cm-word">;</span><span class="cm-tag"><out></span>{<span class="cm-variable cm-def">"http://www.example.com/ns/my":fn</span>(<span class="cm-atom">12</span>)}<span class="cm-tag"></out></span>'; + + $("#sandbox").html('<textarea id="editor">' + input + '</textarea>'); + var editor = CodeMirror.fromTextArea($("#editor")[0]); + var result = $(".CodeMirror-lines div div pre")[0].innerHTML; + + equal(result, expected); + $("#editor").html(""); + }); + +// -------------------------------------------------------------------------------- +// this test is based on: +// http://mbrevoort.github.com/CodeMirror2/#!Basics/EQNames/eqname-003.xq +// -------------------------------------------------------------------------------- + test("test EQName function with single quotes", function() { + expect(1); + + var input = 'declare function \'http://www.example.com/ns/my\':fn ($a as xs:integer) as xs:integer {\ + $a + 2\ +};\ +<out>{\'http://www.example.com/ns/my\':fn(12)}</out>'; + + var expected = '<span class="cm-keyword">declare</span> <span class="cm-keyword">function</span> <span class="cm-variable cm-def">\'http://www.example.com/ns/my\':fn</span> (<span class="cm-variable">$a</span> <span class="cm-keyword">as</span> <span class="cm-atom">xs:integer</span>) <span class="cm-keyword">as</span> <span class="cm-atom">xs:integer</span> { <span class="cm-variable">$a</span> <span class="cm-keyword">+</span> <span class="cm-atom">2</span>}<span class="cm-word">;</span><span class="cm-tag"><out></span>{<span class="cm-variable cm-def">\'http://www.example.com/ns/my\':fn</span>(<span class="cm-atom">12</span>)}<span class="cm-tag"></out></span>'; + + $("#sandbox").html('<textarea id="editor">' + input + '</textarea>'); + var editor = CodeMirror.fromTextArea($("#editor")[0]); + var result = $(".CodeMirror-lines div div pre")[0].innerHTML; + + equal(result, expected); + $("#editor").html(""); + }); + +}); + + diff --git a/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testProcessingInstructions.js b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testProcessingInstructions.js new file mode 100644 index 0000000..9b75305 --- /dev/null +++ b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testProcessingInstructions.js @@ -0,0 +1,16 @@ +$(document).ready(function(){ + module("testProcessingInstructions"); + test("testProcessingInstructions", function() { + expect(1); + + var input = 'data(<?target content?>) instance of xs:string'; + var expected = '<span class="cm-variable cm-def">data</span>(<span class="cm-comment cm-meta"><?target content?></span>) <span class="cm-keyword">instance</span> <span class="cm-keyword">of</span> <span class="cm-atom">xs:string</span>'; + + $("#sandbox").html('<textarea id="editor">' + input + '</textarea>'); + var editor = CodeMirror.fromTextArea($("#editor")[0]); + var result = $(".CodeMirror-lines div div pre")[0].innerHTML; + + equal(result, expected); + $("#editor").html(""); + }); +}); diff --git a/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testQuotes.js b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testQuotes.js new file mode 100644 index 0000000..79e5142 --- /dev/null +++ b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/test/testQuotes.js @@ -0,0 +1,19 @@ + $(document).ready(function(){ + module("testQuoteEscape"); + test("testQuoteEscapeDouble", function() { + expect(1); + + var input = 'let $rootfolder := "c:\\builds\\winnt\\HEAD\\qa\\scripts\\"\ +let $keysfolder := concat($rootfolder, "keys\\")\ +return\ +$keysfolder'; + var expected = '<span class="cm-keyword">let</span> <span class="cm-variable">$rootfolder</span> <span class="cm-keyword">:=</span> <span class="cm-string">"c:\\builds\\winnt\\HEAD\\qa\\scripts\\"</span><span class="cm-keyword">let</span> <span class="cm-variable">$keysfolder</span> <span class="cm-keyword">:=</span> <span class="cm-variable cm-def">concat</span>(<span class="cm-variable">$rootfolder</span>, <span class="cm-string">"keys\\"</span>)<span class="cm-word">return$keysfolder</span>'; + + $("#sandbox").html('<textarea id="editor">' + input + '</textarea>'); + var editor = CodeMirror.fromTextArea($("#editor")[0]); + var result = $(".CodeMirror-lines div div pre")[0].innerHTML; + + equal(result, expected); + $("#editor").html(""); + }); + }); diff --git a/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/xquery.js b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/xquery.js new file mode 100644 index 0000000..78916da --- /dev/null +++ b/codemirror_ui/lib/CodeMirror-2.3/mode/xquery/xquery.js @@ -0,0 +1,448 @@ +/* +Copyright (C) 2011 by MarkLogic Corporation +Author: Mike Brevoort <mike@brevoort.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +CodeMirror.defineMode("xquery", function(config, parserConfig) { + + // The keywords object is set to the result of this self executing + // function. Each keyword is a property of the keywords object whose + // value is {type: atype, style: astyle} + var keywords = function(){ + // conveinence functions used to build keywords object + function kw(type) {return {type: type, style: "keyword"};} + var A = kw("keyword a") + , B = kw("keyword b") + , C = kw("keyword c") + , operator = kw("operator") + , atom = {type: "atom", style: "atom"} + , punctuation = {type: "punctuation", style: ""} + , qualifier = {type: "axis_specifier", style: "qualifier"}; + + // kwObj is what is return from this function at the end + var kwObj = { + 'if': A, 'switch': A, 'while': A, 'for': A, + 'else': B, 'then': B, 'try': B, 'finally': B, 'catch': B, + 'element': C, 'attribute': C, 'let': C, 'implements': C, 'import': C, 'module': C, 'namespace': C, + 'return': C, 'super': C, 'this': C, 'throws': C, 'where': C, 'private': C, + ',': punctuation, + 'null': atom, 'fn:false()': atom, 'fn:true()': atom + }; + + // a list of 'basic' keywords. For each add a property to kwObj with the value of + // {type: basic[i], style: "keyword"} e.g. 'after' --> {type: "after", style: "keyword"} + var basic = ['after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before', + 'by','case','cast','child','comment','declare','default','define','descendant','descendant-or-self', + 'descending','document','document-node','element','else','eq','every','except','external','following', + 'following-sibling','follows','for','function','if','import','in','instance','intersect','item', + 'let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding', + 'preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element', + 'self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where', + 'xquery', 'empty-sequence']; + for(var i=0, l=basic.length; i < l; i++) { kwObj[basic[i]] = kw(basic[i])}; + + // a list of types. For each add a property to kwObj with the value of + // {type: "atom", style: "atom"} + var types = ['xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime', + 'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary', + 'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration']; + for(var i=0, l=types.length; i < l; i++) { kwObj[types[i]] = atom;}; + + // each operator will add a property to kwObj with value of {type: "operator", style: "keyword"} + var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-']; + for(var i=0, l=operators.length; i < l; i++) { kwObj[operators[i]] = operator;}; + + // each axis_specifiers will add a property to kwObj with value of {type: "axis_specifier", style: "qualifier"} + var axis_specifiers = ["self::", "attribute::", "child::", "descendant::", "descendant-or-self::", "parent::", + "ancestor::", "ancestor-or-self::", "following::", "preceding::", "following-sibling::", "preceding-sibling::"]; + for(var i=0, l=axis_specifiers.length; i < l; i++) { kwObj[axis_specifiers[i]] = qualifier; }; + + return kwObj; + }(); + + // Used as scratch variables to communicate multiple values without + // consing up tons of objects. + var type, content; + + function ret(tp, style, cont) { + type = tp; content = cont; + return style; + } + + function chain(stream, state, f) { + state.tokenize = f; + return f(stream, state); + } + + // the primary mode tokenizer + function tokenBase(stream, state) { + var ch = stream.next(), + mightBeFunction = false, + isEQName = isEQNameAhead(stream); + + // an XML tag (if not in some sub, chained tokenizer) + if (ch == "<") { + if(stream.match("!--", true)) + return chain(stream, state, tokenXMLComment); + + if(stream.match("![CDATA", false)) { + state.tokenize = tokenCDATA; + return ret("tag", "tag"); + } + + if(stream.match("?", false)) { + return chain(stream, state, tokenPreProcessing); + } + + var isclose = stream.eat("/"); + stream.eatSpace(); + var tagName = "", c; + while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; + + return chain(stream, state, tokenTag(tagName, isclose)); + } + // start code block + else if(ch == "{") { + pushStateStack(state,{ type: "codeblock"}); + return ret("", ""); + } + // end code block + else if(ch == "}") { + popStateStack(state); + return ret("", ""); + } + // if we're in an XML block + else if(isInXmlBlock(state)) { + if(ch == ">") + return ret("tag", "tag"); + else if(ch == "/" && stream.eat(">")) { + popStateStack(state); + return ret("tag", "tag"); + } + else + return ret("word", "word"); + } + // if a number + else if (/\d/.test(ch)) { + stream.match(/^\d*(?:\.\d*)?(?:E[+\-]?\d+)?/); + return ret("number", "atom"); + } + // comment start + else if (ch === "(" && stream.eat(":")) { + pushStateStack(state, { type: "comment"}); + return chain(stream, state, tokenComment); + } + // quoted string + else if ( !isEQName && (ch === '"' || ch === "'")) + return chain(stream, state, tokenString(ch)); + // variable + else if(ch === "$") { + return chain(stream, state, tokenVariable); + } + // assignment + else if(ch ===":" && stream.eat("=")) { + return ret("operator", "keyword"); + } + // open paren + else if(ch === "(") { + pushStateStack(state, { type: "paren"}); + return ret("", ""); + } + // close paren + else if(ch === ")") { + popStateStack(state); + return ret("", ""); + } + // open paren + else if(ch === "[") { + pushStateStack(state, { type: "bracket"}); + return ret("", ""); + } + // close paren + else if(ch === "]") { + popStateStack(state); + return ret("", ""); + } + else { + var known = keywords.propertyIsEnumerable(ch) && keywords[ch]; + + // if there's a EQName ahead, consume the rest of the string portion, it's likely a function + if(isEQName && ch === '\"') while(stream.next() !== '"'){} + if(isEQName && ch === '\'') while(stream.next() !== '\''){} + + // gobble up a word if the character is not known + if(!known) stream.eatWhile(/[\w\$_-]/); + + // gobble a colon in the case that is a lib func type call fn:doc + var foundColon = stream.eat(":") + + // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier + // which should get matched as a keyword + if(!stream.eat(":") && foundColon) { + stream.eatWhile(/[\w\$_-]/); + } + // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort) + if(stream.match(/^[ \t]*\(/, false)) { + mightBeFunction = true; + } + // is the word a keyword? + var word = stream.current(); + known = keywords.propertyIsEnumerable(word) && keywords[word]; + + // if we think it's a function call but not yet known, + // set style to variable for now for lack of something better + if(mightBeFunction && !known) known = {type: "function_call", style: "variable def"}; + + // if the previous word was element, attribute, axis specifier, this word should be the name of that + if(isInXmlConstructor(state)) { + popStateStack(state); + return ret("word", "word", word); + } + // as previously checked, if the word is element,attribute, axis specifier, call it an "xmlconstructor" and + // push the stack so we know to look for it on the next word + if(word == "element" || word == "attribute" || known.type == "axis_specifier") pushStateStack(state, {type: "xmlconstructor"}); + + // if the word is known, return the details of that else just call this a generic 'word' + return known ? ret(known.type, known.style, word) : + ret("word", "word", word); + } + } + + // handle comments, including nested + function tokenComment(stream, state) { + var maybeEnd = false, maybeNested = false, nestedCount = 0, ch; + while (ch = stream.next()) { + if (ch == ")" && maybeEnd) { + if(nestedCount > 0) + nestedCount--; + else { + popStateStack(state); + break; + } + } + else if(ch == ":" && maybeNested) { + nestedCount++; + } + maybeEnd = (ch == ":"); + maybeNested = (ch == "("); + } + + return ret("comment", "comment"); + } + + // tokenizer for string literals + // optionally pass a tokenizer function to set state.tokenize back to when finished + function tokenString(quote, f) { + return function(stream, state) { + var ch; + + if(isInString(state) && stream.current() == quote) { + popStateStack(state); + if(f) state.tokenize = f; + return ret("string", "string"); + } + + pushStateStack(state, { type: "string", name: quote, tokenize: tokenString(quote, f) }); + + // if we're in a string and in an XML block, allow an embedded code block + if(stream.match("{", false) && isInXmlAttributeBlock(state)) { + state.tokenize = tokenBase; + return ret("string", "string"); + } + + + while (ch = stream.next()) { + if (ch == quote) { + popStateStack(state); + if(f) state.tokenize = f; + break; + } + else { + // if we're in a string and in an XML block, allow an embedded code block in an attribute + if(stream.match("{", false) && isInXmlAttributeBlock(state)) { + state.tokenize = tokenBase; + return ret("string", "string"); + } + + } + } + + return ret("string", "string"); + }; + } + + // tokenizer for variables + function tokenVariable(stream, state) { + var isVariableChar = /[\w\$_-]/; + + // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote + if(stream.eat("\"")) { + while(stream.next() !== '\"'){}; + stream.eat(":"); + } else { + stream.eatWhile(isVariableChar); + if(!stream.match(":=", false)) stream.eat(":"); + } + stream.eatWhile(isVariableChar); + state.tokenize = tokenBase; + return ret("variable", "variable"); + } + + // tokenizer for XML tags + function tokenTag(name, isclose) { + return function(stream, state) { + stream.eatSpace(); + if(isclose && stream.eat(">")) { + popStateStack(state); + state.tokenize = tokenBase; + return ret("tag", "tag"); + } + // self closing tag without attributes? + if(!stream.eat("/")) + pushStateStack(state, { type: "tag", name: name, tokenize: tokenBase}); + if(!stream.eat(">")) { + state.tokenize = tokenAttribute; + return ret("tag", "tag"); + } + else { + state.tokenize = tokenBase; + } + return ret("tag", "tag"); + } + } + + // tokenizer for XML attributes + function tokenAttribute(stream, state) { + var ch = stream.next(); + + if(ch == "/" && stream.eat(">")) { + if(isInXmlAttributeBlock(state)) popStateStack(state); + if(isInXmlBlock(state)) popStateStack(state); + return ret("tag", "tag"); + } + if(ch == ">") { + if(isInXmlAttributeBlock(state)) popStateStack(state); + return ret("tag", "tag"); + } + if(ch == "=") + return ret("", ""); + // quoted string + if (ch == '"' || ch == "'") + return chain(stream, state, tokenString(ch, tokenAttribute)); + + if(!isInXmlAttributeBlock(state)) + pushStateStack(state, { type: "attribute", name: name, tokenize: tokenAttribute}); + + stream.eat(/[a-zA-Z_:]/); + stream.eatWhile(/[-a-zA-Z0-9_:.]/); + stream.eatSpace(); + + // the case where the attribute has not value and the tag was closed + if(stream.match(">", false) || stream.match("/", false)) { + popStateStack(state); + state.tokenize = tokenBase; + } + + return ret("attribute", "attribute"); + } + + // handle comments, including nested + function tokenXMLComment(stream, state) { + while (ch = stream.next()) { + if (ch == "-" && stream.match("->", true)) { + state.tokenize = tokenBase; + return ret("comment", "comment"); + } + } + } + + + // handle CDATA + function tokenCDATA(stream, state) { + while (ch = stream.next()) { + if (ch == "]" && stream.match("]", true)) { + state.tokenize = tokenBase; + return ret("comment", "comment"); + } + } + } + + // handle preprocessing instructions + function tokenPreProcessing(stream, state) { + while (ch = stream.next()) { + if (ch == "?" && stream.match(">", true)) { + state.tokenize = tokenBase; + return ret("comment", "comment meta"); + } + } + } + + + // functions to test the current context of the state + function isInXmlBlock(state) { return isIn(state, "tag"); } + function isInXmlAttributeBlock(state) { return isIn(state, "attribute"); } + function isInCodeBlock(state) { return isIn(state, "codeblock"); } + function isInXmlConstructor(state) { return isIn(state, "xmlconstructor"); } + function isInString(state) { return isIn(state, "string"); } + + function isEQNameAhead(stream) { + // assume we've already eaten a quote (") + if(stream.current() === '"') + return stream.match(/^[^\"]+\"\:/, false); + else if(stream.current() === '\'') + return stream.match(/^[^\"]+\'\:/, false); + else + return false; + } + + function isIn(state, type) { + return (state.stack.length && state.stack[state.stack.length - 1].type == type); + } + + function pushStateStack(state, newState) { + state.stack.push(newState); + } + + function popStateStack(state) { + var popped = state.stack.pop(); + var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize + state.tokenize = reinstateTokenize || tokenBase; + } + + // the interface for the mode API + return { + startState: function(basecolumn) { + return { + tokenize: tokenBase, + cc: [], + stack: [] + }; + }, + + token: function(stream, state) { + if (stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + return style; + } + }; + +}); + +CodeMirror.defineMIME("application/xquery", "xquery"); |