forked from forgejo/forgejo
* Cleaning up public/ and documenting js/css libs. This commit mostly addresses #1484 by moving vendor'ed plugins into a vendor/ directory and documenting their upstream source and license in vendor/librejs.html. This also proves gitea is using only open source js/css libraries which helps toward reaching #1524. * Removing unused css file. The version of this file in use is located at: vendor/plugins/highlight/github.css * Cleaned up librejs.html and added javascript header A SafeJS function was added to templates/helper.go to allow keeping comments inside of javascript. A javascript comment was added in the header of templates/base/head.tmpl to mark all non-inline source as free. The librejs.html file was updated to meet the current librejs spec. I have now verified that the librejs plugin detects most of the scripts included in gitea and suspect the non-free detections are the result of a bug in the plugin. I believe this commit is enough to meet the C0.0 requirement of #1534. * Updating SafeJS function per lint suggestion * Added VERSIONS file, per request
This commit is contained in:
parent
64b7068846
commit
a915a09e4f
1339 changed files with 813 additions and 126 deletions
356
public/vendor/plugins/codemirror/mode/django/django.js
vendored
Normal file
356
public/vendor/plugins/codemirror/mode/django/django.js
vendored
Normal file
|
@ -0,0 +1,356 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),
|
||||
require("../../addon/mode/overlay"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror", "../htmlmixed/htmlmixed",
|
||||
"../../addon/mode/overlay"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("django:inner", function() {
|
||||
var keywords = ["block", "endblock", "for", "endfor", "true", "false", "filter", "endfilter",
|
||||
"loop", "none", "self", "super", "if", "elif", "endif", "as", "else", "import",
|
||||
"with", "endwith", "without", "context", "ifequal", "endifequal", "ifnotequal",
|
||||
"endifnotequal", "extends", "include", "load", "comment", "endcomment",
|
||||
"empty", "url", "static", "trans", "blocktrans", "endblocktrans", "now",
|
||||
"regroup", "lorem", "ifchanged", "endifchanged", "firstof", "debug", "cycle",
|
||||
"csrf_token", "autoescape", "endautoescape", "spaceless", "endspaceless",
|
||||
"ssi", "templatetag", "verbatim", "endverbatim", "widthratio"],
|
||||
filters = ["add", "addslashes", "capfirst", "center", "cut", "date",
|
||||
"default", "default_if_none", "dictsort",
|
||||
"dictsortreversed", "divisibleby", "escape", "escapejs",
|
||||
"filesizeformat", "first", "floatformat", "force_escape",
|
||||
"get_digit", "iriencode", "join", "last", "length",
|
||||
"length_is", "linebreaks", "linebreaksbr", "linenumbers",
|
||||
"ljust", "lower", "make_list", "phone2numeric", "pluralize",
|
||||
"pprint", "random", "removetags", "rjust", "safe",
|
||||
"safeseq", "slice", "slugify", "stringformat", "striptags",
|
||||
"time", "timesince", "timeuntil", "title", "truncatechars",
|
||||
"truncatechars_html", "truncatewords", "truncatewords_html",
|
||||
"unordered_list", "upper", "urlencode", "urlize",
|
||||
"urlizetrunc", "wordcount", "wordwrap", "yesno"],
|
||||
operators = ["==", "!=", "<", ">", "<=", ">="],
|
||||
wordOperators = ["in", "not", "or", "and"];
|
||||
|
||||
keywords = new RegExp("^\\b(" + keywords.join("|") + ")\\b");
|
||||
filters = new RegExp("^\\b(" + filters.join("|") + ")\\b");
|
||||
operators = new RegExp("^\\b(" + operators.join("|") + ")\\b");
|
||||
wordOperators = new RegExp("^\\b(" + wordOperators.join("|") + ")\\b");
|
||||
|
||||
// We have to return "null" instead of null, in order to avoid string
|
||||
// styling as the default, when using Django templates inside HTML
|
||||
// element attributes
|
||||
function tokenBase (stream, state) {
|
||||
// Attempt to identify a variable, template or comment tag respectively
|
||||
if (stream.match("{{")) {
|
||||
state.tokenize = inVariable;
|
||||
return "tag";
|
||||
} else if (stream.match("{%")) {
|
||||
state.tokenize = inTag;
|
||||
return "tag";
|
||||
} else if (stream.match("{#")) {
|
||||
state.tokenize = inComment;
|
||||
return "comment";
|
||||
}
|
||||
|
||||
// Ignore completely any stream series that do not match the
|
||||
// Django template opening tags.
|
||||
while (stream.next() != null && !stream.match(/\{[{%#]/, false)) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
// A string can be included in either single or double quotes (this is
|
||||
// the delimiter). Mark everything as a string until the start delimiter
|
||||
// occurs again.
|
||||
function inString (delimiter, previousTokenizer) {
|
||||
return function (stream, state) {
|
||||
if (!state.escapeNext && stream.eat(delimiter)) {
|
||||
state.tokenize = previousTokenizer;
|
||||
} else {
|
||||
if (state.escapeNext) {
|
||||
state.escapeNext = false;
|
||||
}
|
||||
|
||||
var ch = stream.next();
|
||||
|
||||
// Take into account the backslash for escaping characters, such as
|
||||
// the string delimiter.
|
||||
if (ch == "\\") {
|
||||
state.escapeNext = true;
|
||||
}
|
||||
}
|
||||
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
|
||||
// Apply Django template variable syntax highlighting
|
||||
function inVariable (stream, state) {
|
||||
// Attempt to match a dot that precedes a property
|
||||
if (state.waitDot) {
|
||||
state.waitDot = false;
|
||||
|
||||
if (stream.peek() != ".") {
|
||||
return "null";
|
||||
}
|
||||
|
||||
// Dot followed by a non-word character should be considered an error.
|
||||
if (stream.match(/\.\W+/)) {
|
||||
return "error";
|
||||
} else if (stream.eat(".")) {
|
||||
state.waitProperty = true;
|
||||
return "null";
|
||||
} else {
|
||||
throw Error ("Unexpected error while waiting for property.");
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to match a pipe that precedes a filter
|
||||
if (state.waitPipe) {
|
||||
state.waitPipe = false;
|
||||
|
||||
if (stream.peek() != "|") {
|
||||
return "null";
|
||||
}
|
||||
|
||||
// Pipe followed by a non-word character should be considered an error.
|
||||
if (stream.match(/\.\W+/)) {
|
||||
return "error";
|
||||
} else if (stream.eat("|")) {
|
||||
state.waitFilter = true;
|
||||
return "null";
|
||||
} else {
|
||||
throw Error ("Unexpected error while waiting for filter.");
|
||||
}
|
||||
}
|
||||
|
||||
// Highlight properties
|
||||
if (state.waitProperty) {
|
||||
state.waitProperty = false;
|
||||
if (stream.match(/\b(\w+)\b/)) {
|
||||
state.waitDot = true; // A property can be followed by another property
|
||||
state.waitPipe = true; // A property can be followed by a filter
|
||||
return "property";
|
||||
}
|
||||
}
|
||||
|
||||
// Highlight filters
|
||||
if (state.waitFilter) {
|
||||
state.waitFilter = false;
|
||||
if (stream.match(filters)) {
|
||||
return "variable-2";
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore all white spaces
|
||||
if (stream.eatSpace()) {
|
||||
state.waitProperty = false;
|
||||
return "null";
|
||||
}
|
||||
|
||||
// Identify numbers
|
||||
if (stream.match(/\b\d+(\.\d+)?\b/)) {
|
||||
return "number";
|
||||
}
|
||||
|
||||
// Identify strings
|
||||
if (stream.match("'")) {
|
||||
state.tokenize = inString("'", state.tokenize);
|
||||
return "string";
|
||||
} else if (stream.match('"')) {
|
||||
state.tokenize = inString('"', state.tokenize);
|
||||
return "string";
|
||||
}
|
||||
|
||||
// Attempt to find the variable
|
||||
if (stream.match(/\b(\w+)\b/) && !state.foundVariable) {
|
||||
state.waitDot = true;
|
||||
state.waitPipe = true; // A property can be followed by a filter
|
||||
return "variable";
|
||||
}
|
||||
|
||||
// If found closing tag reset
|
||||
if (stream.match("}}")) {
|
||||
state.waitProperty = null;
|
||||
state.waitFilter = null;
|
||||
state.waitDot = null;
|
||||
state.waitPipe = null;
|
||||
state.tokenize = tokenBase;
|
||||
return "tag";
|
||||
}
|
||||
|
||||
// If nothing was found, advance to the next character
|
||||
stream.next();
|
||||
return "null";
|
||||
}
|
||||
|
||||
function inTag (stream, state) {
|
||||
// Attempt to match a dot that precedes a property
|
||||
if (state.waitDot) {
|
||||
state.waitDot = false;
|
||||
|
||||
if (stream.peek() != ".") {
|
||||
return "null";
|
||||
}
|
||||
|
||||
// Dot followed by a non-word character should be considered an error.
|
||||
if (stream.match(/\.\W+/)) {
|
||||
return "error";
|
||||
} else if (stream.eat(".")) {
|
||||
state.waitProperty = true;
|
||||
return "null";
|
||||
} else {
|
||||
throw Error ("Unexpected error while waiting for property.");
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to match a pipe that precedes a filter
|
||||
if (state.waitPipe) {
|
||||
state.waitPipe = false;
|
||||
|
||||
if (stream.peek() != "|") {
|
||||
return "null";
|
||||
}
|
||||
|
||||
// Pipe followed by a non-word character should be considered an error.
|
||||
if (stream.match(/\.\W+/)) {
|
||||
return "error";
|
||||
} else if (stream.eat("|")) {
|
||||
state.waitFilter = true;
|
||||
return "null";
|
||||
} else {
|
||||
throw Error ("Unexpected error while waiting for filter.");
|
||||
}
|
||||
}
|
||||
|
||||
// Highlight properties
|
||||
if (state.waitProperty) {
|
||||
state.waitProperty = false;
|
||||
if (stream.match(/\b(\w+)\b/)) {
|
||||
state.waitDot = true; // A property can be followed by another property
|
||||
state.waitPipe = true; // A property can be followed by a filter
|
||||
return "property";
|
||||
}
|
||||
}
|
||||
|
||||
// Highlight filters
|
||||
if (state.waitFilter) {
|
||||
state.waitFilter = false;
|
||||
if (stream.match(filters)) {
|
||||
return "variable-2";
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore all white spaces
|
||||
if (stream.eatSpace()) {
|
||||
state.waitProperty = false;
|
||||
return "null";
|
||||
}
|
||||
|
||||
// Identify numbers
|
||||
if (stream.match(/\b\d+(\.\d+)?\b/)) {
|
||||
return "number";
|
||||
}
|
||||
|
||||
// Identify strings
|
||||
if (stream.match("'")) {
|
||||
state.tokenize = inString("'", state.tokenize);
|
||||
return "string";
|
||||
} else if (stream.match('"')) {
|
||||
state.tokenize = inString('"', state.tokenize);
|
||||
return "string";
|
||||
}
|
||||
|
||||
// Attempt to match an operator
|
||||
if (stream.match(operators)) {
|
||||
return "operator";
|
||||
}
|
||||
|
||||
// Attempt to match a word operator
|
||||
if (stream.match(wordOperators)) {
|
||||
return "keyword";
|
||||
}
|
||||
|
||||
// Attempt to match a keyword
|
||||
var keywordMatch = stream.match(keywords);
|
||||
if (keywordMatch) {
|
||||
if (keywordMatch[0] == "comment") {
|
||||
state.blockCommentTag = true;
|
||||
}
|
||||
return "keyword";
|
||||
}
|
||||
|
||||
// Attempt to match a variable
|
||||
if (stream.match(/\b(\w+)\b/)) {
|
||||
state.waitDot = true;
|
||||
state.waitPipe = true; // A property can be followed by a filter
|
||||
return "variable";
|
||||
}
|
||||
|
||||
// If found closing tag reset
|
||||
if (stream.match("%}")) {
|
||||
state.waitProperty = null;
|
||||
state.waitFilter = null;
|
||||
state.waitDot = null;
|
||||
state.waitPipe = null;
|
||||
// If the tag that closes is a block comment tag, we want to mark the
|
||||
// following code as comment, until the tag closes.
|
||||
if (state.blockCommentTag) {
|
||||
state.blockCommentTag = false; // Release the "lock"
|
||||
state.tokenize = inBlockComment;
|
||||
} else {
|
||||
state.tokenize = tokenBase;
|
||||
}
|
||||
return "tag";
|
||||
}
|
||||
|
||||
// If nothing was found, advance to the next character
|
||||
stream.next();
|
||||
return "null";
|
||||
}
|
||||
|
||||
// Mark everything as comment inside the tag and the tag itself.
|
||||
function inComment (stream, state) {
|
||||
if (stream.match(/^.*?#\}/)) state.tokenize = tokenBase
|
||||
else stream.skipToEnd()
|
||||
return "comment";
|
||||
}
|
||||
|
||||
// Mark everything as a comment until the `blockcomment` tag closes.
|
||||
function inBlockComment (stream, state) {
|
||||
if (stream.match(/\{%\s*endcomment\s*%\}/, false)) {
|
||||
state.tokenize = inTag;
|
||||
stream.match("{%");
|
||||
return "tag";
|
||||
} else {
|
||||
stream.next();
|
||||
return "comment";
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function () {
|
||||
return {tokenize: tokenBase};
|
||||
},
|
||||
token: function (stream, state) {
|
||||
return state.tokenize(stream, state);
|
||||
},
|
||||
blockCommentStart: "{% comment %}",
|
||||
blockCommentEnd: "{% endcomment %}"
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMode("django", function(config) {
|
||||
var htmlBase = CodeMirror.getMode(config, "text/html");
|
||||
var djangoInner = CodeMirror.getMode(config, "django:inner");
|
||||
return CodeMirror.overlayMode(htmlBase, djangoInner);
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-django", "django");
|
||||
});
|
73
public/vendor/plugins/codemirror/mode/django/index.html
vendored
Normal file
73
public/vendor/plugins/codemirror/mode/django/index.html
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Django template mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<link rel="stylesheet" href="../../theme/mdn-like.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/mode/overlay.js"></script>
|
||||
<script src="../xml/xml.js"></script>
|
||||
<script src="../htmlmixed/htmlmixed.js"></script>
|
||||
<script src="django.js"></script>
|
||||
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Django</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Django template mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>My Django web application</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
{{ page.title|capfirst }}
|
||||
</h1>
|
||||
<ul class="my-list">
|
||||
{# traverse a list of items and produce links to their views. #}
|
||||
{% for item in items %}
|
||||
<li>
|
||||
<a href="{% url 'item_view' item.name|slugify %}">
|
||||
{{ item.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>You have no items in your list.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% comment "this is a forgotten footer" %}
|
||||
<footer></footer>
|
||||
{% endcomment %}
|
||||
</body>
|
||||
</html>
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
mode: "django",
|
||||
indentUnit: 2,
|
||||
indentWithTabs: true,
|
||||
theme: "mdn-like"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Mode for HTML with embedded Django template markup.</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-django</code></p>
|
||||
</article>
|
Loading…
Add table
Add a link
Reference in a new issue