Major code refactoring

This commit is contained in:
Estevão Soares dos Santos 2015-01-15 21:21:33 +00:00
parent 548becfd58
commit eae5f0e01f
137 changed files with 2116 additions and 9354 deletions

7
.gitattributes vendored
View File

@ -1,7 +1,6 @@
/test export-ignore
.gitattributes export-ignore
.gitignore export-ignore
/perlMarkdown export-ignore
/example export-ignore
grunt.js export-ignore
.jshintignore export-ignore
.travis.yml export-ignore
Gruntfile.js export-ignore

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
.idea/
build/
.DS_Store
node_modules
npm-debug.log
.idea/

View File

@ -1,2 +1,3 @@
Gruntfile.js
dist/**/*.js
dist/**/*.js
build/**/*.js

27
.jshintrc Normal file
View File

@ -0,0 +1,27 @@
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": "nofunc",
"newcap": true,
"noarg": true,
"quotmark": "single",
"undef": false,
"unused": true,
"strict": false,
"trailing": true,
"smarttabs": true,
"globals": {
"angular": true,
"module": true,
"define": true,
"window": true,
"showdown": true
}
}

39
CREDITS.md Normal file
View File

@ -0,0 +1,39 @@
Credits
=======
- Showdown v2
* [Estevão Santos](http://soares-dos-santos.com)<br/>
Code Refactoring and project maintainer
- Showdown v1
* [Corey Innis](http://github.com/coreyti):<br/>
GitHub project maintainer
* [Remy Sharp](https://github.com/remy/):<br/>
CommonJS-compatibility and more
* [Konstantin Käfer](https://github.com/kkaefer/):<br/>
CommonJS packaging
* [Roger Braun](https://github.com/rogerbraun):<br/>
Github-style code blocks
* [Dominic Tarr](https://github.com/dominictarr):<br/>
Documentation
* [Cat Chen](https://github.com/CatChen):<br/>
Export fix
* [Titus Stone](https://github.com/tstone):<br/>
Mocha tests, extension mechanism, and bug fixes
* [Rob Sutherland](https://github.com/roberocity):<br/>
The idea that lead to extensions
* [Pavel Lang](https://github.com/langpavel):<br/>
Code cleanup
* [Ben Combee](https://github.com/unwiredben):<br/>
Regex optimization
* [Adam Backstrom](https://github.com/abackstrom):<br/>
WebKit bugfix
* [Pascal Deschênes](https://github.com/pdeschen):<br/>
Grunt support, extension fixes + additions, packaging improvements, documentation
* [Estevão Santos](http://soares-dos-santos.com)<br/>
Bug fixing and later maintainer
- Original Project
* [John Gruber](http://daringfireball.net/projects/markdown/)<br/>
Author of Markdown
* [John Fraser](http://attacklab.net/)
Author of Showdown

View File

@ -9,28 +9,13 @@ module.exports = function (grunt) {
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: ';',
sourceMap: true
sourceMap: true,
banner: ";/*! <%= pkg.name %> <%= grunt.template.today('dd-mm-yyyy') %> */\n(function(){\n 'use strict';\n",
footer: "}).call(this)"
},
dist: {
src: ['src/showdown.js', 'src/*.js'],
dest: 'compressed/<%= pkg.name %>.js'
},
github_ext: {
src: ['src/extensions/github.js'],
dest: 'compressed/extensions/github.min.js'
},
prettify_ext: {
src: ['src/extensions/prettify.js'],
dest: 'compressed/extensions/prettify.min.js'
},
table_ext: {
src: ['src/extensions/table.js'],
dest: 'compressed/extensions/table.min.js'
},
twitter_ext: {
src: ['src/extensions/twitter.js'],
dest: 'compressed/extensions/twitter.min.js'
src: ['src/showdown.js', 'src/helpers.js', 'src/subParsers/*.js', 'src/loader.js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
uglify: {
@ -39,41 +24,21 @@ module.exports = function (grunt) {
},
dist: {
files: {
'compressed/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
},
github_ext: {
files: {
'compressed/extensions/github.min.js': ['<%= concat.github_ext.dest %>']
}
},
prettify_ext: {
files: {
'compressed/extensions/prettify.min.js': ['<%= concat.prettify_ext.dest %>']
}
},
table_ext: {
files: {
'compressed/extensions/table.min.js': ['<%= concat.table_ext.dest %>']
}
},
twitter_ext: {
files: {
'compressed/extensions/twitter.min.js': ['<%= concat.twitter_ext.dest %>']
'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
}
},
jshint: {
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js']
files: ['Gruntfile.js', 'src/**/*.js']
},
simplemocha: {
all: {
src: 'test/run.js',
src: 'test/**/*.js',
options: {
globals: ['should'],
timeout: 3000,
ignoreLeaks: false,
ui: 'bdd'
reporter: 'spec'
}
}
}
@ -85,16 +50,23 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-simple-mocha');
// test
/*
grunt.registerTask('sourceMapsSupport', function() {
'use strict';
//# sourceMappingURL=path/to/source.map
sourceMapSupport.install();
});
*/
grunt.registerTask('lint', ['jshint']);
grunt.registerTask('test', ['simplemocha']);
grunt.registerTask('test', ['jshint', 'concat', 'simplemocha']);
grunt.registerTask('test-without-building', ['simplemocha']);
// build with uglify
grunt.registerTask('build', ['concat', 'uglify']);
// Build with closure compiler
grunt.registerTask('build-with-closure', ['test', 'concat', 'closure-compiler']);
// Default task(s).
grunt.registerTask('default', []);
};

638
README.md
View File

@ -1,315 +1,323 @@
# Showdown
A JavaScript port of Markdown
## Note
> Showdown is now maintained by the [showdownjs](https://github.com/showdownjs) organization on Github.
>
> The organization needs members to maintain Showdown.
>
> Please see [this issue](https://github.com/showdownjs/showdown/issues/114) to express interest or comment on this note.
## Original Attributions
Showdown Copyright (c) 2007 John Fraser.
<http://www.attacklab.net/>
Original Markdown Copyright (c) 2004-2005 John Gruber
<http://daringfireball.net/projects/markdown/>
Redistributable under a BSD-style open source license.
See license.txt for more information.
## Quick Example
```js
var Showdown = require('showdown');
var converter = new Showdown.converter();
converter.makeHtml('#hello markdown!');
// <h1 id="hellomarkdown">hello, markdown</h1>
```
## What's it for?
Developers can use Showdown to:
* Add in-browser preview to existing Markdown apps
Showdown's output is (almost always) identical to
markdown.pl's, so the server can reproduce exactly
the output that the user saw. (See below for
exceptions.)
* Add Markdown input to programs that don't support it
Any app that accepts HTML input can now be made to speak
Markdown by modifying the input pages's HTML. If your
application lets users edit documents again later,
then they won't have access to the original Markdown
text. But this should be good enough for many
uses -- and you can do it with just a two-line
`onsubmit` function!
* Add Markdown input to closed-source web apps
You can write bookmarklets or userscripts to extend
any standard textarea on the web so that it accepts
Markdown instead of HTML. With a little more hacking,
the same can probably be done with many rich edit
controls.
* Build new web apps from scratch
A Showdown front-end can send back text in Markdown,
HTML or both, so you can trade bandwidth for server
load to reduce your cost of operation. If your app
requires JavaScript, you won't need to do any
Markdown processing on the server at all. (For most
uses, you'll still need to sanitize the HTML before
showing it to other users -- but you'd need to do
that anyway if you're allowing raw HTML in your
Markdown.)
## Browser Compatibility
Showdown has been tested successfully with:
* Firefox 1.5 and 2.0
* Internet Explorer 6 and 7
* Safari 2.0.4
* Opera 8.54 and 9.10
* Netscape 8.1.2
* Konqueror 3.5.4
In theory, Showdown will work in any browser that supports ECMA 262 3rd Edition (JavaScript 1.5). The converter itself might even work in things that aren't web browsers, like Acrobat. No promises.
## Extensions
Showdown allows additional functionality to be loaded via extensions.
### Client-side Extension Usage
```js
<script src="src/showdown.js" />
<script src="src/extensions/twitter.js" />
var converter = new Showdown.converter({ extensions: 'twitter' });
```
### Server-side Extension Usage
```js
// Using a bundled extension
var Showdown = require('showdown');
var converter = new Showdown.converter({ extensions: ['twitter'] });
// Using a custom extension
var mine = require('./custom-extensions/mine');
var converter = new Showdown.converter({ extensions: ['twitter', mine] });
```
## Known Differences in Output
In most cases, Showdown's output is identical to that of Perl Markdown v1.0.2b7. What follows is a list of all known deviations. Please file an issue if you find more.
* This release uses the HTML parser from Markdown 1.0.2b2,
which means it fails `Inline HTML (Advanced).text` from
the Markdown test suite:
<div>
<div>
unindented == broken
</div>
</div>
* Showdown doesn't support the markdown="1" attribute:
<div markdown="1">
Markdown does *not* work in here.
</div>
This is half laziness on my part and half stubbornness.
Markdown is smart enough to process the contents of span-
level tags without screwing things up; shouldn't it be
able to do the same inside block elements? Let's find a
way to make markdown="1" the default.
* You can only nest square brackets in link titles to a
depth of two levels:
[[fine]](http://www.attacklab.net/)
[[[broken]]](http://www.attacklab.net/)
If you need more, you can escape them with backslashes.
* When sublists have paragraphs, Showdown produces equivalent
HTML with a slightly different arrangement of newlines:
+ item
- subitem
The HTML has a superfluous newline before this
paragraph.
- subitem
The HTML here is unchanged.
- subitem
The HTML is missing a newline after this
list subitem.
* Markdown.pl creates empty title attributes for
inline-style images:
Here's an empty title on an inline-style
![image](http://w3.org/Icons/valid-xhtml10).
I tried to replicate this to clean up my diffs during
testing, but I went too far: now Showdown also makes
empty titles for reference-style images:
Showdown makes an empty title for
reference-style ![images][] too.
[images]: http://w3.org/Icons/valid-xhtml10
* With crazy input, Markdown will mistakenly put
`<strong>` or `<em>` tags in URLs:
<a href="<*Markdown adds em tags in here*>">
improbable URL
</a>
Showdown won't. But still, don't do that.
## Tests
A suite of tests is available which require node.js. Once node is installed, run the following command from the project root to install the development dependencies:
npm install --dev
Once installed the tests can be run from the project root using:
npm test
New test cases can easily be added. Create a markdown file (ending in `.md`) which contains the markdown to test. Create a `.html` file of the exact same name. It will automatically be tested when the tests are executed with `mocha`.
## Creating Markdown Extensions
A showdown extension is simply a function which returns an array of extensions. Each single extension can be one of two types:
* Language Extension -- Language extensions are ones that that add new markdown syntax to showdown. For example, say you wanted `^^youtube http://www.youtube.com/watch?v=oHg5SJYRHA0` to automatically render as an embedded YouTube video, that would be a language extension.
* Output Modifiers -- After showdown has run, and generated HTML, an output modifier would change that HTML. For example, say you wanted to change `<div class="header">` to be `<header>`, that would be an output modifier.
Each extension can provide two combinations of interfaces for showdown.
### Regex/Replace
Regex/replace style extensions are very similar to javascripts `string.replace` function. Two properties are given, `regex` and `replace`. `regex` is a string and `replace` can be either a string or a function. If `replace` is a string, it can use the `$1` syntax for group substitution, exactly as if it were making use of `string.replace` (internally it does this actually); The value of `regex` is assumed to be a global replacement.
**Example:**
```js
var demo = function(converter) {
return [
// Replace escaped @ symbols
{ type: 'lang', regex: '\\@', replace: '@' }
];
}
```
### Filter
Alternately, if you'd just like to do everything yourself, you can specify a filter which is a callback with a single input parameter, text (the current source text within the showdown engine).
**Example:**
```js
var demo = function(converter) {
return [
// Replace escaped @ symbols
{ type: 'lang', filter: function(text) {
return text.replace(/\\@/g, '@');
}}
];
}
```
### Implementation Concerns
One bit which should be taken into account is maintaining both client-side and server-side compatibility. This can be achieved with a few lines of boilerplate code. First, to prevent polluting the global scope for client-side code, the extension definition should be wrapped in a self-executing function.
```js
(function(){
// Your extension here
}());
```
Second, client-side extensions should add a property onto `Showdown.extensions` which matches the name of the file. As an example, a file named `demo.js` should then add `Showdown.extensions.demo`. Server-side extensions can simply export themselves.
```js
(function(){
var demo = function(converter) {
// ... extension code here ...
};
// Client-side export
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.demo = demo; }
// Server-side export
if (typeof module !== 'undefined') module.exports = demo;
}());
```
### Testing Extensions
The showdown test runner is setup to automatically test cases for extensions. To add test cases for an extension, create a new folder under `./test/extensions` which matches the name of the `.js` file in `./src/extensions`. Place any test cases into the filder using the md/html format and they will automatically be run when tests are run.
## Credits
* Origins
* [John Fraser](http://attacklab.net/):<br/>
Author of Showdown
* [John Gruber](http://daringfireball.net/projects/markdown/):<br/>
Author of Markdown
* Maintenance/Contributions (roughly chronologically)
* [Corey Innis](http://github.com/coreyti):<br/>
GitHub project maintainer
* [Remy Sharp](https://github.com/remy/):<br/>
CommonJS-compatibility and more
* [Konstantin Käfer](https://github.com/kkaefer/):<br/>
CommonJS packaging
* [Roger Braun](https://github.com/rogerbraun):<br/>
Github-style code blocks
* [Dominic Tarr](https://github.com/dominictarr):<br/>
Documentation
* [Cat Chen](https://github.com/CatChen):<br/>
Export fix
* [Titus Stone](https://github.com/tstone):<br/>
Mocha tests, extension mechanism, and bug fixes
* [Rob Sutherland](https://github.com/roberocity):<br/>
The idea that lead to extensions
* [Pavel Lang](https://github.com/langpavel):<br/>
Code cleanup
* [Ben Combee](https://github.com/unwiredben):<br/>
Regex optimization
* [Adam Backstrom](https://github.com/abackstrom):<br/>
WebKit bugfix
* [Pascal Deschênes](https://github.com/pdeschen):<br/>
Grunt support, extension fixes + additions, packaging improvements, documentation
Showdown
--------
A Markdown to HTML converter written in Javascript
## Note
> Showdown is now maintained by the [showdownjs](https://github.com/showdownjs) organization on Github.
>
> The organization needs members to maintain Showdown.
>
> Please see [this issue](https://github.com/showdownjs/showdown/issues/114) to express interest or comment on this note.
## Original Attributions
Showdown Copyright (c) 2007 John Fraser.
<http://www.attacklab.net/>
Original Markdown Copyright (c) 2004-2005 John Gruber
<http://daringfireball.net/projects/markdown/>
Redistributable under a BSD-style open source license.
See license.txt for more information.
## Quick Example
```js
var Showdown = require('showdown');
var converter = new Showdown.converter();
converter.makeHtml('#hello markdown!');
// <h1 id="hellomarkdown">hello, markdown</h1>
```
## What's it for?
Developers can use Showdown to:
* Add in-browser preview to existing Markdown apps
Showdown's output is (almost always) identical to
markdown.pl's, so the server can reproduce exactly
the output that the user saw. (See below for
exceptions.)
* Add Markdown input to programs that don't support it
Any app that accepts HTML input can now be made to speak
Markdown by modifying the input pages's HTML. If your
application lets users edit documents again later,
then they won't have access to the original Markdown
text. But this should be good enough for many
uses -- and you can do it with just a two-line
`onsubmit` function!
* Add Markdown input to closed-source web apps
You can write bookmarklets or userscripts to extend
any standard textarea on the web so that it accepts
Markdown instead of HTML. With a little more hacking,
the same can probably be done with many rich edit
controls.
* Build new web apps from scratch
A Showdown front-end can send back text in Markdown,
HTML or both, so you can trade bandwidth for server
load to reduce your cost of operation. If your app
requires JavaScript, you won't need to do any
Markdown processing on the server at all. (For most
uses, you'll still need to sanitize the HTML before
showing it to other users -- but you'd need to do
that anyway if you're allowing raw HTML in your
Markdown.)
## Browser Compatibility
Showdown has been tested successfully with:
* Firefox 1.5 and 2.0
* Internet Explorer 6 and 7
* Safari 2.0.4
* Opera 8.54 and 9.10
* Netscape 8.1.2
* Konqueror 3.5.4
In theory, Showdown will work in any browser that supports ECMA 262 3rd Edition (JavaScript 1.5). The converter itself might even work in things that aren't web browsers, like Acrobat. No promises.
## Extensions
Showdown allows additional functionality to be loaded via extensions.
### Client-side Extension Usage
```js
<script src="src/showdown.js" />
<script src="src/extensions/twitter.js" />
var converter = new Showdown.converter({ extensions: 'twitter' });
```
### Server-side Extension Usage
```js
// Using a bundled extension
var Showdown = require('showdown');
var converter = new Showdown.converter({ extensions: ['twitter'] });
// Using a custom extension
var mine = require('./custom-extensions/mine');
var converter = new Showdown.converter({ extensions: ['twitter', mine] });
```
## Known Differences in Output
In most cases, Showdown's output is identical to that of Perl Markdown v1.0.2b7. What follows is a list of all known deviations. Please file an issue if you find more.
* This release uses the HTML parser from Markdown 1.0.2b2,
which means it fails `Inline HTML (Advanced).text` from
the Markdown test suite:
<div>
<div>
unindented == broken
</div>
</div>
* Showdown doesn't support the markdown="1" attribute:
<div markdown="1">
Markdown does *not* work in here.
</div>
This is half laziness on my part and half stubbornness.
Markdown is smart enough to process the contents of span-
level tags without screwing things up; shouldn't it be
able to do the same inside block elements? Let's find a
way to make markdown="1" the default.
* You can only nest square brackets in link titles to a
depth of two levels:
[[fine]](http://www.attacklab.net/)
[[[broken]]](http://www.attacklab.net/)
If you need more, you can escape them with backslashes.
* When sublists have paragraphs, Showdown produces equivalent
HTML with a slightly different arrangement of newlines:
+ item
- subitem
The HTML has a superfluous newline before this
paragraph.
- subitem
The HTML here is unchanged.
- subitem
The HTML is missing a newline after this
list subitem.
* Markdown.pl creates empty title attributes for
inline-style images:
Here's an empty title on an inline-style
![image](http://w3.org/Icons/valid-xhtml10).
I tried to replicate this to clean up my diffs during
testing, but I went too far: now Showdown also makes
empty titles for reference-style images:
Showdown makes an empty title for
reference-style ![images][] too.
[images]: http://w3.org/Icons/valid-xhtml10
* With crazy input, Markdown will mistakenly put
`<strong>` or `<em>` tags in URLs:
<a href="<*Markdown adds em tags in here*>">
improbable URL
</a>
Showdown won't. But still, don't do that.
## Tests
A suite of tests is available which require node.js. Once node is installed, run the following command from the project root to install the development dependencies:
npm install --dev
Once installed the tests can be run from the project root using:
npm test
New test cases can easily be added. Create a markdown file (ending in `.md`) which contains the markdown to test. Create a `.html` file of the exact same name. It will automatically be tested when the tests are executed with `mocha`.
## Creating Markdown Extensions
A showdown extension is simply a function which returns an array of extensions. Each single extension can be one of two types:
* Language Extension -- Language extensions are ones that that add new markdown syntax to showdown. For example, say you wanted `^^youtube http://www.youtube.com/watch?v=oHg5SJYRHA0` to automatically render as an embedded YouTube video, that would be a language extension.
* Output Modifiers -- After showdown has run, and generated HTML, an output modifier would change that HTML. For example, say you wanted to change `<div class="header">` to be `<header>`, that would be an output modifier.
Each extension can provide two combinations of interfaces for showdown.
### Regex/Replace
Regex/replace style extensions are very similar to Javascript's `string.replace` function. Two properties are given, `regex` and `replace`. `regex` is a string and `replace` can be either a string or a function. If `replace` is a string, it can use the `$1` syntax for group substitution, exactly as if it were making use of `string.replace` (internally it does this actually); The value of `regex` is assumed to be a global replacement.
**Example:**
```js
var demo = function(converter) {
return [
// Replace escaped @ symbols
{ type: 'lang', regex: '\\@', replace: '@' }
];
}
```
### Filter
Alternately, if you'd just like to do everything yourself, you can specify a filter which is a callback with a single input parameter, text (the current source text within the showdown engine).
**Example:**
```js
var demo = function(converter) {
return [
// Replace escaped @ symbols
{ type: 'lang', filter: function(text) {
return text.replace(/\\@/g, '@');
}}
];
}
```
### Implementation Concerns
One bit which should be taken into account is maintaining both client-side and server-side compatibility. This can be achieved with a few lines of boilerplate code. First, to prevent polluting the global scope for client-side code, the extension definition should be wrapped in a self-executing function.
```js
(function(){
// Your extension here
}());
```
Second, client-side extensions should add a property onto `Showdown.extensions` which matches the name of the file. As an example, a file named `demo.js` should then add `Showdown.extensions.demo`. Server-side extensions can simply export themselves.
```js
(function(){
var demo = function(converter) {
// ... extension code here ...
};
// Client-side export
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.demo = demo; }
// Server-side export
if (typeof module !== 'undefined') module.exports = demo;
}());
```
### Testing Extensions
The showdown test runner is setup to automatically test cases for extensions. To add test cases for an extension, create a new folder under `./test/extensions` which matches the name of the `.js` file in `./src/extensions`. Place any test cases into the folder using the md/html format and they will automatically be run when tests are run.
## Credits
- Showdown v2
* [Estevão Santos](http://soares-dos-santos.com)<br/>
Code Refactoring and Project Maintainer
- Showdown v1
* [Corey Innis](http://github.com/coreyti):<br/>
GitHub project maintainer
* [Remy Sharp](https://github.com/remy/):<br/>
CommonJS-compatibility and more
* [Konstantin Käfer](https://github.com/kkaefer/):<br/>
CommonJS packaging
* [Roger Braun](https://github.com/rogerbraun):<br/>
Github-style code blocks
* [Dominic Tarr](https://github.com/dominictarr):<br/>
Documentation
* [Cat Chen](https://github.com/CatChen):<br/>
Export fix
* [Titus Stone](https://github.com/tstone):<br/>
Mocha tests, extension mechanism, and bug fixes
* [Rob Sutherland](https://github.com/roberocity):<br/>
The idea that lead to extensions
* [Pavel Lang](https://github.com/langpavel):<br/>
Code cleanup
* [Ben Combee](https://github.com/unwiredben):<br/>
Regex optimization
* [Adam Backstrom](https://github.com/abackstrom):<br/>
WebKit bugfix
* [Pascal Deschênes](https://github.com/pdeschen):<br/>
Grunt support, extension fixes + additions, packaging improvements, documentation
* [Estevão Santos](http://soares-dos-santos.com):<br/>
Bug fixes and later maintainer
- Original Project
* [John Gruber](http://daringfireball.net/projects/markdown/)<br/>
Author of Markdown
* [John Fraser](http://attacklab.net/)<br/>
Author of Showdown

View File

@ -1,12 +1,12 @@
{
"name": "showdown",
"description": "JavaScript port of Markdown",
"description": "A Markdown to HTML converter written in Javascript",
"homepage": "https://github.com/showdownjs/showdown",
"authors": [
"John Fraser",
"Corey Innis (https://github.com/coreyti)",
"Estevão Santos (https://github.com/tivie)",
"Pascal Deschênes (https://github.com/pdeschen)",
"Estevão Santos (https://github.com/tivie)"
"Corey Innis (https://github.com/coreyti)",
"John Fraser"
],
"main": ["src/showdown.js"],
"ignore": [

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +0,0 @@
/*! showdown 06-01-2015 */
!function(){var a=function(){return[{type:"lang",regex:"(~T){2}([^~]+)(~T){2}",replace:function(a,b,c){return"<del>"+c+"</del>"}}]};"undefined"!=typeof window&&window.Showdown&&window.Showdown.extensions&&(window.Showdown.extensions.github=a),"undefined"!=typeof module&&(module.exports=a)}();

View File

@ -1 +0,0 @@
{"version":3,"sources":["..\\..\\src\\extensions\\github.js"],"names":[],"mappings":"AAAA;AAAA,IACI,MAAM,CAAC,SAAS,EAAE,GAAG;AAAA,MACnB,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG;AAAA;AAAA;AAAA,CAGpD,QAAQ;AAAA,IACL,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC,SAAS;AAAA,QAC3B,MAAM;AAAA;AAAA,iBAEG,MAAM,CAAC,OAAO;AAAA,iBACd,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AAAA,cAClF,IAAI,OAAO,IAAI;AAAA,cACf,KAAK,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;AAAA,cAC/B,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;AAAA,kBAC7C,MAAM,GAAG,GAAG,KAAK,OAAO,MAAM,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAM5C,MAAM,CAAC,IAAI,CAAC,MAAM;AAAA,IACrB,EAAE,EAAE,MAAM,CAAC,MAAM,MAAM,SAAS,KAAK,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,GAAG,MAAM;AAAA,OAC7H,MAAM,CAAC,IAAI,CAAC,MAAM;AAAA,IACrB,EAAE,EAAE,MAAM,CAAC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM;AAAA","file":"github.min.js","sourcesContent":["//\r\n// Github Extension (WIP)\r\n// ~~strike-through~~ -> <del>strike-through</del>\r\n//\r\n\r\n(function(){\r\n var github = function(converter) {\r\n return [\r\n {\r\n // strike-through\r\n // NOTE: showdown already replaced \"~\" with \"~T\", so we need to adjust accordingly.\r\n type : 'lang',\r\n regex : '(~T){2}([^~]+)(~T){2}',\r\n replace : function(match, prefix, content, suffix) {\r\n return '<del>' + content + '</del>';\r\n }\r\n }\r\n ];\r\n };\r\n\r\n // Client-side export\r\n if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.github = github; }\r\n // Server-side export\r\n if (typeof module !== 'undefined') module.exports = github;\r\n}());\r\n"]}

View File

@ -1,2 +0,0 @@
/*! showdown 06-01-2015 */
!function(){var a=function(){return[{type:"output",filter:function(a){return a.replace(/(<pre>)?<code>/gi,function(a,b){return b?'<pre class="prettyprint linenums" tabIndex="0"><code data-inner="1">':'<code class="prettyprint">'})}}]};"undefined"!=typeof window&&window.Showdown&&window.Showdown.extensions&&(window.Showdown.extensions.prettify=a),"undefined"!=typeof module&&(module.exports=a)}();

View File

@ -1 +0,0 @@
{"version":3,"sources":["..\\..\\src\\extensions\\prettify.js"],"names":[],"mappings":"AAAA;AAAA,IACI,MAAM,CAAC,QAAQ;AAAA,IACf,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ;AAAA,IAC1F,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;AAAA;AAAA;AAAA,CAGlC,QAAQ;AAAA;AAAA,IAEL,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC,SAAS;AAAA,QAC7B,MAAM;AAAA,cACA,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,MAAM;AAAA;AAAA,gBAErC,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,GAAG,IAAI,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,KAAK,EAAE,GAAG;AAAA,oBACzD,EAAE,EAAE,GAAG;AAAA,wBACH,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;AAAA,sBAC5E,IAAI;AAAA,wBACF,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAOjD,MAAM,CAAC,IAAI,CAAC,MAAM;AAAA,IACrB,EAAE,EAAE,MAAM,CAAC,MAAM,MAAM,SAAS,KAAK,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,GAAG,QAAQ;AAAA,OACjI,MAAM,CAAC,IAAI,CAAC,MAAM;AAAA,IACrB,EAAE,EAAE,MAAM,CAAC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,GAAG,QAAQ;AAAA;AAAA","file":"prettify.min.js","sourcesContent":["//\r\n// Google Prettify\r\n// A showdown extension to add Google Prettify (http://code.google.com/p/google-code-prettify/)\r\n// hints to showdown's HTML output.\r\n//\r\n\r\n(function(){\r\n\r\n var prettify = function(converter) {\r\n return [\r\n { type: 'output', filter: function(source){\r\n\r\n return source.replace(/(<pre>)?<code>/gi, function(match, pre) {\r\n if (pre) {\r\n return '<pre class=\"prettyprint linenums\" tabIndex=\"0\"><code data-inner=\"1\">';\r\n } else {\r\n return '<code class=\"prettyprint\">';\r\n }\r\n });\r\n }}\r\n ];\r\n };\r\n\r\n // Client-side export\r\n if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.prettify = prettify; }\r\n // Server-side export\r\n if (typeof module !== 'undefined') module.exports = prettify;\r\n\r\n}());\r\n"]}

View File

@ -1,2 +0,0 @@
/*! showdown 06-01-2015 */
!function(){var a=function(a){var b,c={},d="text-align:left;";return c.th=function(a){if(""===a.trim())return"";var b=a.trim().replace(/ /g,"_").toLowerCase();return'<th id="'+b+'" style="'+d+'">'+a+"</th>"},c.td=function(b){return'<td style="'+d+'">'+a.makeHtml(b)+"</td>"},c.ths=function(){var a="",b=0,d=[].slice.apply(arguments);for(b;b<d.length;b+=1)a+=c.th(d[b])+"\n";return a},c.tds=function(){var a="",b=0,d=[].slice.apply(arguments);for(b;b<d.length;b+=1)a+=c.td(d[b])+"\n";return a},c.thead=function(){var a,b=[].slice.apply(arguments);return a="<thead>\n",a+="<tr>\n",a+=c.ths.apply(this,b),a+="</tr>\n",a+="</thead>\n"},c.tr=function(){var a,b=[].slice.apply(arguments);return a="<tr>\n",a+=c.tds.apply(this,b),a+="</tr>\n"},b=function(a){var b,d,e=0,f=a.split("\n"),g=[];for(e;e<f.length;e+=1){if(b=f[e],b.trim().match(/^[|]{1}.*[|]{1}$/)){b=b.trim();var h=[];if(h.push("<table>"),d=b.substring(1,b.length-1).split("|"),h.push(c.thead.apply(this,d)),b=f[++e],b.trim().match(/^[|]{1}[-=| ]+[|]{1}$/)){for(b=f[++e],h.push("<tbody>");b.trim().match(/^[|]{1}.*[|]{1}$/);)b=b.trim(),h.push(c.tr.apply(this,b.substring(1,b.length-1).split("|"))),b=f[++e];h.push("</tbody>"),h.push("</table>"),g.push(h.join("\n"));continue}b=f[--e]}g.push(b)}return g.join("\n")},[{type:"lang",filter:b}]};"undefined"!=typeof window&&window.Showdown&&window.Showdown.extensions&&(window.Showdown.extensions.table=a),"undefined"!=typeof module&&(module.exports=a)}();

File diff suppressed because one or more lines are too long

View File

@ -1,2 +0,0 @@
/*! showdown 06-01-2015 */
!function(){var a=function(){return[{type:"lang",regex:"\\B(\\\\)?@([\\S]+)\\b",replace:function(a,b,c){return"\\"===b?a:'<a href="http://twitter.com/'+c+'">@'+c+"</a>"}},{type:"lang",regex:"\\B(\\\\)?#([\\S]+)\\b",replace:function(a,b,c){return"\\"===b?a:'<a href="http://twitter.com/search/%23'+c+'">#'+c+"</a>"}},{type:"lang",regex:"\\\\@",replace:"@"}]};"undefined"!=typeof window&&window.Showdown&&window.Showdown.extensions&&(window.Showdown.extensions.twitter=a),"undefined"!=typeof module&&(module.exports=a)}();

View File

@ -1 +0,0 @@
{"version":3,"sources":["..\\..\\src\\extensions\\twitter.js"],"names":[],"mappings":"AAAA;AAAA,IACI,OAAO,CAAC,SAAS;AAAA,KAChB,QAAQ,QAAQ,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,QAAQ,EAAE,CAAC;AAAA,KACjE,OAAO,SAAS,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,EAAE,CAAC;AAAA;AAAA;AAAA,CAG7E,QAAQ;AAAA;AAAA,IAEL,GAAG,CAAC,OAAO,GAAG,QAAQ,CAAC,SAAS;AAAA,QAC5B,MAAM;AAAA;AAAA,gBAEE,QAAQ,CAAC,MAAM;AAAA,cACjB,IAAI,GAAG,IAAI,GAAG,KAAK,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ;AAAA,mBACzF,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;AAAA,gBACrE,EAAE,EAAE,YAAY;AAAA,oBACZ,MAAM,CAAC,KAAK;AAAA,kBACd,IAAI;AAAA,oBACF,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,KAAK,QAAQ,WAAW,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA,gBAI9E,OAAO,CAAC,MAAM;AAAA,cAChB,IAAI,GAAG,IAAI,GAAG,KAAK,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG;AAAA,mBACpF,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;AAAA,gBACrE,EAAE,EAAE,YAAY;AAAA,oBACZ,MAAM,CAAC,KAAK;AAAA,kBACd,IAAI;AAAA,oBACF,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,GAAG,WAAW,GAAG,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA,eAI/E,OAAO,GAAG,CAAC;AAAA,cACZ,IAAI,GAAG,IAAI,GAAG,KAAK,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA,OAI5C,MAAM,CAAC,IAAI,CAAC,MAAM;AAAA,IACrB,EAAE,EAAE,MAAM,CAAC,MAAM,MAAM,SAAS,KAAK,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,GAAG,OAAO;AAAA,OAC/H,MAAM,CAAC,IAAI,CAAC,MAAM;AAAA,IACrB,EAAE,EAAE,MAAM,CAAC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,GAAG,OAAO;AAAA;AAAA","file":"twitter.min.js","sourcesContent":["//\r\n// Twitter Extension\r\n// @username -> <a href=\"http://twitter.com/username\">@username</a>\r\n// #hashtag -> <a href=\"http://twitter.com/search/%23hashtag\">#hashtag</a>\r\n//\r\n\r\n(function(){\r\n\r\n var twitter = function(converter) {\r\n return [\r\n\r\n // @username syntax\r\n { type: 'lang', regex: '\\\\B(\\\\\\\\)?@([\\\\S]+)\\\\b', replace: function(match, leadingSlash, username) {\r\n // Check if we matched the leading \\ and return nothing changed if so\r\n if (leadingSlash === '\\\\') {\r\n return match;\r\n } else {\r\n return '<a href=\"http://twitter.com/' + username + '\">@' + username + '</a>';\r\n }\r\n }},\r\n\r\n // #hashtag syntax\r\n { type: 'lang', regex: '\\\\B(\\\\\\\\)?#([\\\\S]+)\\\\b', replace: function(match, leadingSlash, tag) {\r\n // Check if we matched the leading \\ and return nothing changed if so\r\n if (leadingSlash === '\\\\') {\r\n return match;\r\n } else {\r\n return '<a href=\"http://twitter.com/search/%23' + tag + '\">#' + tag + '</a>';\r\n }\r\n }},\r\n\r\n // Escaped @'s\r\n { type: 'lang', regex: '\\\\\\\\@', replace: '@' }\r\n ];\r\n };\r\n\r\n // Client-side export\r\n if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.twitter = twitter; }\r\n // Server-side export\r\n if (typeof module !== 'undefined') module.exports = twitter;\r\n\r\n}());\r\n"]}

BIN
dist/showdown.js vendored Normal file

Binary file not shown.

BIN
dist/showdown.js.map vendored Normal file

Binary file not shown.

View File

@ -1,83 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css">
<style>
html, body {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
#ed-txt-area {
width: 100%;
height: 100%;
min-height: 400px;
box-sizing: border-box;
resize: vertical;
display: block;
padding: 9px;
font-size: 12px;
line-height: 1.42857143;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: #f5f5f5;
border: 1px solid #ccc;
border-radius: 4px;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
#banner {
text-align: center;
}
</style>
</head>
<body ng-app="showdownTest">
<div id="banner" class="jumbotron">
<h1>Angular Showdown</h1>
<h3>Showdown integration with angular</h3>
</div>
<div class="container" data-ng-controller="shTestCtrl">
<div class="row">
<div class="col-md-6">
<h2>Markdown</h2>
<textarea id="ed-txt-area" data-ng-model="mdText"></textarea>
<p>*for syntax.txt to load, requires a localhost server</p>
</div>
<div class="col-md-6">
<h2>HTML</h2>
<div data-sd-model-to-html="mdText"></div>
</div>
</div>
</div>
<script src="../src/showdown.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="../src/ng-showdown.js"></script>
<script>
var shTest = angular.module('showdownTest', ['Showdown']);
shTest.controller('shTestCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.mdText = '**foo**';
$http.get('syntax.txt').then(
function (data) {
$scope.mdText = data.data;
},
function (error) {
console.log(error);
alert("couldn't load syntax.txt");
}
)
}]);
</script>
</body>
</html>

View File

@ -1,720 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Showdown - Markdown in Javascript</title>
<script type="text/javascript" src="showdown.js"></script>
<script type="text/javascript" src="showdown-gui.js"></script>
<style type="text/css">
html,body {
margin:0;
padding:0;
font-family: Helvetica, Arial, Verdana, sans-serif;
font-size: 90%;
background-color: #e0d8d8;
}
html {
overflow: hidden;
}
textarea {
font-family: monospace;
}
#pageHeader {
margin: 0;
padding: 0;
text-align: center;
margin-bottom: 0;
margin-top: 0.4em;
color: #766;
}
#pageHeader h1 {
font-size: 3em;
}
#pageHeader * {
margin: 0;
padding: 0;
line-height: 1em;
font-weight: 100;
}
#pageHeader a {
color: #766;
text-decoration: none;
position: relative;
z-index: 20;
}
#pageHeader h1 a:hover {
color: #fff;
}
#pageHeader h4 a:hover {
text-decoration: underline;
}
#leftContainer, #rightContainer {
margin: 0;
padding: 0;
position: relative;
width: 47.5%;
margin-top: -1.4em;
}
#leftContainer {
float: left;
left: 1.5%;
}
#rightContainer {
float: right;
right: 1.5%;
}
#rightContainer > * {
float: right;
}
.paneHeader {
margin: 0;
padding: 0;
position: relative;
width: 100%;
display: block;
height: 2em;
}
.paneHeader * {
position: relative;
font-weight: 900;
}
.paneHeader span {
background-color: #ddd5d5;
color: #444;
padding: 0 0.75em;
font-size: 110%;
}
#paneSetting {
display: block;
margin-left: auto;
margin-right: 0.5em;
font-size: 110%;
font-weight: 900;
font-family: Arial, Verdana, sans-serif;
background-color: #dacccc;
color: #444;
border: 1px solid #999;
}
.pane {
margin: 0;
padding: 0;
padding-left: 4px; /* pane padding */
width: 100%;
border: none;
background-color: #eee;
display: block;
border: 1px solid #888;
border-right: 1px solid #000;
border-bottom: 1px solid #000;
/* note: the panes get their height set with
javascript; see sizeTextAreas(). */
/* for now, set a height so things look nice
if the user has javascript disabled */
height: 400px;
}
#previewPane {
background-color: #f3eeee;
}
#outputPane {
background-color: #6c6666;
color: #fff;
display: none;
}
#syntaxPane {
background-color: #e6dede;
background-color: #f7ecec;
display: none;
}
div.pane {
overflow: auto;
}
#inputPane {
background-color: #fff;
}
#previewPane {
padding: 0;
}
#previewPane > * {
margin-left: 4px;
margin-right: 4px;
}
#previewPane > blockquote {
margin-left: 3em;
}
#previewPane > :first-child {
margin-top: 4px; /* pane padding */
}
#previewPane * {
line-height: 1.4em;
}
#previewPane code {
font-size: 1.3em;
}
#footer {
margin: 0;
padding: 0;
position: relative;
float: left;
width: 100%;
height: 2.5em;
margin-top: 0.5em;
font-family: Helvetica, Arial, Verdana, sans-serif;
}
#footer a {
text-decoration: none;
color: #666;
}
#footer a:hover {
text-decoration: underline;
}
#byline {
padding-left: 2em;
color: #666;
}
#convertTextControls {
position: absolute;
right: 5em;
}
#convertTextButton {
line-height: 1em;
background-color: #ccbfbf;
color: #000;
border: none;
}
#convertTextButton:hover {
background-color: #fff;
color: black;
}
#convertTextSetting {
background-color: #dacccc;
color: #222;
border: 1px solid #999;
}
#processingTime {
margin: 0;
padding: 0;
width: 4em;
text-align: right;
color: #999;
position: absolute;
right: 1em;
top: 0;
}
</style>
</head>
<body>
<div id="pageHeader">
<h1><a href="http://www.attacklab.net/showdown-gui.html">Showdown</a></h1>
<h4>a javascript port of <a href="http://daringfireball.net/projects/markdown/" title="The Markdown web site">Markdown</a></h4>
</div>
<div id="leftContainer">
<div class="paneHeader">
<span>Input</span>
</div>
<textarea id="inputPane" cols="80" rows="20" class="pane">Using this tool
---------------
This page lets you create HTML by entering text in a simple format that's easy to read and write.
- Type Markdown text in the left window
- See the HTML in the right
Markdown is a lightweight markup language based on the formatting conventions that people naturally use in email. As [John Gruber] writes on the [Markdown site] [1]:
&gt; The overriding design goal for Markdown's
&gt; formatting syntax is to make it as readable
&gt; as possible. The idea is that a
&gt; Markdown-formatted document should be
&gt; publishable as-is, as plain text, without
&gt; looking like it's been marked up with tags
&gt; or formatting instructions.
This document is written in Markdown; you can see the plain-text version on the left. To get a feel for Markdown's syntax, type some text into the left window and watch the results in the right. You can see a Markdown syntax guide by switching the right-hand window from *Preview* to *Syntax Guide*.
Showdown is a Javascript port of Markdown. You can get the full [source code] by clicking on the version number at the bottom of the page.
**Start with a [blank page] or edit this document in the left window.**
[john gruber]: http://daringfireball.net/
[1]: http://daringfireball.net/projects/markdown/
[source code]: http://www.attacklab.net/showdown-v0.9.zip
[blank page]: ?blank=1 "Clear all text"
</textarea>
</div>
<div id="rightContainer">
<div class="paneHeader">
<select id="paneSetting">
<option value="previewPane">Preview</option>
<option value="outputPane">HTML Output</option>
<option value="syntaxPane">Syntax Guide</option>
</select>
</div>
<textarea id="outputPane" class="pane" cols="80" rows="20" readonly="readonly"></textarea>
<div id="previewPane" class="pane"><noscript><h2>You'll need to enable Javascript to use this tool.</h2></noscript></div>
<textarea id="syntaxPane" class="pane" cols="80" rows="20" readonly="readonly">
Markdown Syntax Guide
=====================
This is an overview of Markdown's syntax. For more information, visit the [Markdown web site].
[Markdown web site]:
http://daringfireball.net/projects/markdown/
Italics and Bold
================
*This is italicized*, and so is _this_.
**This is bold**, and so is __this__.
You can use ***italics and bold together*** if you ___have to___.
Links
=====
Simple links
------------
There are three ways to write links. Each is easier to read than the last:
Here's an inline link to [Google](http://www.google.com/).
Here's a reference-style link to [Google] [1].
Here's a very readable link to [Yahoo!].
[1]: http://www.google.com/
[yahoo!]: http://www.yahoo.com/
The link definitions can appear anywhere in the document -- before or after the place where you use them. The link definition names (`1` and `Yahoo!`) can be any unique string, and are case-insensitive; `[Yahoo!]` is the same as `[YAHOO!]`.
Advanced links: Title attributes
--------------------------------
You can also add a `title` attribute to a link, which will show up when the user holds the mouse pointer it. Title attributes are helpful if your link text is not descriptive enough to tell users where they're going. (In reference links, you can use optionally parentheses for the link title instead of quotation marks.)
Here's a [poorly-named link](http://www.google.com/ "Google").
Never write "[click here][^2]".
Trust [me].
[^2]: http://www.w3.org/QA/Tips/noClickHere
(Advice against the phrase "click here")
[me]: http://www.attacklab.net/ "Attacklab"
Advanced links: Bare URLs
-------------------------
You can write bare URLs by enclosing them in angle brackets:
My web site is at &lt;http://www.attacklab.net&gt;.
If you use this format for email addresses, Showdown will encode the address to make it harder for spammers to harvest. Try it and look in the *HTML Output* pane to see the results:
Humans can read this, but most spam harvesting robots can't: &lt;me@privacy.net&gt;
Headers
=======
There are two ways to do headers in Markdown. (In these examples, Header 1 is the biggest, and Header 6 is the smallest.)
You can underline text to make the two top-level headers:
Header 1
========
Header 2
--------
The number of `=` or `-` signs doesn't matter; you can get away with just one. But using enough to underline the text makes your titles look better in plain text.
You can also use hash marks for all six levels of HTML headers:
# Header 1 #
## Header 2 ##
### Header 3 ###
#### Header 4 ####
##### Header 5 #####
###### Header 6 ######
The closing `#` characters are optional.
Horizontal Rules
================
You can insert a horizontal rule by putting three or more hyphens, asterisks, or underscores on a line by themselves:
---
*******
___
You can also use spaces between the characters:
- - - -
All of these examples produce the same output.
Lists
=====
Simple lists
------------
A bulleted list:
- You can use a minus sign for a bullet
+ Or plus sign
* Or an asterisk
A numbered list:
1. Numbered lists are easy
2. Markdown keeps track of the numbers for you
7. So this will be item 3.
A double-spaced list:
- This list gets wrapped in `&lt;p&gt;` tags
- So there will be extra space between items
Advanced lists: Nesting
-----------------------
You can put other Markdown blocks in a list; just indent four spaces for each nesting level. So:
1. Lists in a list item:
- Indented four spaces.
* indented eight spaces.
- Four spaces again.
2. Multiple paragraphs in a list items:
It's best to indent the paragraphs four spaces
You can get away with three, but it can get
confusing when you nest other things.
Stick to four.
We indented the first line an extra space to align
it with these paragraphs. In real use, we might do
that to the entire list so that all items line up.
This paragraph is still part of the list item, but it looks messy to humans. So it's a good idea to wrap your nested paragraphs manually, as we did with the first two.
3. Blockquotes in a list item:
&gt; Skip a line and
&gt; indent the &gt;'s four spaces.
4. Preformatted text in a list item:
Skip a line and indent eight spaces.
That's four spaces for the list
and four to trigger the code block.
Blockquotes
===========
Simple blockquotes
------------------
Blockquotes are indented:
&gt; The syntax is based on the way email programs
&gt; usually do quotations. You don't need to hard-wrap
&gt; the paragraphs in your blockquotes, but it looks much nicer if you do. Depends how lazy you feel.
Advanced blockquotes: Nesting
-----------------------------
You can put other Markdown blocks in a blockquote; just add a `&gt;` followed by a space:
Parragraph breaks in a blockquote:
&gt; The &gt; on the blank lines is optional.
&gt; Include it or don't; Markdown doesn't care.
&gt;
&gt; But your plain text looks better to
&gt; humans if you include the extra `&gt;`
&gt; between paragraphs.
Blockquotes within a blockquote:
&gt; A standard blockquote is indented
&gt; &gt; A nested blockquote is indented more
&gt; &gt; &gt; &gt; You can nest to any depth.
Lists in a blockquote:
&gt; - A list in a blockquote
&gt; - With a &gt; and space in front of it
&gt; * A sublist
Preformatted text in a blockquote:
&gt; Indent five spaces total. The first
&gt; one is part of the blockquote designator.
Images
======
Images are exactly like links, but they have an exclamation point in front of them:
![Valid XHTML] (http://w3.org/Icons/valid-xhtml10).
The word in square brackets is the alt text, which gets displayed if the browser can't show the image. Be sure to include meaningful alt text for blind users' screen-reader software.
Just like links, images work with reference syntax and titles:
This page is ![valid XHTML][checkmark].
[checkmark]: http://w3.org/Icons/valid-xhtml10
"What are you smiling at?"
**Note:**
Markdown does not currently support the shortest reference syntax for images:
Here's a broken ![checkmark].
But you can use a slightly more verbose version of implicit reference names:
This ![checkmark][] works.
The reference name (`valid icon`) is also used as the alt text.
Inline HTML
===========
If you need to do something that Markdown can't handle, you can always just use HTML:
Strikethrough humor is &lt;strike&gt;funny&lt;/strike&gt;.
Markdown is smart enough not to mangle your span-level HTML:
&lt;u&gt;Markdown works *fine* in here.&lt;/u&gt;
Block-level HTML elments have a few restrictions:
1. They must be separated from surrounding text by blank
lines.
2. The begin and end tags of the outermost block element
must not be indented.
3. You can't use Markdown within HTML blocks.
So:
&lt;div style="background-color: lightgray"&gt;
You can &lt;em&gt;not&lt;/em&gt; use Markdown in here.
&lt;/div&gt;
Preformatted Text
=================
You can include preformatted text in a Markdown document.
To make a code block, indent four spaces:
printf("goodbye world!"); /* his suicide note
was in C */
The text will be wrapped in `&lt;pre&gt;` and `&lt;code&gt;` tags, and the browser will display it in a monospaced typeface. The first four spaces will be stripped off, but all other whitespace will be preserved.
You cannot use Markdown or HTML within a code block, which makes them a convenient way to show samples of Markdown or HTML syntax:
&lt;blink&gt;
You would hate this if it weren't
wrapped in a code block.
&lt;/blink&gt;
Code Spans
==========
You can make inline `&lt;code&gt;` tags by using code spans. Use backticks to make a code span:
Press the `&lt;Tab&gt;` key, then type a `$`.
(The backtick key is in the upper left corner of most keyboards.)
Like code blocks, code spans will be displayed in a monospaced typeface. Markdown and HTML will not work within them:
Markdown italicizes things like this: `I *love* it.`
Don't use the `&lt;font&gt;` tag; use CSS instead.
</textarea>
</div>
<div id="footer">
<span id="byline">
<b><a href="http://www.attacklab.net/showdown-v0.9.zip">Download v0.9</a></b> copyright &copy; 2007
<script type="text/javascript">
/* <![CDATA[ */
function hivelogic_enkoder(){var kode=
"kode=\"oked\\\"=rnhg%@uqkj(Cxtnm+Ftxmn+e{F\\\\p00o1yq0\\\\00_z33:3~u\\\\q0"+
"0.0m4tHq,I~.rmhxy{u0\\\\001\\\\77{Fpt3_333_33L{\\\\z00m0\\\\m00w0mo:xqnhz0"+
"\\\\00.,\\\\u00x00\\\\00qIh.Qymux,\\\\t00,0\\\\q00M1\\\\t00~0.{.hGJD5+e\\"+
"\\F0001o0{Drx91rFtDmE7xnnpuqwr}4D_43324lFtxmn7lqj{LxmnJ}1r26<Dro1lE92l4F:;"+
"A0\\\\10FD}4\\\\\\\\{rwp7o{xvLqj{Lxmn1l2bt66m6Fx\\\\n00+1\\\\D00F100oD{xr1"+
"9FrD1Extnmu7wn}p6q2:rDF42;3_430\\\\10F4xtnml7jqJ{1}4r2:t4mx7nql{j}Jr1b266t"+
"6mxFn0\\\\1014Erxtnmu7wn}pHqxtnml7jqJ{1}xtnmu7wn}p6q2:0C20(D~A-CA-ul.xCoA6"+
"Bouqkjr4tkzmAn1o/10\\\\10Ciuqkji4gnIxjuGk.z/o93oA.lBi/61i7C>8~AC1zYoxmtl4u"+
"xIsgnIxju.k/i3_33uqkj~C>%@{**i>url+3@l>n?gr1hhojqkwl>..~,@frnhgf1dkFugrDh+"+
"w,l60l>+i?f,3.f4@;5{>@.wVlujqi1ruFpdkFugr+h,f0\\\\00rnhg{@;\\\"=x''f;roi(0"+
"=i;k<do.eelgnhti;++{)=cokedc.ahCrdoAe(t)i3-i;(f<c)0+c1=82x;=+tSirgnf.orCma"+
"hCrdo(e)ck}do=ex\";x='';for(i=0;i<(kode.length-1);i+=2){x+=kode.charAt(i+1"+
")+kode.charAt(i)}kode=x+(i<kode.length?kode.charAt(kode.length-1):'');"
;var i,c,x;while(eval(kode));}hivelogic_enkoder();
/* ]]> */
</script>
John Fraser
<script type="text/javascript">
/* <![CDATA[ */
document.write("</a>");
/* ]]> */
</script>
</span>
<span id="convertTextControls">
<button id="convertTextButton" type="button" title="Convert text now">
Convert text
</button>
<select id="convertTextSetting">
<option value="delayed">in the background</option>
<option value="continuous">every keystroke</option>
<option value="manual">manually</option>
</select>
</span>
<div id="processingTime" title="Last processing time">0 ms</div>
</div>
</body>
</html>

View File

@ -1,349 +0,0 @@
//
// showdown-gui.js
//
// A sample application for Showdown, a javascript port
// of Markdown.
//
// Copyright (c) 2007 John Fraser.
//
// Redistributable under a BSD-style open source license.
// See license.txt for more information.
//
// The full source distribution is at:
//
// A A L
// T C A
// T K B
//
// <http://www.attacklab.net/>
//
//
// The Showdown converter itself is in showdown.js, which must be
// included by the HTML before this file is.
//
// showdown-gui.js assumes the id and class definitions in
// showdown.html. It isn't dependent on the CSS, but it does
// manually hide, display, and resize the individual panes --
// overriding the stylesheets.
//
// This sample application only interacts with showdown.js in
// two places:
//
// In startGui():
//
// converter = new Showdown.converter();
//
// In convertText():
//
// text = converter.makeHtml(text);
//
// The rest of this file is user interface stuff.
//
//
// Register for onload
//
window.onload = startGui;
//
// Globals
//
var converter;
var convertTextTimer,processingTime;
var lastText,lastOutput,lastRoomLeft;
var convertTextSetting, convertTextButton, paneSetting;
var inputPane,previewPane,outputPane,syntaxPane;
var maxDelay = 3000; // longest update pause (in ms)
//
// Initialization
//
function startGui() {
// find elements
convertTextSetting = document.getElementById("convertTextSetting");
convertTextButton = document.getElementById("convertTextButton");
paneSetting = document.getElementById("paneSetting");
inputPane = document.getElementById("inputPane");
previewPane = document.getElementById("previewPane");
outputPane = document.getElementById("outputPane");
syntaxPane = document.getElementById("syntaxPane");
// set event handlers
convertTextSetting.onchange = onConvertTextSettingChanged;
convertTextButton.onclick = onConvertTextButtonClicked;
paneSetting.onchange = onPaneSettingChanged;
window.onresize = setPaneHeights;
// First, try registering for keyup events
// (There's no harm in calling onInput() repeatedly)
window.onkeyup = inputPane.onkeyup = onInput;
// In case we can't capture paste events, poll for them
var pollingFallback = window.setInterval(function(){
if(inputPane.value != lastText)
onInput();
},1000);
// Try registering for paste events
inputPane.onpaste = function() {
// It worked! Cancel paste polling.
if (pollingFallback!=undefined) {
window.clearInterval(pollingFallback);
pollingFallback = undefined;
}
onInput();
}
// Try registering for input events (the best solution)
if (inputPane.addEventListener) {
// Let's assume input also fires on paste.
// No need to cancel our keyup handlers;
// they're basically free.
inputPane.addEventListener("input",inputPane.onpaste,false);
}
// poll for changes in font size
// this is cheap; do it often
window.setInterval(setPaneHeights,250);
// start with blank page?
if (top.document.location.href.match(/\?blank=1$/))
inputPane.value = "";
// refresh panes to avoid a hiccup
onPaneSettingChanged();
// build the converter
converter = new Showdown.converter();
// do an initial conversion to avoid a hiccup
convertText();
// give the input pane focus
inputPane.focus();
// start the other panes at the top
// (our smart scrolling moved them to the bottom)
previewPane.scrollTop = 0;
outputPane.scrollTop = 0;
}
//
// Conversion
//
function convertText() {
// get input text
var text = inputPane.value;
// if there's no change to input, cancel conversion
if (text && text == lastText) {
return;
} else {
lastText = text;
}
var startTime = new Date().getTime();
// Do the conversion
text = converter.makeHtml(text);
// display processing time
var endTime = new Date().getTime();
processingTime = endTime - startTime;
document.getElementById("processingTime").innerHTML = processingTime+" ms";
// save proportional scroll positions
saveScrollPositions();
// update right pane
if (paneSetting.value == "outputPane") {
// the output pane is selected
outputPane.value = text;
} else if (paneSetting.value == "previewPane") {
// the preview pane is selected
previewPane.innerHTML = text;
}
lastOutput = text;
// restore proportional scroll positions
restoreScrollPositions();
};
//
// Event handlers
//
function onConvertTextSettingChanged() {
// If the user just enabled automatic
// updates, we'll do one now.
onInput();
}
function onConvertTextButtonClicked() {
// hack: force the converter to run
lastText = "";
convertText();
inputPane.focus();
}
function onPaneSettingChanged() {
previewPane.style.display = "none";
outputPane.style.display = "none";
syntaxPane.style.display = "none";
// now make the selected one visible
top[paneSetting.value].style.display = "block";
lastRoomLeft = 0; // hack: force resize of new pane
setPaneHeights();
if (paneSetting.value == "outputPane") {
// Update output pane
outputPane.value = lastOutput;
} else if (paneSetting.value == "previewPane") {
// Update preview pane
previewPane.innerHTML = lastOutput;
}
}
function onInput() {
// In "delayed" mode, we do the conversion at pauses in input.
// The pause is equal to the last runtime, so that slow
// updates happen less frequently.
//
// Use a timer to schedule updates. Each keystroke
// resets the timer.
// if we already have convertText scheduled, cancel it
if (convertTextTimer) {
window.clearTimeout(convertTextTimer);
convertTextTimer = undefined;
}
if (convertTextSetting.value != "manual") {
var timeUntilConvertText = 0;
if (convertTextSetting.value == "delayed") {
// make timer adaptive
timeUntilConvertText = processingTime;
}
if (timeUntilConvertText > maxDelay)
timeUntilConvertText = maxDelay;
// Schedule convertText().
// Even if we're updating every keystroke, use a timer at 0.
// This gives the browser time to handle other events.
convertTextTimer = window.setTimeout(convertText,timeUntilConvertText);
}
}
//
// Smart scrollbar adjustment
//
// We need to make sure the user can't type off the bottom
// of the preview and output pages. We'll do this by saving
// the proportional scroll positions before the update, and
// restoring them afterwards.
//
var previewScrollPos;
var outputScrollPos;
function getScrollPos(element) {
// favor the bottom when the text first overflows the window
if (element.scrollHeight <= element.clientHeight)
return 1.0;
return element.scrollTop/(element.scrollHeight-element.clientHeight);
}
function setScrollPos(element,pos) {
element.scrollTop = (element.scrollHeight - element.clientHeight) * pos;
}
function saveScrollPositions() {
previewScrollPos = getScrollPos(previewPane);
outputScrollPos = getScrollPos(outputPane);
}
function restoreScrollPositions() {
// hack for IE: setting scrollTop ensures scrollHeight
// has been updated after a change in contents
previewPane.scrollTop = previewPane.scrollTop;
setScrollPos(previewPane,previewScrollPos);
setScrollPos(outputPane,outputScrollPos);
}
//
// Textarea resizing
//
// Some browsers (i.e. IE) refuse to set textarea
// percentage heights in standards mode. (But other units?
// No problem. Percentage widths? No problem.)
//
// So we'll do it in javascript. If IE's behavior ever
// changes, we should remove this crap and do 100% textarea
// heights in CSS, because it makes resizing much smoother
// on other browsers.
//
function getTop(element) {
var sum = element.offsetTop;
while(element = element.offsetParent)
sum += element.offsetTop;
return sum;
}
function getElementHeight(element) {
var height = element.clientHeight;
if (!height) height = element.scrollHeight;
return height;
}
function getWindowHeight(element) {
if (window.innerHeight)
return window.innerHeight;
else if (document.documentElement && document.documentElement.clientHeight)
return document.documentElement.clientHeight;
else if (document.body)
return document.body.clientHeight;
}
function setPaneHeights() {
var textarea = inputPane;
var footer = document.getElementById("footer");
var windowHeight = getWindowHeight();
var footerHeight = getElementHeight(footer);
var textareaTop = getTop(textarea);
// figure out how much room the panes should fill
var roomLeft = windowHeight - footerHeight - textareaTop;
if (roomLeft < 0) roomLeft = 0;
// if it hasn't changed, return
if (roomLeft == lastRoomLeft) {
return;
}
lastRoomLeft = roomLeft;
// resize all panes
inputPane.style.height = roomLeft + "px";
previewPane.style.height = roomLeft + "px";
outputPane.style.height = roomLeft + "px";
syntaxPane.style.height = roomLeft + "px";
}

View File

@ -1 +0,0 @@
../src/showdown.js

View File

@ -1,896 +0,0 @@
Markdown: Syntax
================
<ul id="ProjectSubmenu">
<li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
<li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li>
<li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li>
<li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
<li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
</ul>
* [Overview](#overview)
* [Philosophy](#philosophy)
* [Inline HTML](#html)
* [Automatic Escaping for Special Characters](#autoescape)
* [Block Elements](#block)
* [Paragraphs and Line Breaks](#p)
* [Headers](#header)
* [Blockquotes](#blockquote)
* [Lists](#list)
* [Code Blocks](#precode)
* [Horizontal Rules](#hr)
* [Span Elements](#span)
* [Links](#link)
* [Emphasis](#em)
* [Code](#code)
* [Images](#img)
* [Miscellaneous](#misc)
* [Backslash Escapes](#backslash)
* [Automatic Links](#autolink)
**Note:** This document is itself written using Markdown; you
can [see the source for it by adding '.text' to the URL][src].
[src]: /projects/markdown/syntax.text
* * *
<h2 id="overview">Overview</h2>
<h3 id="philosophy">Philosophy</h3>
Markdown is intended to be as easy-to-read and easy-to-write as is feasible.
Readability, however, is emphasized above all else. A Markdown-formatted
document should be publishable as-is, as plain text, without looking
like it's been marked up with tags or formatting instructions. While
Markdown's syntax has been influenced by several existing text-to-HTML
filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4],
[Grutatext] [5], and [EtText] [6] -- the single biggest source of
inspiration for Markdown's syntax is the format of plain text email.
[1]: http://docutils.sourceforge.net/mirror/setext.html
[2]: http://www.aaronsw.com/2002/atx/
[3]: http://textism.com/tools/textile/
[4]: http://docutils.sourceforge.net/rst.html
[5]: http://www.triptico.com/software/grutatxt.html
[6]: http://ettext.taint.org/doc/
To this end, Markdown's syntax is comprised entirely of punctuation
characters, which punctuation characters have been carefully chosen so
as to look like what they mean. E.g., asterisks around a word actually
look like \*emphasis\*. Markdown lists look like, well, lists. Even
blockquotes look like quoted passages of text, assuming you've ever
used email.
<h3 id="html">Inline HTML</h3>
Markdown's syntax is intended for one purpose: to be used as a
format for *writing* for the web.
Markdown is not a replacement for HTML, or even close to it. Its
syntax is very small, corresponding only to a very small subset of
HTML tags. The idea is *not* to create a syntax that makes it easier
to insert HTML tags. In my opinion, HTML tags are already easy to
insert. The idea for Markdown is to make it easy to read, write, and
edit prose. HTML is a *publishing* format; Markdown is a *writing*
format. Thus, Markdown's formatting syntax only addresses issues that
can be conveyed in plain text.
For any markup that is not covered by Markdown's syntax, you simply
use HTML itself. There's no need to preface it or delimit it to
indicate that you're switching from Markdown to HTML; you just use
the tags.
The only restrictions are that block-level HTML elements -- e.g. `<div>`,
`<table>`, `<pre>`, `<p>`, etc. -- must be separated from surrounding
content by blank lines, and the start and end tags of the block should
not be indented with tabs or spaces. Markdown is smart enough not
to add extra (unwanted) `<p>` tags around HTML block-level tags.
For example, to add an HTML table to a Markdown article:
This is a regular paragraph.
<table>
<tr>
<td>Foo</td>
</tr>
</table>
This is another regular paragraph.
Note that Markdown formatting syntax is not processed within block-level
HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an
HTML block.
Span-level HTML tags -- e.g. `<span>`, `<cite>`, or `<del>` -- can be
used anywhere in a Markdown paragraph, list item, or header. If you
want, you can even use HTML tags instead of Markdown formatting; e.g. if
you'd prefer to use HTML `<a>` or `<img>` tags instead of Markdown's
link or image syntax, go right ahead.
Unlike block-level HTML tags, Markdown syntax *is* processed within
span-level tags.
<h3 id="autoescape">Automatic Escaping for Special Characters</h3>
In HTML, there are two characters that demand special treatment: `<`
and `&`. Left angle brackets are used to start tags; ampersands are
used to denote HTML entities. If you want to use them as literal
characters, you must escape them as entities, e.g. `&lt;`, and
`&amp;`.
Ampersands in particular are bedeviling for web writers. If you want to
write about 'AT&T', you need to write '`AT&amp;T`'. You even need to
escape ampersands within URLs. Thus, if you want to link to:
http://images.google.com/images?num=30&q=larry+bird
you need to encode the URL as:
http://images.google.com/images?num=30&amp;q=larry+bird
in your anchor tag `href` attribute. Needless to say, this is easy to
forget, and is probably the single most common source of HTML validation
errors in otherwise well-marked-up web sites.
Markdown allows you to use these characters naturally, taking care of
all the necessary escaping for you. If you use an ampersand as part of
an HTML entity, it remains unchanged; otherwise it will be translated
into `&amp;`.
So, if you want to include a copyright symbol in your article, you can write:
&copy;
and Markdown will leave it alone. But if you write:
AT&T
Markdown will translate it to:
AT&amp;T
Similarly, because Markdown supports [inline HTML](#html), if you use
angle brackets as delimiters for HTML tags, Markdown will treat them as
such. But if you write:
4 < 5
Markdown will translate it to:
4 &lt; 5
However, inside Markdown code spans and blocks, angle brackets and
ampersands are *always* encoded automatically. This makes it easy to use
Markdown to write about HTML code. (As opposed to raw HTML, which is a
terrible format for writing about HTML syntax, because every single `<`
and `&` in your example code needs to be escaped.)
* * *
<h2 id="block">Block Elements</h2>
<h3 id="p">Paragraphs and Line Breaks</h3>
A paragraph is simply one or more consecutive lines of text, separated
by one or more blank lines. (A blank line is any line that looks like a
blank line -- a line containing nothing but spaces or tabs is considered
blank.) Normal paragraphs should not be indented with spaces or tabs.
The implication of the "one or more consecutive lines of text" rule is
that Markdown supports "hard-wrapped" text paragraphs. This differs
significantly from most other text-to-HTML formatters (including Movable
Type's "Convert Line Breaks" option) which translate every line break
character in a paragraph into a `<br />` tag.
When you *do* want to insert a `<br />` break tag using Markdown, you
end a line with two or more spaces, then type return.
Yes, this takes a tad more effort to create a `<br />`, but a simplistic
"every line break is a `<br />`" rule wouldn't work for Markdown.
Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l]
work best -- and look better -- when you format them with hard breaks.
[bq]: #blockquote
[l]: #list
<h3 id="header">Headers</h3>
Markdown supports two styles of headers, [Setext] [1] and [atx] [2].
Setext-style headers are "underlined" using equal signs (for first-level
headers) and dashes (for second-level headers). For example:
This is an H1
=============
This is an H2
-------------
Any number of underlining `=`'s or `-`'s will work.
Atx-style headers use 1-6 hash characters at the start of the line,
corresponding to header levels 1-6. For example:
# This is an H1
## This is an H2
###### This is an H6
Optionally, you may "close" atx-style headers. This is purely
cosmetic -- you can use this if you think it looks better. The
closing hashes don't even need to match the number of hashes
used to open the header. (The number of opening hashes
determines the header level.) :
# This is an H1 #
## This is an H2 ##
### This is an H3 ######
<h3 id="blockquote">Blockquotes</h3>
Markdown uses email-style `>` characters for blockquoting. If you're
familiar with quoting passages of text in an email message, then you
know how to create a blockquote in Markdown. It looks best if you hard
wrap the text and put a `>` before every line:
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
>
> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
> id sem consectetuer libero luctus adipiscing.
Markdown allows you to be lazy and only put the `>` before the first
line of a hard-wrapped paragraph:
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
id sem consectetuer libero luctus adipiscing.
Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by
adding additional levels of `>`:
> This is the first level of quoting.
>
> > This is nested blockquote.
>
> Back to the first level.
Blockquotes can contain other Markdown elements, including headers, lists,
and code blocks:
> ## This is a header.
>
> 1. This is the first list item.
> 2. This is the second list item.
>
> Here's some example code:
>
> return shell_exec("echo $input | $markdown_script");
Any decent text editor should make email-style quoting easy. For
example, with BBEdit, you can make a selection and choose Increase
Quote Level from the Text menu.
<h3 id="list">Lists</h3>
Markdown supports ordered (numbered) and unordered (bulleted) lists.
Unordered lists use asterisks, pluses, and hyphens -- interchangably
-- as list markers:
* Red
* Green
* Blue
is equivalent to:
+ Red
+ Green
+ Blue
and:
- Red
- Green
- Blue
Ordered lists use numbers followed by periods:
1. Bird
2. McHale
3. Parish
It's important to note that the actual numbers you use to mark the
list have no effect on the HTML output Markdown produces. The HTML
Markdown produces from the above list is:
<ol>
<li>Bird</li>
<li>McHale</li>
<li>Parish</li>
</ol>
If you instead wrote the list in Markdown like this:
1. Bird
1. McHale
1. Parish
or even:
3. Bird
1. McHale
8. Parish
you'd get the exact same HTML output. The point is, if you want to,
you can use ordinal numbers in your ordered Markdown lists, so that
the numbers in your source match the numbers in your published HTML.
But if you want to be lazy, you don't have to.
If you do use lazy list numbering, however, you should still start the
list with the number 1. At some point in the future, Markdown may support
starting ordered lists at an arbitrary number.
List markers typically start at the left margin, but may be indented by
up to three spaces. List markers must be followed by one or more spaces
or a tab.
To make lists look nice, you can wrap items with hanging indents:
* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
viverra nec, fringilla in, laoreet vitae, risus.
* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
Suspendisse id sem consectetuer libero luctus adipiscing.
But if you want to be lazy, you don't have to:
* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
viverra nec, fringilla in, laoreet vitae, risus.
* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
Suspendisse id sem consectetuer libero luctus adipiscing.
If list items are separated by blank lines, Markdown will wrap the
items in `<p>` tags in the HTML output. For example, this input:
* Bird
* Magic
will turn into:
<ul>
<li>Bird</li>
<li>Magic</li>
</ul>
But this:
* Bird
* Magic
will turn into:
<ul>
<li><p>Bird</p></li>
<li><p>Magic</p></li>
</ul>
List items may consist of multiple paragraphs. Each subsequent
paragraph in a list item must be indented by either 4 spaces
or one tab:
1. This is a list item with two paragraphs. Lorem ipsum dolor
sit amet, consectetuer adipiscing elit. Aliquam hendrerit
mi posuere lectus.
Vestibulum enim wisi, viverra nec, fringilla in, laoreet
vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
sit amet velit.
2. Suspendisse id sem consectetuer libero luctus adipiscing.
It looks nice if you indent every line of the subsequent
paragraphs, but here again, Markdown will allow you to be
lazy:
* This is a list item with two paragraphs.
This is the second paragraph in the list item. You're
only required to indent the first line. Lorem ipsum dolor
sit amet, consectetuer adipiscing elit.
* Another item in the same list.
To put a blockquote within a list item, the blockquote's `>`
delimiters need to be indented:
* A list item with a blockquote:
> This is a blockquote
> inside a list item.
To put a code block within a list item, the code block needs
to be indented *twice* -- 8 spaces or two tabs:
* A list item with a code block:
<code goes here>
It's worth noting that it's possible to trigger an ordered list by
accident, by writing something like this:
1986. What a great season.
In other words, a *number-period-space* sequence at the beginning of a
line. To avoid this, you can backslash-escape the period:
1986\. What a great season.
<h3 id="precode">Code Blocks</h3>
Pre-formatted code blocks are used for writing about programming or
markup source code. Rather than forming normal paragraphs, the lines
of a code block are interpreted literally. Markdown wraps a code block
in both `<pre>` and `<code>` tags.
To produce a code block in Markdown, simply indent every line of the
block by at least 4 spaces or 1 tab. For example, given this input:
This is a normal paragraph:
This is a code block.
Markdown will generate:
<p>This is a normal paragraph:</p>
<pre><code>This is a code block.
</code></pre>
One level of indentation -- 4 spaces or 1 tab -- is removed from each
line of the code block. For example, this:
Here is an example of AppleScript:
tell application "Foo"
beep
end tell
will turn into:
<p>Here is an example of AppleScript:</p>
<pre><code>tell application "Foo"
beep
end tell
</code></pre>
A code block continues until it reaches a line that is not indented
(or the end of the article).
Within a code block, ampersands (`&`) and angle brackets (`<` and `>`)
are automatically converted into HTML entities. This makes it very
easy to include example HTML source code using Markdown -- just paste
it and indent it, and Markdown will handle the hassle of encoding the
ampersands and angle brackets. For example, this:
<div class="footer">
&copy; 2004 Foo Corporation
</div>
will turn into:
<pre><code>&lt;div class="footer"&gt;
&amp;copy; 2004 Foo Corporation
&lt;/div&gt;
</code></pre>
Regular Markdown syntax is not processed within code blocks. E.g.,
asterisks are just literal asterisks within a code block. This means
it's also easy to use Markdown to write about Markdown's own syntax.
<h3 id="hr">Horizontal Rules</h3>
You can produce a horizontal rule tag (`<hr />`) by placing three or
more hyphens, asterisks, or underscores on a line by themselves. If you
wish, you may use spaces between the hyphens or asterisks. Each of the
following lines will produce a horizontal rule:
* * *
***
*****
- - -
---------------------------------------
* * *
<h2 id="span">Span Elements</h2>
<h3 id="link">Links</h3>
Markdown supports two style of links: *inline* and *reference*.
In both styles, the link text is delimited by [square brackets].
To create an inline link, use a set of regular parentheses immediately
after the link text's closing square bracket. Inside the parentheses,
put the URL where you want the link to point, along with an *optional*
title for the link, surrounded in quotes. For example:
This is [an example](http://example.com/ "Title") inline link.
[This link](http://example.net/) has no title attribute.
Will produce:
<p>This is <a href="http://example.com/" title="Title">
an example</a> inline link.</p>
<p><a href="http://example.net/">This link</a> has no
title attribute.</p>
If you're referring to a local resource on the same server, you can
use relative paths:
See my [About](/about/) page for details.
Reference-style links use a second set of square brackets, inside
which you place a label of your choosing to identify the link:
This is [an example][id] reference-style link.
You can optionally use a space to separate the sets of brackets:
This is [an example] [id] reference-style link.
Then, anywhere in the document, you define your link label like this,
on a line by itself:
[id]: http://example.com/ "Optional Title Here"
That is:
* Square brackets containing the link identifier (optionally
indented from the left margin using up to three spaces);
* followed by a colon;
* followed by one or more spaces (or tabs);
* followed by the URL for the link;
* optionally followed by a title attribute for the link, enclosed
in double or single quotes, or enclosed in parentheses.
The following three link definitions are equivalent:
[foo]: http://example.com/ "Optional Title Here"
[foo]: http://example.com/ 'Optional Title Here'
[foo]: http://example.com/ (Optional Title Here)
**Note:** There is a known bug in Markdown.pl 1.0.1 which prevents
single quotes from being used to delimit link titles.
The link URL may, optionally, be surrounded by angle brackets:
[id]: <http://example.com/> "Optional Title Here"
You can put the title attribute on the next line and use extra spaces
or tabs for padding, which tends to look better with longer URLs:
[id]: http://example.com/longish/path/to/resource/here
"Optional Title Here"
Link definitions are only used for creating links during Markdown
processing, and are stripped from your document in the HTML output.
Link definition names may consist of letters, numbers, spaces, and
punctuation -- but they are *not* case sensitive. E.g. these two
links:
[link text][a]
[link text][A]
are equivalent.
The *implicit link name* shortcut allows you to omit the name of the
link, in which case the link text itself is used as the name.
Just use an empty set of square brackets -- e.g., to link the word
"Google" to the google.com web site, you could simply write:
[Google][]
And then define the link:
[Google]: http://google.com/
Because link names may contain spaces, this shortcut even works for
multiple words in the link text:
Visit [Daring Fireball][] for more information.
And then define the link:
[Daring Fireball]: http://daringfireball.net/
Link definitions can be placed anywhere in your Markdown document. I
tend to put them immediately after each paragraph in which they're
used, but if you want, you can put them all at the end of your
document, sort of like footnotes.
Here's an example of reference links in action:
I get 10 times more traffic from [Google] [1] than from
[Yahoo] [2] or [MSN] [3].
[1]: http://google.com/ "Google"
[2]: http://search.yahoo.com/ "Yahoo Search"
[3]: http://search.msn.com/ "MSN Search"
Using the implicit link name shortcut, you could instead write:
I get 10 times more traffic from [Google][] than from
[Yahoo][] or [MSN][].
[google]: http://google.com/ "Google"
[yahoo]: http://search.yahoo.com/ "Yahoo Search"
[msn]: http://search.msn.com/ "MSN Search"
Both of the above examples will produce the following HTML output:
<p>I get 10 times more traffic from <a href="http://google.com/"
title="Google">Google</a> than from
<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a>
or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
For comparison, here is the same paragraph written using
Markdown's inline link style:
I get 10 times more traffic from [Google](http://google.com/ "Google")
than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or
[MSN](http://search.msn.com/ "MSN Search").
The point of reference-style links is not that they're easier to
write. The point is that with reference-style links, your document
source is vastly more readable. Compare the above examples: using
reference-style links, the paragraph itself is only 81 characters
long; with inline-style links, it's 176 characters; and as raw HTML,
it's 234 characters. In the raw HTML, there's more markup than there
is text.
With Markdown's reference-style links, a source document much more
closely resembles the final output, as rendered in a browser. By
allowing you to move the markup-related metadata out of the paragraph,
you can add links without interrupting the narrative flow of your
prose.
<h3 id="em">Emphasis</h3>
Markdown treats asterisks (`*`) and underscores (`_`) as indicators of
emphasis. Text wrapped with one `*` or `_` will be wrapped with an
HTML `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML
`<strong>` tag. E.g., this input:
*single asterisks*
_single underscores_
**double asterisks**
__double underscores__
will produce:
<em>single asterisks</em>
<em>single underscores</em>
<strong>double asterisks</strong>
<strong>double underscores</strong>
You can use whichever style you prefer; the lone restriction is that
the same character must be used to open and close an emphasis span.
Emphasis can be used in the middle of a word:
un*frigging*believable
But if you surround an `*` or `_` with spaces, it'll be treated as a
literal asterisk or underscore.
To produce a literal asterisk or underscore at a position where it
would otherwise be used as an emphasis delimiter, you can backslash
escape it:
\*this text is surrounded by literal asterisks\*
<h3 id="code">Code</h3>
To indicate a span of code, wrap it with backtick quotes (`` ` ``).
Unlike a pre-formatted code block, a code span indicates code within a
normal paragraph. For example:
Use the `printf()` function.
will produce:
<p>Use the <code>printf()</code> function.</p>
To include a literal backtick character within a code span, you can use
multiple backticks as the opening and closing delimiters:
``There is a literal backtick (`) here.``
which will produce this:
<p><code>There is a literal backtick (`) here.</code></p>
The backtick delimiters surrounding a code span may include spaces --
one after the opening, one before the closing. This allows you to place
literal backtick characters at the beginning or end of a code span:
A single backtick in a code span: `` ` ``
A backtick-delimited string in a code span: `` `foo` ``
will produce:
<p>A single backtick in a code span: <code>`</code></p>
<p>A backtick-delimited string in a code span: <code>`foo`</code></p>
With a code span, ampersands and angle brackets are encoded as HTML
entities automatically, which makes it easy to include example HTML
tags. Markdown will turn this:
Please don't use any `<blink>` tags.
into:
<p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>
You can write this:
`&#8212;` is the decimal-encoded equivalent of `&mdash;`.
to produce:
<p><code>&amp;#8212;</code> is the decimal-encoded
equivalent of <code>&amp;mdash;</code>.</p>
<h3 id="img">Images</h3>
Admittedly, it's fairly difficult to devise a "natural" syntax for
placing images into a plain text document format.
Markdown uses an image syntax that is intended to resemble the syntax
for links, allowing for two styles: *inline* and *reference*.
Inline image syntax looks like this:
![Alt text](/path/to/img.jpg)
![Alt text](/path/to/img.jpg "Optional title")
That is:
* An exclamation mark: `!`;
* followed by a set of square brackets, containing the `alt`
attribute text for the image;
* followed by a set of parentheses, containing the URL or path to
the image, and an optional `title` attribute enclosed in double
or single quotes.
Reference-style image syntax looks like this:
![Alt text][id]
Where "id" is the name of a defined image reference. Image references
are defined using syntax identical to link references:
[id]: url/to/image "Optional title attribute"
As of this writing, Markdown has no syntax for specifying the
dimensions of an image; if this is important to you, you can simply
use regular HTML `<img>` tags.
* * *
<h2 id="misc">Miscellaneous</h2>
<h3 id="autolink">Automatic Links</h3>
Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:
<http://example.com/>
Markdown will turn this into:
<a href="http://example.com/">http://example.com/</a>
Automatic links for email addresses work similarly, except that
Markdown will also perform a bit of randomized decimal and hex
entity-encoding to help obscure your address from address-harvesting
spambots. For example, Markdown will turn this:
<address@example.com>
into something like this:
<a href="&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65;
&#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;
&#109;">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61;
&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a>
which will render in a browser as a clickable link to "address@example.com".
(This sort of entity-encoding trick will indeed fool many, if not
most, address-harvesting bots, but it definitely won't fool all of
them. It's better than nothing, but an address published in this way
will probably eventually start receiving spam.)
<h3 id="backslash">Backslash Escapes</h3>
Markdown allows you to use backslash escapes to generate literal
characters which would otherwise have special meaning in Markdown's
formatting syntax. For example, if you wanted to surround a word
with literal asterisks (instead of an HTML `<em>` tag), you can use
backslashes before the asterisks, like this:
\*literal asterisks\*
Markdown provides backslash escapes for the following characters:
\ backslash
` backtick
* asterisk
_ underscore
{} curly braces
[] square brackets
() parentheses
# hash mark
+ plus sign
- minus sign (hyphen)
. dot
! exclamation mark

View File

@ -1,9 +1,9 @@
Copyright (c) 2007, John Fraser
<http://www.attacklab.net/>
Showdown Copyright (c) 2007, John Fraser
<http://www.attacklab.net/>
All rights reserved.
Original Markdown copyright (c) 2004, John Gruber
<http://daringfireball.net/>
Original Markdown copyright (c) 2004, John Gruber
<http://daringfireball.net/>
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@ -1,7 +1,8 @@
{
"name": "showdown",
"version": "0.3.4",
"author": "John Fraser",
"version": "2.0.0-alpha1",
"description": "A Markdown to HTML converter written in Javascript",
"authors": "Estevão Santos",
"contributors": [
"John Gruber",
"John Fraser",
@ -30,18 +31,20 @@
"url": "https://github.com/coreyti/showdown/raw/master/license.txt"
}
],
"main": "./src/showdown",
"main": "./dist/showdown.js",
"scripts": {
"test": "mocha ./test/run.js"
},
"devDependencies": {
"angular": "^1.3.2",
"chai": "^1.10.0",
"grunt": "^0.4.5",
"grunt-contrib-concat": "^0.5.0",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-uglify": "^0.6.0",
"grunt-simple-mocha": "^0.4.0",
"mocha": "*",
"should": "^4.4.2"
"should": "^4.4.2",
"source-map-support": "^0.2.9"
}
}

View File

@ -1,30 +0,0 @@
Copyright (c) 2004, John Gruber
<http://daringfireball.net/>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name "Markdown" nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as
is" and any express or implied warranties, including, but not limited
to, the implied warranties of merchantability and fitness for a
particular purpose are disclaimed. In no event shall the copyright owner
or contributors be liable for any direct, indirect, incidental, special,
exemplary, or consequential damages (including, but not limited to,
procurement of substitute goods or services; loss of use, data, or
profits; or business interruption) however caused and on any theory of
liability, whether in contract, strict liability, or tort (including
negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
Reference Implementation
------------------------
This directory contains John Gruber's original Perl implementation of Markdown. Smart diff programs like Araxis Merge will be able to match up this file with markdown.pl.
A little tweaking helps. In markdown.pl:
- replace `#` with `//`
- replace `$text` with `text`
Be sure to ignore whitespace and line endings.
Note: This release of Showdown is based on `markdown1.0.2b7.pl`, but uses the HTML parser from `markdown1.0.2b2.pl`.

View File

@ -4,13 +4,14 @@
//Check if AngularJs and Showdown is defined and only load ng-Showdown if both are present
if (typeof angular !== 'undefined' && typeof Showdown !== 'undefined') {
if (typeof angular !== 'undefined' && typeof showdown !== 'undefined') {
(function (module, Showdown) {
(function (module, showdown) {
'use strict';
module
.provider('$Showdown', provider)
.directive('sdModelToHtml', ['$Showdown', markdownToHtmlDirective])
.provider('$showdown', provider)
.directive('sdModelToHtml', ['$showdown', markdownToHtmlDirective])
.filter('sdStripHtml', stripHtmlFilter);
/**
@ -20,7 +21,6 @@ if (typeof angular !== 'undefined' && typeof Showdown !== 'undefined') {
* with the user configurations.
* If the user wants to use a different configuration in a determined context, he can use the "classic" Showdown
* object instead.
*
*/
function provider() {
@ -35,9 +35,9 @@ if (typeof angular !== 'undefined' && typeof Showdown !== 'undefined') {
*
* @param {string} key Config parameter key
* @param {string} value Config parameter value
*/
*/ /* jshint validthis: true */
this.setOption = function (key, value) {
config.key = value;
config[key] = value;
return this;
};
@ -68,7 +68,7 @@ if (typeof angular !== 'undefined' && typeof Showdown !== 'undefined') {
};
function SDObject() {
var converter = new Showdown.converter(config);
var converter = new showdown.Converter(config);
/**
* Converts a markdown text into HTML
@ -103,16 +103,16 @@ if (typeof angular !== 'undefined' && typeof Showdown !== 'undefined') {
* Usage example:
* <div sd-md-to-html-model="markdownText" ></div>
*
* @param $Showdown
* @param $showdown
* @returns {*}
*/
function markdownToHtmlDirective($Showdown) {
function markdownToHtmlDirective($showdown) {
var link = function (scope, element) {
scope.$watch('model', function (newValue) {
var val;
if (typeof newValue === 'string') {
val = $Showdown.makeHtml(newValue);
val = $showdown.makeHtml(newValue);
} else {
val = typeof newValue;
}
@ -126,7 +126,7 @@ if (typeof angular !== 'undefined' && typeof Showdown !== 'undefined') {
scope: {
model: '=sdModelToHtml'
}
}
};
}
/**
@ -140,11 +140,11 @@ if (typeof angular !== 'undefined' && typeof Showdown !== 'undefined') {
};
}
})(angular.module('Showdown', []), Showdown);
})(angular.module('showdown', []), showdown);
} else {
/** TODO Since this library is opt out, maybe we should not throw an error so we can concatenate this
script with the main lib */
script with the main lib */
// throw new Error("ng-showdown was not loaded because one of it's dependencies (AngularJS or Showdown) wasn't met");
}

View File

@ -1,25 +0,0 @@
//
// Github Extension (WIP)
// ~~strike-through~~ -> <del>strike-through</del>
//
(function(){
var github = function(converter) {
return [
{
// strike-through
// NOTE: showdown already replaced "~" with "~T", so we need to adjust accordingly.
type : 'lang',
regex : '(~T){2}([^~]+)(~T){2}',
replace : function(match, prefix, content, suffix) {
return '<del>' + content + '</del>';
}
}
];
};
// Client-side export
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.github = github; }
// Server-side export
if (typeof module !== 'undefined') module.exports = github;
}());

View File

@ -1,29 +0,0 @@
//
// Google Prettify
// A showdown extension to add Google Prettify (http://code.google.com/p/google-code-prettify/)
// hints to showdown's HTML output.
//
(function(){
var prettify = function(converter) {
return [
{ type: 'output', filter: function(source){
return source.replace(/(<pre>)?<code>/gi, function(match, pre) {
if (pre) {
return '<pre class="prettyprint linenums" tabIndex="0"><code data-inner="1">';
} else {
return '<code class="prettyprint">';
}
});
}}
];
};
// Client-side export
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.prettify = prettify; }
// Server-side export
if (typeof module !== 'undefined') module.exports = prettify;
}());

View File

@ -1,106 +0,0 @@
/*global module:true*/
/*
* Basic table support with re-entrant parsing, where cell content
* can also specify markdown.
*
* Tables
* ======
*
* | Col 1 | Col 2 |
* |======== |====================================================|
* |**bold** | ![Valid XHTML] (http://w3.org/Icons/valid-xhtml10) |
* | Plain | Value |
*
*/
(function(){
var table = function(converter) {
var tables = {}, style = 'text-align:left;', filter;
tables.th = function(header){
if (header.trim() === "") { return "";}
var id = header.trim().replace(/ /g, '_').toLowerCase();
return '<th id="' + id + '" style="'+style+'">' + header + '</th>';
};
tables.td = function(cell) {
return '<td style="'+style+'">' + converter.makeHtml(cell) + '</td>';
};
tables.ths = function(){
var out = "", i = 0, hs = [].slice.apply(arguments);
for (i;i<hs.length;i+=1) {
out += tables.th(hs[i]) + '\n';
}
return out;
};
tables.tds = function(){
var out = "", i = 0, ds = [].slice.apply(arguments);
for (i;i<ds.length;i+=1) {
out += tables.td(ds[i]) + '\n';
}
return out;
};
tables.thead = function() {
var out, i = 0, hs = [].slice.apply(arguments);
out = "<thead>\n";
out += "<tr>\n";
out += tables.ths.apply(this, hs);
out += "</tr>\n";
out += "</thead>\n";
return out;
};
tables.tr = function() {
var out, i = 0, cs = [].slice.apply(arguments);
out = "<tr>\n";
out += tables.tds.apply(this, cs);
out += "</tr>\n";
return out;
};
filter = function(text) {
var i=0, lines = text.split('\n'), line, hs, rows, out = [];
for (i; i<lines.length;i+=1) {
line = lines[i];
// looks like a table heading
if (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
line = line.trim();
var tbl = [];
tbl.push('<table>');
hs = line.substring(1, line.length -1).split('|');
tbl.push(tables.thead.apply(this, hs));
line = lines[++i];
if (!line.trim().match(/^[|]{1}[-=| ]+[|]{1}$/)) {
// not a table rolling back
line = lines[--i];
}
else {
line = lines[++i];
tbl.push('<tbody>');
while (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
line = line.trim();
tbl.push(tables.tr.apply(this, line.substring(1, line.length -1).split('|')));
line = lines[++i];
}
tbl.push('</tbody>');
tbl.push('</table>');
// we are done with this table and we move along
out.push(tbl.join('\n'));
continue;
}
}
out.push(line);
}
return out.join('\n');
};
return [
{
type: 'lang',
filter: filter
}
];
};
// Client-side export
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.table = table; }
// Server-side export
if (typeof module !== 'undefined') {
module.exports = table;
}
}());

View File

@ -1,42 +0,0 @@
//
// Twitter Extension
// @username -> <a href="http://twitter.com/username">@username</a>
// #hashtag -> <a href="http://twitter.com/search/%23hashtag">#hashtag</a>
//
(function(){
var twitter = function(converter) {
return [
// @username syntax
{ type: 'lang', regex: '\\B(\\\\)?@([\\S]+)\\b', replace: function(match, leadingSlash, username) {
// Check if we matched the leading \ and return nothing changed if so
if (leadingSlash === '\\') {
return match;
} else {
return '<a href="http://twitter.com/' + username + '">@' + username + '</a>';
}
}},
// #hashtag syntax
{ type: 'lang', regex: '\\B(\\\\)?#([\\S]+)\\b', replace: function(match, leadingSlash, tag) {
// Check if we matched the leading \ and return nothing changed if so
if (leadingSlash === '\\') {
return match;
} else {
return '<a href="http://twitter.com/search/%23' + tag + '">#' + tag + '</a>';
}
}},
// Escaped @'s
{ type: 'lang', regex: '\\\\@', replace: '@' }
];
};
// Client-side export
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.twitter = twitter; }
// Server-side export
if (typeof module !== 'undefined') module.exports = twitter;
}());

98
src/helpers.js Normal file
View File

@ -0,0 +1,98 @@
/**
* Created by Estevao on 11-01-2015.
*/
function isString(a) {
return (typeof a === 'string' || a instanceof String);
}
function forEach(obj, callback) {
if (typeof obj.forEach === 'function') {
obj.forEach(callback);
} else {
var i, len = obj.length;
for (i = 0; i < len; i++) {
callback(obj[i], i, obj);
}
}
}
function isArray(a) {
return a.constructor === Array;
}
function isUndefined(value) {
return typeof value === 'undefined';
}
var escapeCharactersCallback = function (wholeMatch, m1) {
var charCodeToEscape = m1.charCodeAt(0);
return '~E' + charCodeToEscape + 'E';
};
var escapeCharacters = function (text, charsToEscape, afterBackslash) {
// First we have to escape the escape characters so that
// we can build a character class out of them
var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
if (afterBackslash) {
regexString = '\\\\' + regexString;
}
var regex = new RegExp(regexString, 'g');
text = text.replace(regex, escapeCharactersCallback);
return text;
};
if (!showdown.hasOwnProperty('helper')) {
showdown.helper = {};
}
/**
* isString helper function
* @param a
* @returns {boolean}
*/
showdown.helper.isString = isString;
/**
* ForEach helper function
* @param {*} obj
* @param callback
*/
showdown.helper.forEach = forEach;
/**
* isArray helper function
* @param {*} a
* @returns {boolean}
*/
showdown.helper.isArray = isArray;
/**
* Check if value is undefined
*
* @static
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
*/
showdown.helper.isUndefined = isUndefined;
/**
* Callback used to escape characters when passing through String.replace
* @param {string} wholeMatch
* @param {string} m1
* @returns {string}
*/
showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
/**
* Escape characters in a string
*
* @param {string} text
* @param {string} charsToEscape
* @param {boolean} afterBackslash
* @returns {XML|string|void|*}
*/
showdown.helper.escapeCharacters = escapeCharacters;

20
src/loader.js Normal file
View File

@ -0,0 +1,20 @@
/**
* Created by Estevao on 15-01-2015.
*/
var root = this;
// CommonJS/nodeJS Loader
if (typeof module !== 'undefined' && module.exports) {
module.exports = showdown;
}
// AMD Loader
else if (typeof define === 'function' && define.amd) {
define('showdown', function () {
return showdown;
});
}
// Regular Browser loader
else {
root.showdown = showdown;
}

File diff suppressed because it is too large Load Diff

145
src/showdown.js Normal file
View File

@ -0,0 +1,145 @@
/**
* Created by Tivie on 06-01-2015.
*/
// Private properties
var showdown = {},
parsers = {},
globalOptions = {
omitExtraWLInCodeBlocks: false
};
///////////////////////////////////////////////////////////////////////////
// Public API
//
/**
* helper namespace
* @type {{}}
*/
showdown.helper = {};
///////////////////////////////////////////////////////////////////////////
// API
//
// Public properties
showdown.extensions = {};
//Public methods
showdown.setOption = function (key, value) {
globalOptions[key] = value;
return this;
};
/**
* Static Method
*
* subParser(name) - Get a registered subParser
* subParser(name, func) - Register a subParser
* @param {string} name
* @param {function} [func]
* @returns {*}
*/
showdown.subParser = function (name, func) {
if (showdown.helper.isString(name)) {
if (typeof func !== 'undefined') {
parsers[name] = func;
} else {
if (parsers.hasOwnProperty(name)) {
return parsers[name];
} else {
throw Error('SubParser named ' + name + ' not registered!');
}
}
}
};
/**
*
* @param {object} [converterOptions]
* @returns {{makeHtml: Function}}
*/
showdown.Converter = function (converterOptions) {
converterOptions = converterOptions || {};
var options = globalOptions,
parserOrder = [
'detab',
'stripBlankLines',
//runLanguageExtensions,
'githubCodeBlocks',
'hashHTMLBlocks',
'stripLinkDefinitions',
'blockGamut',
'unescapeSpecialChars'
];
// Merge options
if (typeof converterOptions === 'object') {
for (var opt in converterOptions) {
if (converterOptions.hasOwnProperty(opt)) {
options[opt] = converterOptions[opt];
}
}
}
var makeHtml = function (text) {
//check if text is not falsy
if (!text) {
return text;
}
var globals = {
gHtmlBlocks: [],
gUrls: {},
gTitles: {},
gListLevel: 0
};
// attacklab: Replace ~ with ~T
// This lets us use tilde as an escape char to avoid md5 hashes
// The choice of character is arbitrary; anything that isn't
// magic in Markdown will work.
text = text.replace(/~/g, '~T');
// attacklab: Replace $ with ~D
// RegExp interprets $ as a special character
// when it's in a replacement string
text = text.replace(/\$/g, '~D');
// Standardize line endings
text = text.replace(/\r\n/g, '\n'); // DOS to Unix
text = text.replace(/\r/g, '\n'); // Mac to Unix
// Make sure text begins and ends with a couple of newlines:
text = '\n\n' + text + '\n\n';
// Run all registered parsers
for (var i = 0; i < parserOrder.length; ++i) {
var name = parserOrder[i];
text = parsers[name](text, options, globals);
}
// attacklab: Restore dollar signs
text = text.replace(/~D/g, '$$');
// attacklab: Restore tildes
text = text.replace(/~T/g, '~');
// Run output modifiers
//showdown.forEach(g_output_modifiers, function (x) {
// text = _ExecuteExtension(x, text);
//});
return text;
};
return {
makeHtml: makeHtml
};
};

136
src/subParsers/anchors.js Normal file
View File

@ -0,0 +1,136 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Turn Markdown link shortcuts into XHTML <a> tags.
*/
showdown.subParser('anchors', function (text, config, globals) {
'use strict';
var writeAnchorTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
if (showdown.helper.isUndefined(m7)) {
m7 = '';
}
wholeMatch = m1;
var linkText = m2,
linkId = m3.toLowerCase(),
url = m4,
title = m7;
if (!url) {
if (!linkId) {
// lower-case and turn embedded newlines into spaces
linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
}
url = '#' + linkId;
if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
url = globals.gUrls[linkId];
if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
title = globals.gTitles[linkId];
}
}
else {
if (wholeMatch.search(/\(\s*\)$/m) > -1) {
// Special case for explicit empty url
url = '';
} else {
return wholeMatch;
}
}
}
url = showdown.helper.escapeCharacters(url, '*_');
var result = '<a href="' + url + '"';
if (title !== '' && title !== null) {
title = title.replace(/"/g, '&quot;');
title = showdown.helper.escapeCharacters(title, '*_');
result += ' title="' + title + '"';
}
result += '>' + linkText + '</a>';
return result;
};
// First, handle reference-style links: [link text] [id]
/*
text = text.replace(/
( // wrap whole match in $1
\[
(
(?:
\[[^\]]*\] // allow brackets nested one level
|
[^\[] // or anything else
)*
)
\]
[ ]? // one optional space
(?:\n[ ]*)? // one optional newline followed by spaces
\[
(.*?) // id = $3
\]
)()()()() // pad remaining backreferences
/g,_DoAnchors_callback);
*/
text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);
//
// Next, inline-style links: [link text](url "optional title")
//
/*
text = text.replace(/
( // wrap whole match in $1
\[
(
(?:
\[[^\]]*\] // allow brackets nested one level
|
[^\[\]] // or anything else
)
)
\]
\( // literal paren
[ \t]*
() // no id, so leave $3 empty
<?(.*?)>? // href = $4
[ \t]*
( // $5
(['"]) // quote char = $6
(.*?) // Title = $7
\6 // matching quote
[ \t]* // ignore any spaces/tabs between closing quote and )
)? // title is optional
\)
)
/g,writeAnchorTag);
*/
text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag);
//
// Last, handle reference-style shortcuts: [link text]
// These must come last in case you've also got [link test][1]
// or [link test](/foo)
//
/*
text = text.replace(/
( // wrap whole match in $1
\[
([^\[\]]+) // link text = $2; can't contain '[' or ']'
\]
)()()()()() // pad rest of backreferences
/g, writeAnchorTag);
*/
text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
return text;
});

View File

@ -0,0 +1,33 @@
/**
* Created by Estevao on 12-01-2015.
*/
showdown.subParser('autoLinks', function (text) {
'use strict';
text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi, "<a href=\"$1\">$1</a>");
// Email addresses: <address@domain.foo>
/*
text = text.replace(/
<
(?:mailto:)?
(
[-.\w]+
\@
[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
)
>
/gi, _DoAutoLinks_callback());
*/
text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
function (wholeMatch, m1) {
var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1);
return showdown.subParser('encodeEmailAddress')(unescapedStr);
}
);
return text;
});

View File

@ -0,0 +1,33 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* These are all the transformations that form block-level
* tags like paragraphs, headers, and list items.
*/
showdown.subParser('blockGamut', function (text, options, globals) {
'use strict';
text = showdown.subParser('headers')(text, options, globals);
// Do Horizontal Rules:
var key = showdown.subParser('hashBlock')('<hr />', options, globals);
text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, key);
text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, key);
text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm, key);
text = showdown.subParser('lists')(text, options, globals);
text = showdown.subParser('codeBlocks')(text, options, globals);
text = showdown.subParser('blockQuotes')(text, options, globals);
// We already ran _HashHTMLBlocks() before, in Markdown(), but that
// was to escape raw HTML in the original Markdown source. This time,
// we're escaping the markup we've just created, so that we don't wrap
// <p> tags around block-level tags.
text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
text = showdown.subParser('paragraphs')(text, options, globals);
return text;
});

View File

@ -0,0 +1,50 @@
/**
* Created by Estevao on 12-01-2015.
*/
showdown.subParser('blockQuotes', function (text, options, globals) {
'use strict';
/*
text = text.replace(/
( // Wrap whole match in $1
(
^[ \t]*>[ \t]? // '>' at the start of a line
.+\n // rest of the first line
(.+\n)* // subsequent consecutive lines
\n* // blanks
)+
)
/gm, function(){...});
*/
text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
function (wholeMatch, m1) {
var bq = m1;
// attacklab: hack around Konqueror 3.5.4 bug:
// "----------bug".replace(/^-/g,"") == "bug"
bq = bq.replace(/^[ \t]*>[ \t]?/gm, '~0'); // trim one level of quoting
// attacklab: clean up hack
bq = bq.replace(/~0/g, '');
bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
bq = bq.replace(/(^|\n)/g, '$1 ');
// These leading spaces screw with <pre> content, so we need to fix that:
bq = bq.replace(
/(\s*<pre>[^\r]+?<\/pre>)/gm,
function (wholeMatch, m1) {
var pre = m1;
// attacklab: hack around Konqueror 3.5.4 bug:
pre = pre.replace(/^ /mg, '~0');
pre = pre.replace(/~0/g, '');
return pre;
});
return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
});
return text;
});

View File

@ -0,0 +1,48 @@
/**
* Created by Estevao on 12-01-2015.
*/
/**
* Process Markdown `<pre><code>` blocks.
*/
showdown.subParser('codeBlocks', function (text, options, globals) {
'use strict';
/*
text = text.replace(text,
/(?:\n\n|^)
( // $1 = the code block -- one or more lines, starting with a space/tab
(?:
(?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
.*\n+
)+
)
(\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width
/g,function(){...});
*/
// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
text += '~0';
text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
function (wholeMatch, m1, m2) {
var codeblock = m1,
nextChar = m2;
codeblock = showdown.subParser('outdent')(codeblock);
codeblock = showdown.subParser('encodeCode')(codeblock);
codeblock = showdown.subParser('detab')(codeblock);
codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
codeblock = '<pre><code>' + codeblock + '\n</code></pre>';
return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
}
);
// attacklab: strip sentinel
text = text.replace(/~0/, '');
return text;
});

View File

@ -0,0 +1,57 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
*
* * Backtick quotes are used for <code></code> spans.
*
* * You can use multiple backticks as the delimiters if you want to
* include literal backticks in the code span. So, this input:
*
* Just type ``foo `bar` baz`` at the prompt.
*
* Will translate to:
*
* <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
*
* There's no arbitrary limit to the number of backticks you
* can use as delimters. If you need three consecutive backticks
* in your code, use four for delimiters, etc.
*
* * You can use spaces to get literal backticks at the edges:
*
* ... type `` `bar` `` ...
*
* Turns to:
*
* ... type <code>`bar`</code> ...
*/
showdown.subParser('codeSpans', function (text) {
'use strict';
/*
text = text.replace(/
(^|[^\\]) // Character before opening ` can't be a backslash
(`+) // $2 = Opening run of `
( // $3 = The code block
[^\r]*?
[^`] // attacklab: work around lack of lookbehind
)
\2 // Matching closer
(?!`)
/gm, function(){...});
*/
text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
function (wholeMatch, m1, m2, m3) {
var c = m3;
c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
c = showdown.subParser('encodeCode')(c);
return m1 + '<code>' + c + '</code>';
});
return text;
});

38
src/subParsers/detab.js Normal file
View File

@ -0,0 +1,38 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Convert all tabs to spaces
*/
showdown.subParser('detab', function (text) {
'use strict';
// expand first n-1 tabs
text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width
// replace the nth with two sentinels
text = text.replace(/\t/g, '~A~B');
// use the sentinel to anchor our regex so it doesn't explode
text = text.replace(/~B(.+?)~A/g,
function (wholeMatch, m1) {
var leadingText = m1,
numSpaces = 4 - leadingText.length % 4; // g_tab_width
// there *must* be a better way to do this:
for (var i = 0; i < numSpaces; i++) {
leadingText += ' ';
}
return leadingText;
}
);
// clean up sentinels
text = text.replace(/~A/g, ' '); // g_tab_width
text = text.replace(/~B/g, '');
return text;
});

View File

@ -0,0 +1,18 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Smart processing for ampersands and angle brackets that need to be encoded.
*/
showdown.subParser('encodeAmpsAndAngles', function (text) {
'use strict';
// Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
// http://bumppo.net/projects/amputator/
text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
// Encode naked <'s
text = text.replace(/<(?![a-z\/?\$!])/gi, '&lt;');
return text;
});

View File

@ -0,0 +1,21 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Returns the string, with after processing the following backslash escape sequences.
*
* attacklab: The polite way to do this is with the new escapeCharacters() function:
*
* text = escapeCharacters(text,"\\",true);
* text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
*
* ...but we're sidestepping its use of the (slow) RegExp constructor
* as an optimization for Firefox. This function gets called a LOT.
*/
showdown.subParser('encodeBackslashEscapes', function (text) {
'use strict';
text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, showdown.helper.escapeCharactersCallback);
return text;
});

View File

@ -0,0 +1,33 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Encode/escape certain characters inside Markdown code runs.
* The point is that in code, these characters are literals,
* and lose their special Markdown meanings.
*/
showdown.subParser('encodeCode', function (text) {
'use strict';
// Encode all ampersands; HTML entities are not
// entities within a Markdown code span.
text = text.replace(/&/g, '&amp;');
// Do the angle bracket song and dance:
text = text.replace(/</g, '&lt;');
text = text.replace(/>/g, '&gt;');
// Now, escape characters that are magic in Markdown:
text = showdown.helper.escapeCharacters(text, '*_{}[]\\', false);
// jj the line above breaks this:
//---
//* Item
// 1. Subitem
// special char: *
// ---
return text;
});

View File

@ -0,0 +1,60 @@
/**
* Created by Estevao on 12-01-2015.
*/
/**
* Input: an email address, e.g. "foo@example.com"
*
* Output: the email address as a mailto link, with each character
* of the address encoded as either a decimal or hex entity, in
* the hopes of foiling most address harvesting spam bots. E.g.:
*
* <a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
* x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
* &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
*
* Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
* mailing list: <http://tinyurl.com/yu7ue>
*
*/
showdown.subParser('encodeEmailAddress', function (addr) {
'use strict';
var encode = [
function (ch) {
return '&#' + ch.charCodeAt(0) + ';';
},
function (ch) {
return '&#x' + ch.charCodeAt(0).toString(16) + ';';
},
function (ch) {
return ch;
}
];
addr = 'mailto:' + addr;
addr = addr.replace(/./g, function (ch) {
if (ch === '@') {
// this *must* be encoded. I insist.
ch = encode[Math.floor(Math.random() * 2)](ch);
} else if (ch !== ':') {
// leave ':' alone (to spot mailto: later)
var r = Math.random();
// roughly 10% raw, 45% hex, 45% dec
ch = (
r > 0.9 ? encode[2](ch) :
r > 0.45 ? encode[1](ch) :
encode[0](ch)
);
}
return ch;
});
addr = '<a href="' + addr + '">' + addr + '</a>';
addr = addr.replace(/">.+:/g, '">'); // strip the mailto: from the visible part
return addr;
});

View File

@ -0,0 +1,23 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Within tags -- meaning between < and > -- encode [\ ` * _] so they
* don't conflict with their use in Markdown for code, italics and strong.
*/
showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text) {
'use strict';
// Build a regex to find HTML tags and comments. See Friedl's
// "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
text = text.replace(regex, function (wholeMatch) {
var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, '$1`');
tag = showdown.helper.escapeCharacters(tag, '\\`*_');
return tag;
});
return text;
});

View File

@ -0,0 +1,46 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Handle github codeblocks prior to running HashHTML so that
* HTML contained within the codeblock gets escaped properly
* Example:
* ```ruby
* def hello_world(x)
* puts "Hello, #{x}"
* end
* ```
*/
showdown.subParser('githubCodeBlocks', function (text, options, globals) {
'use strict';
text += '~0';
text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,
function (wholeMatch, m1, m2) {
var language = m1,
codeblock = m2,
end = '\n';
if (options.omitExtraWLInCodeBlocks) {
end = '';
}
codeblock = showdown.subParser('encodeCode')(codeblock);
codeblock = showdown.subParser('detab')(codeblock);
codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
codeblock = '<pre><code' + (language ? ' class="' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
return showdown.subParser('hashBlock')(codeblock, options, globals);
}
);
// attacklab: strip sentinel
text = text.replace(/~0/, '');
return text;
});

View File

@ -0,0 +1,9 @@
/**
* Created by Estevao on 11-01-2015.
*/
showdown.subParser('hashBlock', function (text, options, globals) {
'use strict';
text = text.replace(/(^\n+|\n+$)/g, '');
return '\n\n~K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
});

View File

@ -0,0 +1,23 @@
/**
* Created by Estevao on 11-01-2015.
*/
showdown.subParser('hashElement', function (text, options, globals) {
'use strict';
return function (wholeMatch, m1) {
var blockText = m1;
// Undo double lines
blockText = blockText.replace(/\n\n/g, '\n');
blockText = blockText.replace(/^\n/, '');
// strip trailing blank lines
blockText = blockText.replace(/\n+$/g, '');
// Replace the element text with a marker ("~KxK" where x is its key)
blockText = '\n\n~K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
return blockText;
};
});

View File

@ -0,0 +1,131 @@
/**
* Created by Estevao on 11-01-2015.
*/
showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
'use strict';
// attacklab: Double up blank lines to reduce lookaround
text = text.replace(/\n/g, '\n\n');
// Hashify HTML blocks:
// We only want to do this for block-level HTML tags, such as headers,
// lists, and tables. That's because we still want to wrap <p>s around
// "paragraphs" that are wrapped in non-block-level tags, such as anchors,
// phrase emphasis, and spans. The list of tags we're looking for is
// hard-coded:
//var block_tags_a = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside';
//var block_tags_b = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside';
// First, look for nested blocks, e.g.:
// <div>
// <div>
// tags for inner block must be indented.
// </div>
// </div>
//
// The outermost tags must start at the left margin for this to match, and
// the inner nested divs must be indented.
// We need to do this before the next, more liberal match, because the next
// match will start at the first `<div>` and stop at the first `</div>`.
// attacklab: This regex can be expensive when it fails.
/*
var text = text.replace(/
( // save in $1
^ // start of line (with /m)
<($block_tags_a) // start tag = $2
\b // word break
// attacklab: hack around khtml/pcre bug...
[^\r]*?\n // any number of lines, minimally matching
</\2> // the matching end tag
[ \t]* // trailing spaces/tabs
(?=\n+) // followed by a newline
) // attacklab: there are sentinel newlines at end of document
/gm,function(){...}};
*/
text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, showdown.subParser('hashElement')(text, options, globals));
//
// Now match more liberally, simply from `\n<tag>` to `</tag>\n`
//
/*
var text = text.replace(/
( // save in $1
^ // start of line (with /m)
<($block_tags_b) // start tag = $2
\b // word break
// attacklab: hack around khtml/pcre bug...
[^\r]*? // any number of lines, minimally matching
</\2> // the matching end tag
[ \t]* // trailing spaces/tabs
(?=\n+) // followed by a newline
) // attacklab: there are sentinel newlines at end of document
/gm,function(){...}};
*/
text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm, showdown.subParser('hashElement')(text, options, globals));
// Special case just for <hr />. It was easier to make a special case than
// to make the other regex more complicated.
/*
text = text.replace(/
( // save in $1
\n\n // Starting after a blank line
[ ]{0,3}
(<(hr) // start tag = $2
\b // word break
([^<>])*? //
\/?>) // the matching end tag
[ \t]*
(?=\n{2,}) // followed by a blank line
)
/g,showdown.subParser('hashElement')(text, options, globals));
*/
text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, showdown.subParser('hashElement')(text, options, globals));
// Special case for standalone HTML comments:
/*
text = text.replace(/
( // save in $1
\n\n // Starting after a blank line
[ ]{0,3} // attacklab: g_tab_width - 1
<!
(--[^\r]*?--\s*)+
>
[ \t]*
(?=\n{2,}) // followed by a blank line
)
/g,showdown.subParser('hashElement')(text, options, globals));
*/
text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g, showdown.subParser('hashElement')(text, options, globals));
// PHP and ASP-style processor instructions (<?...?> and <%...%>)
/*
text = text.replace(/
(?:
\n\n // Starting after a blank line
)
( // save in $1
[ ]{0,3} // attacklab: g_tab_width - 1
(?:
<([?%]) // $2
[^\r]*?
\2>
)
[ \t]*
(?=\n{2,}) // followed by a blank line
)
/g,showdown.subParser('hashElement')(text, options, globals));
*/
text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, showdown.subParser('hashElement')(text, options, globals));
// attacklab: Undo double lines (see comment at top of this function)
text = text.replace(/\n\n/g, '\n');
return text;
});

59
src/subParsers/headers.js Normal file
View File

@ -0,0 +1,59 @@
/**
* Created by Estevao on 11-01-2015.
*/
showdown.subParser('headers', function (text, options, globals) {
'use strict';
// Set text-style headers:
// Header 1
// ========
//
// Header 2
// --------
//
text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
function (wholeMatch, m1) {
return showdown.subParser('hashBlock')('<h1 id="' + headerId(m1) + '">' +
showdown.subParser('spanGamut')(m1, options, globals) + '</h1>', options, globals);
});
text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
function (matchFound, m1) {
return showdown.subParser('hashBlock')('<h2 id="' + headerId(m1) + '">' +
showdown.subParser('spanGamut')(m1, options, globals) + '</h2>', options, globals);
});
// atx-style headers:
// # Header 1
// ## Header 2
// ## Header 2 with closing hashes ##
// ...
// ###### Header 6
//
/*
text = text.replace(/
^(\#{1,6}) // $1 = string of #'s
[ \t]*
(.+?) // $2 = Header text
[ \t]*
\#* // optional closing #'s (not counted)
\n+
/gm, function() {...});
*/
text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
function (wholeMatch, m1, m2) {
var span = showdown.subParser('spanGamut')(m2, options, globals),
header = '<h' + m1.length + ' id="' + headerId(m2) + '">' + span + '</h' + m1.length + '>';
return showdown.subParser('hashBlock')(header, options, globals);
});
function headerId(m) {
return m.replace(/[^\w]/g, '').toLowerCase();
}
return text;
});

109
src/subParsers/images.js Normal file
View File

@ -0,0 +1,109 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Turn Markdown image shortcuts into <img> tags.
*/
showdown.subParser('images', function (text, options, globals) {
'use strict';
var writeImageTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
wholeMatch = m1;
var altText = m2,
linkId = m3.toLowerCase(),
url = m4,
title = m7,
gUrls = globals.gUrls,
gTitles = globals.gTitles;
if (!title) {
title = '';
}
if (url === '' || url === null) {
if (linkId === '' || linkId === null) {
// lower-case and turn embedded newlines into spaces
linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
}
url = '#' + linkId;
if (typeof gUrls[linkId] !== 'undefined') {
url = gUrls[linkId];
if (typeof gTitles[linkId] !== 'undefined') {
title = gTitles[linkId];
}
}
else {
return wholeMatch;
}
}
altText = altText.replace(/"/g, '&quot;');
url = showdown.helper.escapeCharacters(url, '*_');
var result = '<img src="' + url + '" alt="' + altText + '"';
// attacklab: Markdown.pl adds empty title attributes to images.
// Replicate this bug.
//if (title != "") {
title = title.replace(/"/g, '&quot;');
title = escapeCharacters(title, '*_');
result += ' title="' + title + '"';
//}
result += ' />';
return result;
};
// First, handle reference-style labeled images: ![alt text][id]
/*
text = text.replace(/
( // wrap whole match in $1
!\[
(.*?) // alt text = $2
\]
[ ]? // one optional space
(?:\n[ ]*)? // one optional newline followed by spaces
\[
(.*?) // id = $3
\]
)()()()() // pad rest of backreferences
/g,writeImageTag);
*/
text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
// Next, handle inline images: ![alt text](url "optional title")
// Don't forget: encode * and _
/*
text = text.replace(/
( // wrap whole match in $1
!\[
(.*?) // alt text = $2
\]
\s? // One optional whitespace character
\( // literal paren
[ \t]*
() // no id, so leave $3 empty
<?(\S+?)>? // src url = $4
[ \t]*
( // $5
(['"]) // quote char = $6
(.*?) // title = $7
\6 // matching quote
[ \t]*
)? // title is optional
\)
)
/g,writeImageTag);
*/
text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);
return text;
});

View File

@ -0,0 +1,15 @@
/**
* Created by Estevao on 12-01-2015.
*/
showdown.subParser('italicsAndBold', function (text) {
'use strict';
// <strong> must go first:
text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,
'<strong>$2</strong>');
text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
'<em>$2</em>');
return text;
});

150
src/subParsers/lists.js Normal file
View File

@ -0,0 +1,150 @@
/**
* Created by Estevao on 12-01-2015.
*/
/**
* Form HTML ordered (numbered) and unordered (bulleted) lists.
*/
showdown.subParser('lists', function (text, options, globals) {
'use strict';
/**
* Process the contents of a single ordered or unordered list, splitting it
* into individual list items.
* @param listStr
* @returns {string|*}
*/
var processListItems = function (listStr) {
// The $g_list_level global keeps track of when we're inside a list.
// Each time we enter a list, we increment it; when we leave a list,
// we decrement. If it's zero, we're not in a list anymore.
//
// We do this because when we're not inside a list, we want to treat
// something like this:
//
// I recommend upgrading to version
// 8. Oops, now this line is treated
// as a sub-list.
//
// As a single paragraph, despite the fact that the second line starts
// with a digit-period-space sequence.
//
// Whereas when we're inside a list (or sub-list), that line will be
// treated as the start of a sub-list. What a kludge, huh? This is
// an aspect of Markdown's syntax that's hard to parse perfectly
// without resorting to mind-reading. Perhaps the solution is to
// change the syntax rules such that sub-lists must start with a
// starting cardinal number; e.g. "1." or "a.".
globals.gListLevel++;
// trim trailing blank lines:
listStr = listStr.replace(/\n{2,}$/, '\n');
// attacklab: add sentinel to emulate \z
listStr += '~0';
/*
list_str = list_str.replace(/
(\n)? // leading line = $1
(^[ \t]*) // leading whitespace = $2
([*+-]|\d+[.]) [ \t]+ // list marker = $3
([^\r]+? // list item text = $4
(\n{1,2}))
(?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
/gm, function(){...});
*/
listStr = listStr.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
function (wholeMatch, m1, m2, m3, m4) {
var item = showdown.subParser('outdent')(m4, options, globals);
//m1 - LeadingLine
if (m1 || (item.search(/\n{2,}/) > -1)) {
item = showdown.subParser('blockGamut')(item, options, globals);
} else {
// Recursion for sub-lists:
item = showdown.subParser('lists')(item, options, globals);
item = item.replace(/\n$/, ''); // chomp(item)
item = showdown.subParser('spanGamut')(item, options, globals);
}
return '<li>' + item + '</li>\n';
}
);
// attacklab: strip sentinel
listStr = listStr.replace(/~0/g, '');
globals.gListLevel--;
return listStr;
};
// attacklab: add sentinel to hack around khtml/safari bug:
// http://bugs.webkit.org/show_bug.cgi?id=11231
text += '~0';
// Re-usable pattern to match any entirel ul or ol list:
/*
var whole_list = /
( // $1 = whole list
( // $2
[ ]{0,3} // attacklab: g_tab_width - 1
([*+-]|\d+[.]) // $3 = first list item marker
[ \t]+
)
[^\r]+?
( // $4
~0 // sentinel for workaround; should be $
|
\n{2,}
(?=\S)
(?! // Negative lookahead for another list item marker
[ \t]*
(?:[*+-]|\d+[.])[ \t]+
)
)
)/g
*/
var wholeList = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
if (globals.gListLevel) {
text = text.replace(wholeList, function (wholeMatch, m1, m2) {
var list = m1,
listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
// Turn double returns into triple returns, so that we can make a
// paragraph for the last item in a list, if necessary:
list = list.replace(/\n{2,}/g, '\n\n\n');
var result = processListItems(list);
// Trim any trailing whitespace, to put the closing `</$list_type>`
// up on the preceding line, to get it past the current stupid
// HTML block parser. This is a hack to work around the terrible
// hack that is the HTML block parser.
result = result.replace(/\s+$/, '');
result = '<' + listType + '>' + result + '</' + listType + '>\n';
return result;
});
} else {
wholeList = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
text = text.replace(wholeList, function(wholeMatch,m1,m2,m3) {
// Turn double returns into triple returns, so that we can make a
// paragraph for the last item in a list, if necessary:
var list = m2.replace(/\n{2,}/g, '\n\n\n'),
listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol',
result = processListItems(list);
return m1 + '<' + listType + '>\n' + result + '</' + listType + '>\n';
});
}
// attacklab: strip sentinel
text = text.replace(/~0/, '');
return text;
});

19
src/subParsers/outdent.js Normal file
View File

@ -0,0 +1,19 @@
/**
* Created by Estevao on 12-01-2015.
*/
/**
* Remove one level of line-leading tabs or spaces
*/
showdown.subParser('outdent', function (text) {
'use strict';
// attacklab: hack around Konqueror 3.5.4 bug:
// "----------bug".replace(/^-/g,"") == "bug"
text = text.replace(/^(\t|[ ]{1,4})/gm, '~0'); // attacklab: g_tab_width
// attacklab: clean up hack
text = text.replace(/~0/g, '');
return text;
});

View File

@ -0,0 +1,47 @@
/**
* Created by Estevao on 12-01-2015.
*/
/**
*
*/
showdown.subParser('paragraphs', function (text, options, globals) {
'use strict';
// Strip leading and trailing lines:
text = text.replace(/^\n+/g, '');
text = text.replace(/\n+$/g, '');
var grafs = text.split(/\n{2,}/g),
grafsOut = [];
/** Wrap <p> tags. */
var end = grafs.length;
for (var i = 0; i < end; i++) {
var str = grafs[i];
// if this is an HTML marker, copy it
if (str.search(/~K(\d+)K/g) >= 0) {
grafsOut.push(str);
}
else if (str.search(/\S/) >= 0) {
str = showdown.subParser('spanGamut')(str, options, globals);
str = str.replace(/^([ \t]*)/g, '<p>');
str += '</p>';
grafsOut.push(str);
}
}
/** Unhashify HTML blocks */
end = grafsOut.length;
for (i = 0; i < end; i++) {
// if this is a marker for an html block...
while (grafsOut[i].search(/~K(\d+)K/) >= 0) {
var blockText = globals.gHtmlBlocks[RegExp.$1];
blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
grafsOut[i] = grafsOut[i].replace(/~K\d+K/, blockText);
}
}
return grafsOut.join('\n\n');
});

View File

@ -0,0 +1,34 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* These are all the transformations that occur *within* block-level
* tags like paragraphs, headers, and list items.
*/
showdown.subParser('spanGamut', function (text, options, globals) {
'use strict';
text = showdown.subParser('codeSpans')(text, options, globals);
text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
// Process anchor and image tags. Images must come first,
// because ![foo][f] looks like an anchor.
text = showdown.subParser('images')(text, options, globals);
text = showdown.subParser('anchors')(text, options, globals);
// Make links out of things like `<http://example.com/>`
// Must come after _DoAnchors(), because you can use < and >
// delimiters in inline links like [this](<url>).
text = showdown.subParser('autoLinks')(text, options, globals);
text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
text = showdown.subParser('italicsAndBold')(text, options, globals);
// Do hard breaks:
text = text.replace(/ +\n/g, ' <br />\n');
return text;
});

View File

@ -0,0 +1,14 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Strip any lines consisting only of spaces and tabs.
* This makes subsequent regexs easier to write, because we can
* match consecutive blank lines with /\n+/ instead of something
* contorted like /[ \t]*\n+/
*/
showdown.subParser('stripBlankLines', function (text) {
'use strict';
return text.replace(/^[ \t]+$/mg, '');
});

View File

@ -0,0 +1,57 @@
/**
* Created by Estevao on 11-01-2015.
*/
/**
* Strips link definitions from text, stores the URLs and titles in
* hash references.
* Link defs are in the form: ^[id]: url "optional title"
*
* ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1
* [ \t]*
* \n? // maybe *one* newline
* [ \t]*
* <?(\S+?)>? // url = $2
* [ \t]*
* \n? // maybe one newline
* [ \t]*
* (?:
* (\n*) // any lines skipped = $3 attacklab: lookbehind removed
* ["(]
* (.+?) // title = $4
* [")]
* [ \t]*
* )? // title is optional
* (?:\n+|$)
* /gm,
* function(){...});
*
*/
showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
'use strict';
// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
text += '~0';
text = text.replace(/^[ ]{0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm,
function (wholeMatch, m1, m2, m3, m4) {
m1 = m1.toLowerCase();
globals.gUrls[m1] = showdown.subParser('encodeAmpsAndAngles')(m2); // Link IDs are case-insensitive
if (m3) {
// Oops, found blank lines, so it's not a title.
// Put back the parenthetical statement we stole.
return m3 + m4;
} else if (m4) {
globals.gTitles[m1] = m4.replace(/"/g, '&quot;');
}
// Completely remove the definition from the text
return '';
}
);
// attacklab: strip sentinel
text = text.replace(/~0/, '');
return text;
});

View File

@ -0,0 +1,18 @@
/**
* Created by Estevao on 12-01-2015.
*/
/**
* Swap back in all the special characters we've hidden.
*/
showdown.subParser('unescapeSpecialChars', function (text) {
'use strict';
text = text.replace(/~E(\d+)E/g,
function (wholeMatch, m1) {
var charCodeToReplace = parseInt(m1);
return String.fromCharCode(charCodeToReplace);
}
);
return text;
});

View File

@ -1,5 +1,4 @@
<p>This is <a href="http://example.com/" title="Optional Title Here">an example</a> reference-style link.
This is <a href="http://example.com/" title="Optional Title Here">another</a> reference-style link.
This is <a href="http://example.com/" title="Optional Title Here">a third</a> reference-style link.
This is <a href="http://example.com/" title="Optional Title Here">a fourth</a> reference-style link.</p>
This is <a href="http://example.com/" title="Optional Title Here">a fourth</a> reference-style link.</p>

View File

@ -1,2 +1 @@
<p><a href="http://example.com/">http://example.com/</a></p>
<p><a href="http://example.com/">http://example.com/</a></p>

View File

@ -2,4 +2,4 @@
<p>This is a multi line blockquote test</p>
<p>With more than one line.</p>
</blockquote>
</blockquote>

View File

@ -1,5 +1,4 @@
<p>This is some HTML:</p>
<pre><code>&lt;h1&gt;Heading&lt;/h1&gt;
</code></pre>
</code></pre>

View File

@ -1,5 +1,4 @@
<p>This is a normal paragraph:</p>
<pre><code>This is a code block.
</code></pre>
</code></pre>

View File

@ -1,5 +1,4 @@
<ul>
<li><p>Bird</p></li>
<li><p>Magic</p></li>
</ul>
</ul>

View File

@ -1,8 +1,7 @@
<p><em>important</em></p>
<p><em>important</em></p>
<p>this mid<em>important</em>sentence</p>
<p>*not important*</p>
<p>*not important*</p>

View File

@ -1 +1 @@
<p>It happened in 1986. What a great season.</p>
<p>It happened in 1986. What a great season.</p>

View File

@ -1,4 +1,3 @@
<p>These should all be escaped:</p>
<p>\</p>
@ -29,4 +28,4 @@
<p>.</p>
<p>!</p>
<p>!</p>

View File

@ -1,7 +1,6 @@
<pre><code>function MyFunc(a) {
// ...
}
</code></pre>
<p>That is some code!</p>
<p>That is some code!</p>

View File

@ -1,5 +1,3 @@
<p>Define a function in javascript:</p>
<pre><code>function MyFunc(a) {
@ -10,4 +8,4 @@
<p>And some HTML</p>
<pre><code class="html">&lt;div&gt;HTML!&lt;/div&gt;
</code></pre>
</code></pre>

View File

@ -1,4 +1,3 @@
<pre><code>code can go here
this is rendered on a second line
</code></pre>
</code></pre>

View File

@ -1 +1 @@
<h1 id="thisisanh1">This is an H1</h1>
<h1 id="thisisanh1">This is an H1</h1>

View File

@ -1 +1 @@
<h1 id="thisisanh1">This is an H1</h1>
<h1 id="thisisanh1">This is an H1</h1>

View File

@ -1 +1 @@
<h1 id="thisisanh1">This is an H1</h1>
<h1 id="thisisanh1">This is an H1</h1>

View File

@ -1 +1 @@
<h2 id="thisisanh2">This is an H2</h2>
<h2 id="thisisanh2">This is an H2</h2>

View File

@ -1 +1 @@
<h2 id="thisisanh2">This is an H2</h2>
<h2 id="thisisanh2">This is an H2</h2>

View File

@ -1 +1 @@
<h2 id="thisisanh2">This is an H2</h2>
<h2 id="thisisanh2">This is an H2</h2>

View File

@ -1 +1 @@
<h3 id="thisisanh3">This is an H3</h3>
<h3 id="thisisanh3">This is an H3</h3>

View File

@ -1 +1 @@
<h3 id="thisisanh3">This is an H3</h3>
<h3 id="thisisanh3">This is an H3</h3>

View File

@ -1 +1 @@
<h4 id="thisisanh4">This is an H4</h4>
<h4 id="thisisanh4">This is an H4</h4>

View File

@ -1 +1 @@
<h5 id="thisisanh5">This is an H5</h5>
<h5 id="thisisanh5">This is an H5</h5>

View File

@ -1 +1 @@
<h6 id="thisisanh6">This is an H6</h6>
<h6 id="thisisanh6">This is an H6</h6>

View File

@ -1,4 +1,3 @@
<hr />
<hr />
@ -7,4 +6,4 @@
<hr />
<hr />
<hr />

View File

@ -1,4 +1,3 @@
<p>These HTML5 tags should pass through just fine.</p>
<section>hello</section>
@ -20,4 +19,4 @@ me</article>
ignore me
</aside>
<p>the end</p>
<p>the end</p>

View File

@ -1,6 +1,5 @@
<p><img src="/path/to/img.jpg" alt="Alt text" title="" /></p>
<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title" /></p>
<p><img src="url/to/image" alt="Alt text" title="Optional title attribute" /></p>
<p><img src="url/to/image" alt="Alt text" title="Optional title attribute" /></p>

View File

@ -1,2 +1 @@
<p>Search the web at <a href="http://google.com/">Google</a> or <a href="http://daringfireball.net/">Daring Fireball</a>.</p>
<p>Search the web at <a href="http://google.com/">Google</a> or <a href="http://daringfireball.net/">Daring Fireball</a>.</p>

View File

@ -1,4 +1,3 @@
<p>This is <a href="http://example.com/" title="Title">an example</a> inline link.</p>
<p><a href="http://example.net/">This link</a> has no title attribute.</p>
<p><a href="http://example.net/">This link</a> has no title attribute.</p>

View File

@ -1,4 +1,3 @@
<p>Create a new <code>function</code>.</p>
<p>Use the backtick in MySQL syntax <code>SELECT `column` FROM whatever</code>.</p>
@ -9,4 +8,4 @@
<p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>
<p><code>&amp;#8212;</code> is the decimal-encoded equivalent of <code>&amp;mdash;</code>.</p>
<p><code>&amp;#8212;</code> is the decimal-encoded equivalent of <code>&amp;mdash;</code>.</p>

View File

@ -1,3 +1,2 @@
<p>Hello.this_is_a_variable
and.this.is.another_one</p>
and.this.is.another_one</p>

View File

@ -1,6 +1,5 @@
<style>
p { line-height: 20px; }
</style>
<p>An exciting sentence.</p>
<p>An exciting sentence.</p>

View File

@ -2,4 +2,4 @@
<p>This is a multi line blockquote test</p>
<p>With more than one line.</p>
</blockquote>
</blockquote>

View File

@ -5,4 +5,4 @@
<p>This is a blockquote
inside a list item.</p>
</blockquote></li>
</ul>
</ul>

Some files were not shown because too many files have changed in this diff Show More