first commit
This commit is contained in:
94
codemirror/mode/gfm/gfm.js
vendored
Normal file
94
codemirror/mode/gfm/gfm.js
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
CodeMirror.defineMode("gfm", function(config) {
|
||||
var codeDepth = 0;
|
||||
function blankLine(state) {
|
||||
state.code = false;
|
||||
return null;
|
||||
}
|
||||
var gfmOverlay = {
|
||||
startState: function() {
|
||||
return {
|
||||
code: false,
|
||||
codeBlock: false,
|
||||
ateSpace: false
|
||||
};
|
||||
},
|
||||
copyState: function(s) {
|
||||
return {
|
||||
code: s.code,
|
||||
codeBlock: s.codeBlock,
|
||||
ateSpace: s.ateSpace
|
||||
};
|
||||
},
|
||||
token: function(stream, state) {
|
||||
// Hack to prevent formatting override inside code blocks (block and inline)
|
||||
if (state.codeBlock) {
|
||||
if (stream.match(/^```/)) {
|
||||
state.codeBlock = false;
|
||||
return null;
|
||||
}
|
||||
stream.skipToEnd();
|
||||
return null;
|
||||
}
|
||||
if (stream.sol()) {
|
||||
state.code = false;
|
||||
}
|
||||
if (stream.sol() && stream.match(/^```/)) {
|
||||
stream.skipToEnd();
|
||||
state.codeBlock = true;
|
||||
return null;
|
||||
}
|
||||
// If this block is changed, it may need to be updated in Markdown mode
|
||||
if (stream.peek() === '`') {
|
||||
stream.next();
|
||||
var before = stream.pos;
|
||||
stream.eatWhile('`');
|
||||
var difference = 1 + stream.pos - before;
|
||||
if (!state.code) {
|
||||
codeDepth = difference;
|
||||
state.code = true;
|
||||
} else {
|
||||
if (difference === codeDepth) { // Must be exact
|
||||
state.code = false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} else if (state.code) {
|
||||
stream.next();
|
||||
return null;
|
||||
}
|
||||
// Check if space. If so, links can be formatted later on
|
||||
if (stream.eatSpace()) {
|
||||
state.ateSpace = true;
|
||||
return null;
|
||||
}
|
||||
if (stream.sol() || state.ateSpace) {
|
||||
state.ateSpace = false;
|
||||
if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
|
||||
// User/Project@SHA
|
||||
// User@SHA
|
||||
// SHA
|
||||
return "link";
|
||||
} else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
|
||||
// User/Project#Num
|
||||
// User#Num
|
||||
// #Num
|
||||
return "link";
|
||||
}
|
||||
}
|
||||
if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i)) {
|
||||
// URLs
|
||||
// Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
|
||||
return "link";
|
||||
}
|
||||
stream.next();
|
||||
return null;
|
||||
},
|
||||
blankLine: blankLine
|
||||
};
|
||||
CodeMirror.defineMIME("gfmBase", {
|
||||
name: "markdown",
|
||||
underscoresBreakWords: false,
|
||||
fencedCodeBlocks: true
|
||||
});
|
||||
return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);
|
||||
}, "markdown");
|
||||
70
codemirror/mode/gfm/index.html
vendored
Normal file
70
codemirror/mode/gfm/index.html
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CodeMirror: GFM mode</title>
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../lib/util/overlay.js"></script>
|
||||
<script src="../xml/xml.js"></script>
|
||||
<script src="../markdown/markdown.js"></script>
|
||||
<script src="gfm.js"></script>
|
||||
|
||||
<!-- Code block highlighting modes -->
|
||||
<script src="../javascript/javascript.js"></script>
|
||||
<script src="../css/css.js"></script>
|
||||
<script src="../htmlmixed/htmlmixed.js"></script>
|
||||
<script src="../clike/clike.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="../markdown/markdown.css">
|
||||
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
||||
<link rel="stylesheet" href="../../doc/docs.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>CodeMirror: GFM mode</h1>
|
||||
|
||||
<form><textarea id="code" name="code">
|
||||
GitHub Flavored Markdown
|
||||
========================
|
||||
|
||||
Everything from markdown plus GFM features:
|
||||
|
||||
## URL autolinking
|
||||
|
||||
Underscores_are_allowed_between_words.
|
||||
|
||||
## Fenced code blocks (and syntax highlighting)
|
||||
|
||||
```javascript
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
console.log(items[i], i); // log them
|
||||
}
|
||||
```
|
||||
|
||||
## A bit of GitHub spice
|
||||
|
||||
* SHA: be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
|
||||
* User@SHA ref: mojombo@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
|
||||
* User/Project@SHA: mojombo/god@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
|
||||
* \#Num: #1
|
||||
* User/#Num: mojombo#1
|
||||
* User/Project#Num: mojombo/god#1
|
||||
|
||||
See http://github.github.com/github-flavored-markdown/.
|
||||
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: 'gfm',
|
||||
lineNumbers: true,
|
||||
theme: "default"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Optionally depends on other modes for properly highlighted code blocks.</p>
|
||||
|
||||
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#gfm_*">normal</a>, <a href="../../test/index.html#verbose,gfm_*">verbose</a>.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
225
codemirror/mode/gfm/test.js
vendored
Normal file
225
codemirror/mode/gfm/test.js
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
// Initiate ModeTest and set defaults
|
||||
var MT = ModeTest;
|
||||
MT.modeName = 'gfm';
|
||||
MT.modeOptions = {};
|
||||
|
||||
// Emphasis characters within a word
|
||||
MT.testMode(
|
||||
'emInWordAsterisk',
|
||||
'foo*bar*hello',
|
||||
[
|
||||
null, 'foo',
|
||||
'em', '*bar*',
|
||||
null, 'hello'
|
||||
]
|
||||
);
|
||||
MT.testMode(
|
||||
'emInWordUnderscore',
|
||||
'foo_bar_hello',
|
||||
[
|
||||
null, 'foo_bar_hello'
|
||||
]
|
||||
);
|
||||
MT.testMode(
|
||||
'emStrongUnderscore',
|
||||
'___foo___ bar',
|
||||
[
|
||||
'strong', '__',
|
||||
'emstrong', '_foo__',
|
||||
'em', '_',
|
||||
null, ' bar'
|
||||
]
|
||||
);
|
||||
|
||||
// Fenced code blocks
|
||||
MT.testMode(
|
||||
'fencedCodeBlocks',
|
||||
'```\nfoo\n\n```\nbar',
|
||||
[
|
||||
'comment', '```',
|
||||
'comment', 'foo',
|
||||
'comment', '```',
|
||||
null, 'bar'
|
||||
]
|
||||
);
|
||||
// Fenced code block mode switching
|
||||
MT.testMode(
|
||||
'fencedCodeBlockModeSwitching',
|
||||
'```javascript\nfoo\n\n```\nbar',
|
||||
[
|
||||
'comment', '```javascript',
|
||||
'variable', 'foo',
|
||||
'comment', '```',
|
||||
null, 'bar'
|
||||
]
|
||||
);
|
||||
|
||||
// SHA
|
||||
MT.testMode(
|
||||
'SHA',
|
||||
'foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2 bar',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', 'be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2',
|
||||
null, ' bar'
|
||||
]
|
||||
);
|
||||
// GitHub highlights hashes 7-40 chars in length
|
||||
MT.testMode(
|
||||
'shortSHA',
|
||||
'foo be6a8cc bar',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', 'be6a8cc',
|
||||
null, ' bar'
|
||||
]
|
||||
);
|
||||
// Invalid SHAs
|
||||
//
|
||||
// GitHub does not highlight hashes shorter than 7 chars
|
||||
MT.testMode(
|
||||
'tooShortSHA',
|
||||
'foo be6a8c bar',
|
||||
[
|
||||
null, 'foo be6a8c bar'
|
||||
]
|
||||
);
|
||||
// GitHub does not highlight hashes longer than 40 chars
|
||||
MT.testMode(
|
||||
'longSHA',
|
||||
'foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd22 bar',
|
||||
[
|
||||
null, 'foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd22 bar'
|
||||
]
|
||||
);
|
||||
MT.testMode(
|
||||
'badSHA',
|
||||
'foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cg2 bar',
|
||||
[
|
||||
null, 'foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cg2 bar'
|
||||
]
|
||||
);
|
||||
// User@SHA
|
||||
MT.testMode(
|
||||
'userSHA',
|
||||
'foo bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2 hello',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', 'bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2',
|
||||
null, ' hello'
|
||||
]
|
||||
);
|
||||
// User/Project@SHA
|
||||
MT.testMode(
|
||||
'userProjectSHA',
|
||||
'foo bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2 world',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', 'bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2',
|
||||
null, ' world'
|
||||
]
|
||||
);
|
||||
|
||||
// #Num
|
||||
MT.testMode(
|
||||
'num',
|
||||
'foo #1 bar',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', '#1',
|
||||
null, ' bar'
|
||||
]
|
||||
);
|
||||
// bad #Num
|
||||
MT.testMode(
|
||||
'badNum',
|
||||
'foo #1bar hello',
|
||||
[
|
||||
null, 'foo #1bar hello'
|
||||
]
|
||||
);
|
||||
// User#Num
|
||||
MT.testMode(
|
||||
'userNum',
|
||||
'foo bar#1 hello',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', 'bar#1',
|
||||
null, ' hello'
|
||||
]
|
||||
);
|
||||
// User/Project#Num
|
||||
MT.testMode(
|
||||
'userProjectNum',
|
||||
'foo bar/hello#1 world',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', 'bar/hello#1',
|
||||
null, ' world'
|
||||
]
|
||||
);
|
||||
|
||||
// Vanilla links
|
||||
MT.testMode(
|
||||
'vanillaLink',
|
||||
'foo http://www.example.com/ bar',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', 'http://www.example.com/',
|
||||
null, ' bar'
|
||||
]
|
||||
);
|
||||
MT.testMode(
|
||||
'vanillaLinkPunctuation',
|
||||
'foo http://www.example.com/. bar',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', 'http://www.example.com/',
|
||||
null, '. bar'
|
||||
]
|
||||
);
|
||||
MT.testMode(
|
||||
'vanillaLinkExtension',
|
||||
'foo http://www.example.com/index.html bar',
|
||||
[
|
||||
null, 'foo ',
|
||||
'link', 'http://www.example.com/index.html',
|
||||
null, ' bar'
|
||||
]
|
||||
);
|
||||
// Not a link
|
||||
MT.testMode(
|
||||
'notALink',
|
||||
'```css\nfoo {color:black;}\n```http://www.example.com/',
|
||||
[
|
||||
'comment', '```css',
|
||||
'tag', 'foo',
|
||||
null, ' {',
|
||||
'property', 'color',
|
||||
'operator', ':',
|
||||
'keyword', 'black',
|
||||
null, ';}',
|
||||
'comment', '```',
|
||||
'link', 'http://www.example.com/'
|
||||
]
|
||||
);
|
||||
// Not a link
|
||||
MT.testMode(
|
||||
'notALink',
|
||||
'``foo `bar` http://www.example.com/`` hello',
|
||||
[
|
||||
'comment', '``foo `bar` http://www.example.com/``',
|
||||
null, ' hello'
|
||||
]
|
||||
);
|
||||
// Not a link
|
||||
MT.testMode(
|
||||
'notALink',
|
||||
'`foo\nhttp://www.example.com/\n`foo\n\nhttp://www.example.com/',
|
||||
[
|
||||
'comment', '`foo',
|
||||
'link', 'http://www.example.com/',
|
||||
'comment', '`foo',
|
||||
'link', 'http://www.example.com/'
|
||||
]
|
||||
);
|
||||
Reference in New Issue
Block a user