praxis 0.13.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +15 -2
- data/CHANGELOG.md +54 -1
- data/bin/praxis +49 -2
- data/lib/api_browser/Gruntfile.js +247 -90
- data/lib/api_browser/app/bower_components/angular-mocks/.bower.json +19 -0
- data/lib/api_browser/app/bower_components/angular-mocks/README.md +57 -0
- data/lib/api_browser/app/bower_components/angular-mocks/angular-mocks.js +2193 -0
- data/lib/api_browser/app/bower_components/angular-mocks/bower.json +9 -0
- data/lib/api_browser/app/bower_components/angular-mocks/package.json +27 -0
- data/lib/api_browser/app/bower_components/angular/.bower.json +6 -5
- data/lib/api_browser/app/bower_components/angular/README.md +23 -4
- data/lib/api_browser/app/bower_components/angular/angular-csp.css +6 -0
- data/lib/api_browser/app/bower_components/angular/angular.js +2287 -1597
- data/lib/api_browser/app/bower_components/angular/angular.min.js +212 -205
- data/lib/api_browser/app/bower_components/angular/angular.min.js.gzip +0 -0
- data/lib/api_browser/app/bower_components/angular/angular.min.js.map +3 -3
- data/lib/api_browser/app/bower_components/angular/bower.json +2 -1
- data/lib/api_browser/app/bower_components/angular/package.json +25 -0
- data/lib/api_browser/app/bower_components/showdown/.bower.json +39 -0
- data/lib/api_browser/app/bower_components/showdown/.jshintignore +2 -0
- data/lib/api_browser/app/bower_components/showdown/.travis.yml +8 -0
- data/lib/api_browser/app/bower_components/showdown/Gruntfile.js +100 -0
- data/lib/api_browser/app/bower_components/showdown/README.md +317 -0
- data/lib/api_browser/app/bower_components/showdown/bower.json +26 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.js +1606 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/Showdown.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/github.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/github.min.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/prettify.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/prettify.min.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/table.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/table.min.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/twitter.min.js +2 -0
- data/lib/api_browser/app/bower_components/showdown/compressed/extensions/twitter.min.js.map +1 -0
- data/lib/api_browser/app/bower_components/showdown/license.txt +34 -0
- data/lib/api_browser/app/bower_components/showdown/package.json +47 -0
- data/lib/api_browser/app/bower_components/showdown/src/extensions/github.js +25 -0
- data/lib/api_browser/app/bower_components/showdown/src/extensions/prettify.js +29 -0
- data/lib/api_browser/app/bower_components/showdown/src/extensions/table.js +106 -0
- data/lib/api_browser/app/bower_components/showdown/src/extensions/twitter.js +42 -0
- data/lib/api_browser/app/bower_components/showdown/src/ng-showdown.js +150 -0
- data/lib/api_browser/app/bower_components/showdown/src/showdown.js +1454 -0
- data/lib/api_browser/app/index.html +6 -4
- data/lib/api_browser/app/js/app.js +1 -2
- data/lib/api_browser/app/js/controllers/action.js +4 -4
- data/lib/api_browser/app/js/controllers/controller.js +1 -1
- data/lib/api_browser/app/js/controllers/menu.js +5 -3
- data/lib/api_browser/app/js/controllers/type.js +5 -5
- data/lib/api_browser/app/js/directives/attribute_description.js +5 -5
- data/lib/api_browser/app/js/directives/attribute_table.js +1 -1
- data/lib/api_browser/app/js/directives/attribute_table_row.js +2 -2
- data/lib/api_browser/app/js/directives/no_container.js +1 -1
- data/lib/api_browser/app/js/directives/request_body.js +5 -5
- data/lib/api_browser/app/js/directives/request_headers.js +3 -6
- data/lib/api_browser/app/js/directives/request_parameters.js +3 -6
- data/lib/api_browser/app/js/directives/type_label.js +4 -5
- data/lib/api_browser/app/js/factories/Documentation.js +4 -4
- data/lib/api_browser/app/js/factories/PayloadTemplates.js +2 -2
- data/lib/api_browser/app/js/factories/TypeTemplates.js +3 -3
- data/lib/api_browser/app/js/filters/markdown.js +6 -0
- data/lib/api_browser/app/js/filters/resource_name.js +2 -2
- data/lib/api_browser/app/sass/modules/_header.scss +2 -7
- data/lib/api_browser/app/sass/{main.scss → praxis.scss} +0 -0
- data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +370 -367
- data/lib/api_browser/app/views/action.html +2 -2
- data/lib/api_browser/app/views/controller.html +2 -2
- data/lib/api_browser/app/views/directives/attribute_description.html +1 -1
- data/lib/api_browser/app/views/layout.html +2 -11
- data/lib/api_browser/app/views/navbar.html +9 -0
- data/lib/api_browser/app/views/resource/_actions.html +1 -1
- data/lib/api_browser/app/views/type.html +2 -2
- data/lib/api_browser/app/views/type/_details.html +2 -1
- data/lib/api_browser/bower.json +5 -0
- data/lib/api_browser/package.json +18 -7
- data/lib/praxis.rb +8 -3
- data/lib/praxis/action_definition.rb +28 -6
- data/lib/praxis/api_definition.rb +30 -2
- data/lib/praxis/api_general_info.rb +36 -0
- data/lib/praxis/bootloader.rb +1 -0
- data/lib/praxis/collection.rb +34 -0
- data/lib/praxis/controller.rb +7 -0
- data/lib/praxis/dispatcher.rb +3 -0
- data/lib/praxis/links.rb +2 -8
- data/lib/praxis/media_type.rb +6 -24
- data/lib/praxis/media_type_collection.rb +6 -2
- data/lib/praxis/plugin_concern.rb +2 -1
- data/lib/praxis/request.rb +24 -15
- data/lib/praxis/request_stages/request_stage.rb +19 -4
- data/lib/praxis/request_stages/validate_params_and_headers.rb +1 -1
- data/lib/praxis/request_stages/validate_payload.rb +1 -1
- data/lib/praxis/resource_definition.rb +45 -10
- data/lib/praxis/response_definition.rb +46 -27
- data/lib/praxis/restful_doc_generator.rb +94 -7
- data/lib/praxis/simple_media_type.rb +2 -9
- data/lib/praxis/stage.rb +1 -4
- data/lib/praxis/tasks/api_docs.rb +51 -19
- data/lib/praxis/tasks/routes.rb +19 -15
- data/lib/praxis/types/media_type_common.rb +31 -0
- data/lib/praxis/types/multipart.rb +4 -4
- data/lib/praxis/version.rb +1 -1
- data/praxis.gemspec +2 -2
- data/spec/api_browser/factories/documentation_spec.js +50 -0
- data/spec/api_browser/filters/attribute_name_spec.js +23 -0
- data/spec/functional_spec.rb +62 -10
- data/spec/praxis/action_definition_spec.rb +12 -4
- data/spec/praxis/api_definition_spec.rb +159 -0
- data/spec/praxis/api_general_info_spec.rb +36 -0
- data/spec/praxis/bootloader_spec.rb +10 -1
- data/spec/praxis/media_type_collection_spec.rb +46 -53
- data/spec/praxis/media_type_spec.rb +6 -6
- data/spec/praxis/request_stage_spec.rb +7 -2
- data/spec/praxis/request_stages_validate_spec.rb +12 -7
- data/spec/praxis/resource_definition_spec.rb +62 -0
- data/spec/praxis/response_definition_spec.rb +26 -16
- data/spec/praxis/stage_spec.rb +4 -8
- data/spec/praxis/types/collection_spec.rb +144 -0
- data/spec/spec_app/app/controllers/instances.rb +8 -2
- data/spec/spec_app/design/api.rb +11 -0
- data/spec/spec_app/design/media_types/instance.rb +12 -0
- data/spec/spec_app/design/media_types/volume.rb +9 -2
- data/spec/spec_app/design/media_types/volume_snapshot.rb +9 -6
- data/spec/spec_app/design/resources/instances.rb +25 -10
- data/spec/support/spec_media_types.rb +1 -1
- data/spec/support/spec_resource_definitions.rb +2 -0
- data/tasks/thor/app.rb +15 -10
- data/tasks/thor/example.rb +115 -115
- data/tasks/thor/templates/generator/empty_app/.gitignore +2 -0
- data/tasks/thor/templates/generator/empty_app/docs/app.js +1 -0
- data/tasks/thor/templates/generator/empty_app/docs/styles.scss +3 -0
- metadata +50 -9
- data/lib/api_browser/app/css/main.css +0 -4511
- data/lib/praxis/types/collection.rb +0 -17
@@ -0,0 +1,39 @@
|
|
1
|
+
{
|
2
|
+
"name": "showdown",
|
3
|
+
"description": "JavaScript port of Markdown",
|
4
|
+
"homepage": "https://github.com/showdownjs/showdown",
|
5
|
+
"authors": [
|
6
|
+
"John Fraser",
|
7
|
+
"Corey Innis (https://github.com/coreyti)",
|
8
|
+
"Pascal Deschênes (https://github.com/pdeschen)",
|
9
|
+
"Estevão Santos (https://github.com/tivie)"
|
10
|
+
],
|
11
|
+
"main": [
|
12
|
+
"src/showdown.js"
|
13
|
+
],
|
14
|
+
"ignore": [
|
15
|
+
".jshintrc",
|
16
|
+
"perlMarkdown/*"
|
17
|
+
],
|
18
|
+
"repository": {
|
19
|
+
"type": "git",
|
20
|
+
"url": "https://github.com/showdownjs/showdown.git"
|
21
|
+
},
|
22
|
+
"keywords": [
|
23
|
+
"markdown",
|
24
|
+
"md",
|
25
|
+
"mdown"
|
26
|
+
],
|
27
|
+
"license": "https://github.com/showdownjs/showdown/blob/master/license.txt",
|
28
|
+
"version": "0.4.0",
|
29
|
+
"_release": "0.4.0",
|
30
|
+
"_resolution": {
|
31
|
+
"type": "version",
|
32
|
+
"tag": "0.4.0",
|
33
|
+
"commit": "e7a4a4084257d788b7c039c2252d9e00eb749e41"
|
34
|
+
},
|
35
|
+
"_source": "git://github.com/showdownjs/showdown.git",
|
36
|
+
"_target": "~0.4.0",
|
37
|
+
"_originalSource": "showdown",
|
38
|
+
"_direct": true
|
39
|
+
}
|
@@ -0,0 +1,100 @@
|
|
1
|
+
/**
|
2
|
+
* Created by Tivie on 12-11-2014.
|
3
|
+
*/
|
4
|
+
|
5
|
+
module.exports = function (grunt) {
|
6
|
+
|
7
|
+
// Project configuration.
|
8
|
+
grunt.initConfig({
|
9
|
+
pkg: grunt.file.readJSON('package.json'),
|
10
|
+
concat: {
|
11
|
+
options: {
|
12
|
+
separator: ';',
|
13
|
+
sourceMap: true
|
14
|
+
},
|
15
|
+
dist: {
|
16
|
+
src: ['src/showdown.js', 'src/*.js'],
|
17
|
+
dest: 'compressed/<%= pkg.name %>.js'
|
18
|
+
},
|
19
|
+
github_ext: {
|
20
|
+
src: ['src/extensions/github.js'],
|
21
|
+
dest: 'compressed/extensions/github.min.js'
|
22
|
+
},
|
23
|
+
prettify_ext: {
|
24
|
+
src: ['src/extensions/prettify.js'],
|
25
|
+
dest: 'compressed/extensions/prettify.min.js'
|
26
|
+
},
|
27
|
+
table_ext: {
|
28
|
+
src: ['src/extensions/table.js'],
|
29
|
+
dest: 'compressed/extensions/table.min.js'
|
30
|
+
},
|
31
|
+
twitter_ext: {
|
32
|
+
src: ['src/extensions/twitter.js'],
|
33
|
+
dest: 'compressed/extensions/twitter.min.js'
|
34
|
+
}
|
35
|
+
},
|
36
|
+
uglify: {
|
37
|
+
options: {
|
38
|
+
banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
|
39
|
+
},
|
40
|
+
dist: {
|
41
|
+
files: {
|
42
|
+
'compressed/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
|
43
|
+
}
|
44
|
+
},
|
45
|
+
github_ext: {
|
46
|
+
files: {
|
47
|
+
'compressed/extensions/github.min.js': ['<%= concat.github_ext.dest %>']
|
48
|
+
}
|
49
|
+
},
|
50
|
+
prettify_ext: {
|
51
|
+
files: {
|
52
|
+
'compressed/extensions/prettify.min.js': ['<%= concat.prettify_ext.dest %>']
|
53
|
+
}
|
54
|
+
},
|
55
|
+
table_ext: {
|
56
|
+
files: {
|
57
|
+
'compressed/extensions/table.min.js': ['<%= concat.table_ext.dest %>']
|
58
|
+
}
|
59
|
+
},
|
60
|
+
twitter_ext: {
|
61
|
+
files: {
|
62
|
+
'compressed/extensions/twitter.min.js': ['<%= concat.twitter_ext.dest %>']
|
63
|
+
}
|
64
|
+
}
|
65
|
+
},
|
66
|
+
jshint: {
|
67
|
+
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js']
|
68
|
+
},
|
69
|
+
simplemocha: {
|
70
|
+
all: {
|
71
|
+
src: 'test/run.js',
|
72
|
+
options: {
|
73
|
+
globals: ['should'],
|
74
|
+
timeout: 3000,
|
75
|
+
ignoreLeaks: false,
|
76
|
+
ui: 'bdd'
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
});
|
81
|
+
|
82
|
+
grunt.loadNpmTasks('grunt-contrib-concat');
|
83
|
+
grunt.loadNpmTasks('grunt-contrib-uglify');
|
84
|
+
grunt.loadNpmTasks('grunt-contrib-jshint');
|
85
|
+
grunt.loadNpmTasks('grunt-simple-mocha');
|
86
|
+
|
87
|
+
// test
|
88
|
+
grunt.registerTask('lint', ['jshint']);
|
89
|
+
grunt.registerTask('test', ['simplemocha']);
|
90
|
+
|
91
|
+
// build with uglify
|
92
|
+
grunt.registerTask('build', ['concat', 'uglify']);
|
93
|
+
|
94
|
+
// Build with closure compiler
|
95
|
+
grunt.registerTask('build-with-closure', ['test', 'concat', 'closure-compiler']);
|
96
|
+
|
97
|
+
// Default task(s).
|
98
|
+
grunt.registerTask('default', []);
|
99
|
+
|
100
|
+
};
|
@@ -0,0 +1,317 @@
|
|
1
|
+
# Showdown
|
2
|
+
|
3
|
+
A JavaScript port of Markdown
|
4
|
+
|
5
|
+
## Note
|
6
|
+
|
7
|
+
> Showdown is now maintained by the [showdownjs](https://github.com/showdownjs) organization on Github.
|
8
|
+
>
|
9
|
+
> The organization needs members to maintain Showdown.
|
10
|
+
>
|
11
|
+
> Please see [this issue](https://github.com/showdownjs/showdown/issues/114) to express interest or comment on this note.
|
12
|
+
|
13
|
+
## Original Attributions
|
14
|
+
|
15
|
+
Showdown Copyright (c) 2007 John Fraser.
|
16
|
+
<http://www.attacklab.net/>
|
17
|
+
|
18
|
+
Original Markdown Copyright (c) 2004-2005 John Gruber
|
19
|
+
<http://daringfireball.net/projects/markdown/>
|
20
|
+
|
21
|
+
Redistributable under a BSD-style open source license.
|
22
|
+
See license.txt for more information.
|
23
|
+
|
24
|
+
## Quick Example
|
25
|
+
|
26
|
+
```js
|
27
|
+
var Showdown = require('showdown');
|
28
|
+
var converter = new Showdown.converter();
|
29
|
+
|
30
|
+
converter.makeHtml('#hello markdown!');
|
31
|
+
|
32
|
+
// <h1 id="hellomarkdown">hello, markdown</h1>
|
33
|
+
```
|
34
|
+
|
35
|
+
## What's it for?
|
36
|
+
|
37
|
+
Developers can use Showdown to:
|
38
|
+
|
39
|
+
* Add in-browser preview to existing Markdown apps
|
40
|
+
|
41
|
+
Showdown's output is (almost always) identical to
|
42
|
+
markdown.pl's, so the server can reproduce exactly
|
43
|
+
the output that the user saw. (See below for
|
44
|
+
exceptions.)
|
45
|
+
|
46
|
+
* Add Markdown input to programs that don't support it
|
47
|
+
|
48
|
+
Any app that accepts HTML input can now be made to speak
|
49
|
+
Markdown by modifying the input pages's HTML. If your
|
50
|
+
application lets users edit documents again later,
|
51
|
+
then they won't have access to the original Markdown
|
52
|
+
text. But this should be good enough for many
|
53
|
+
uses -- and you can do it with just a two-line
|
54
|
+
`onsubmit` function!
|
55
|
+
|
56
|
+
* Add Markdown input to closed-source web apps
|
57
|
+
|
58
|
+
You can write bookmarklets or userscripts to extend
|
59
|
+
any standard textarea on the web so that it accepts
|
60
|
+
Markdown instead of HTML. With a little more hacking,
|
61
|
+
the same can probably be done with many rich edit
|
62
|
+
controls.
|
63
|
+
|
64
|
+
* Build new web apps from scratch
|
65
|
+
|
66
|
+
A Showdown front-end can send back text in Markdown,
|
67
|
+
HTML or both, so you can trade bandwidth for server
|
68
|
+
load to reduce your cost of operation. If your app
|
69
|
+
requires JavaScript, you won't need to do any
|
70
|
+
Markdown processing on the server at all. (For most
|
71
|
+
uses, you'll still need to sanitize the HTML before
|
72
|
+
showing it to other users -- but you'd need to do
|
73
|
+
that anyway if you're allowing raw HTML in your
|
74
|
+
Markdown.)
|
75
|
+
|
76
|
+
|
77
|
+
## Browser Compatibility
|
78
|
+
|
79
|
+
Showdown has been tested successfully with:
|
80
|
+
|
81
|
+
* Firefox 1.5 and 2.0
|
82
|
+
* Internet Explorer 6 and 7
|
83
|
+
* Safari 2.0.4
|
84
|
+
* Opera 8.54 and 9.10
|
85
|
+
* Netscape 8.1.2
|
86
|
+
* Konqueror 3.5.4
|
87
|
+
|
88
|
+
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.
|
89
|
+
|
90
|
+
|
91
|
+
## Extensions
|
92
|
+
|
93
|
+
Showdown allows additional functionality to be loaded via extensions.
|
94
|
+
|
95
|
+
### Client-side Extension Usage
|
96
|
+
|
97
|
+
```js
|
98
|
+
<script src="src/showdown.js" />
|
99
|
+
<script src="src/extensions/twitter.js" />
|
100
|
+
|
101
|
+
var converter = new Showdown.converter({ extensions: ['twitter'] });
|
102
|
+
```
|
103
|
+
|
104
|
+
### Server-side Extension Usage
|
105
|
+
|
106
|
+
```js
|
107
|
+
// Using a bundled extension
|
108
|
+
var Showdown = require('showdown');
|
109
|
+
var converter = new Showdown.converter({ extensions: ['twitter'] });
|
110
|
+
|
111
|
+
// Using a custom extension
|
112
|
+
var mine = require('./custom-extensions/mine');
|
113
|
+
var converter = new Showdown.converter({ extensions: ['twitter', mine] });
|
114
|
+
```
|
115
|
+
|
116
|
+
|
117
|
+
## Known Differences in Output
|
118
|
+
|
119
|
+
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.
|
120
|
+
|
121
|
+
* This release uses the HTML parser from Markdown 1.0.2b2,
|
122
|
+
which means it fails `Inline HTML (Advanced).text` from
|
123
|
+
the Markdown test suite:
|
124
|
+
|
125
|
+
<div>
|
126
|
+
<div>
|
127
|
+
unindented == broken
|
128
|
+
</div>
|
129
|
+
</div>
|
130
|
+
|
131
|
+
* Showdown doesn't support the markdown="1" attribute:
|
132
|
+
|
133
|
+
<div markdown="1">
|
134
|
+
Markdown does *not* work in here.
|
135
|
+
</div>
|
136
|
+
|
137
|
+
This is half laziness on my part and half stubbornness.
|
138
|
+
Markdown is smart enough to process the contents of span-
|
139
|
+
level tags without screwing things up; shouldn't it be
|
140
|
+
able to do the same inside block elements? Let's find a
|
141
|
+
way to make markdown="1" the default.
|
142
|
+
|
143
|
+
|
144
|
+
* You can only nest square brackets in link titles to a
|
145
|
+
depth of two levels:
|
146
|
+
|
147
|
+
[[fine]](http://www.attacklab.net/)
|
148
|
+
[[[broken]]](http://www.attacklab.net/)
|
149
|
+
|
150
|
+
If you need more, you can escape them with backslashes.
|
151
|
+
|
152
|
+
|
153
|
+
* When sublists have paragraphs, Showdown produces equivalent
|
154
|
+
HTML with a slightly different arrangement of newlines:
|
155
|
+
|
156
|
+
+ item
|
157
|
+
|
158
|
+
- subitem
|
159
|
+
|
160
|
+
The HTML has a superfluous newline before this
|
161
|
+
paragraph.
|
162
|
+
|
163
|
+
- subitem
|
164
|
+
|
165
|
+
The HTML here is unchanged.
|
166
|
+
|
167
|
+
- subitem
|
168
|
+
|
169
|
+
The HTML is missing a newline after this
|
170
|
+
list subitem.
|
171
|
+
|
172
|
+
|
173
|
+
|
174
|
+
* Markdown.pl creates empty title attributes for
|
175
|
+
inline-style images:
|
176
|
+
|
177
|
+
Here's an empty title on an inline-style
|
178
|
+
![image](http://w3.org/Icons/valid-xhtml10).
|
179
|
+
|
180
|
+
I tried to replicate this to clean up my diffs during
|
181
|
+
testing, but I went too far: now Showdown also makes
|
182
|
+
empty titles for reference-style images:
|
183
|
+
|
184
|
+
Showdown makes an empty title for
|
185
|
+
reference-style ![images][] too.
|
186
|
+
|
187
|
+
[images]: http://w3.org/Icons/valid-xhtml10
|
188
|
+
|
189
|
+
|
190
|
+
* With crazy input, Markdown will mistakenly put
|
191
|
+
`<strong>` or `<em>` tags in URLs:
|
192
|
+
|
193
|
+
<a href="<*Markdown adds em tags in here*>">
|
194
|
+
improbable URL
|
195
|
+
</a>
|
196
|
+
|
197
|
+
Showdown won't. But still, don't do that.
|
198
|
+
|
199
|
+
|
200
|
+
## Tests
|
201
|
+
|
202
|
+
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:
|
203
|
+
|
204
|
+
npm install --dev
|
205
|
+
|
206
|
+
Once installed the tests can be run from the project root using:
|
207
|
+
|
208
|
+
npm test
|
209
|
+
|
210
|
+
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`.
|
211
|
+
|
212
|
+
|
213
|
+
## Creating Markdown Extensions
|
214
|
+
|
215
|
+
A showdown extension is simply a function which returns an array of language extensions and/or output modifiers:
|
216
|
+
|
217
|
+
* Language Extension -- Language extensions are specified with the `lang` type, and 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.
|
218
|
+
* Output Modifiers -- Output Modifiers are specified with the `output` type. After showdown has generated HTML, an output modifier can make changes to the generated HTML. For example, if you wanted to change `<div class="header">` to be `<header>`, you could implement an output modifier.
|
219
|
+
|
220
|
+
Each showdown extension can provide language extensions and/or output modifiers.
|
221
|
+
|
222
|
+
### Regex/Replace
|
223
|
+
|
224
|
+
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.
|
225
|
+
|
226
|
+
**Example:**
|
227
|
+
|
228
|
+
```js
|
229
|
+
var demo = function(converter) {
|
230
|
+
return [
|
231
|
+
// Replace escaped @ symbols
|
232
|
+
{ type: 'lang', regex: '\\@', replace: '@' }
|
233
|
+
];
|
234
|
+
}
|
235
|
+
```
|
236
|
+
|
237
|
+
### Filter
|
238
|
+
|
239
|
+
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).
|
240
|
+
|
241
|
+
**Example:**
|
242
|
+
|
243
|
+
```js
|
244
|
+
var demo = function(converter) {
|
245
|
+
return [
|
246
|
+
// Replace escaped @ symbols
|
247
|
+
{ type: 'lang', filter: function(text) {
|
248
|
+
return text.replace(/\\@/g, '@');
|
249
|
+
}}
|
250
|
+
];
|
251
|
+
}
|
252
|
+
```
|
253
|
+
|
254
|
+
### Implementation Concerns
|
255
|
+
|
256
|
+
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.
|
257
|
+
|
258
|
+
```js
|
259
|
+
(function(){
|
260
|
+
// Your extension here
|
261
|
+
}());
|
262
|
+
```
|
263
|
+
|
264
|
+
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.
|
265
|
+
|
266
|
+
```js
|
267
|
+
(function(){
|
268
|
+
var demo = function(converter) {
|
269
|
+
// ... extension code here ...
|
270
|
+
};
|
271
|
+
|
272
|
+
// Client-side export
|
273
|
+
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.demo = demo; }
|
274
|
+
// Server-side export
|
275
|
+
if (typeof module !== 'undefined') module.exports = demo;
|
276
|
+
}());
|
277
|
+
```
|
278
|
+
|
279
|
+
### Testing Extensions
|
280
|
+
|
281
|
+
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.
|
282
|
+
|
283
|
+
|
284
|
+
## Credits
|
285
|
+
|
286
|
+
* Origins
|
287
|
+
* [John Fraser](http://attacklab.net/):<br/>
|
288
|
+
Author of Showdown
|
289
|
+
* [John Gruber](http://daringfireball.net/projects/markdown/):<br/>
|
290
|
+
Author of Markdown
|
291
|
+
* Maintenance/Contributions (roughly chronologically)
|
292
|
+
* [Corey Innis](http://github.com/coreyti):<br/>
|
293
|
+
GitHub project maintainer
|
294
|
+
* [Remy Sharp](https://github.com/remy/):<br/>
|
295
|
+
CommonJS-compatibility and more
|
296
|
+
* [Konstantin Käfer](https://github.com/kkaefer/):<br/>
|
297
|
+
CommonJS packaging
|
298
|
+
* [Roger Braun](https://github.com/rogerbraun):<br/>
|
299
|
+
Github-style code blocks
|
300
|
+
* [Dominic Tarr](https://github.com/dominictarr):<br/>
|
301
|
+
Documentation
|
302
|
+
* [Cat Chen](https://github.com/CatChen):<br/>
|
303
|
+
Export fix
|
304
|
+
* [Titus Stone](https://github.com/tstone):<br/>
|
305
|
+
Mocha tests, extension mechanism, and bug fixes
|
306
|
+
* [Rob Sutherland](https://github.com/roberocity):<br/>
|
307
|
+
The idea that lead to extensions
|
308
|
+
* [Pavel Lang](https://github.com/langpavel):<br/>
|
309
|
+
Code cleanup
|
310
|
+
* [Ben Combee](https://github.com/unwiredben):<br/>
|
311
|
+
Regex optimization
|
312
|
+
* [Adam Backstrom](https://github.com/abackstrom):<br/>
|
313
|
+
WebKit bugfix
|
314
|
+
* [Pascal Deschênes](https://github.com/pdeschen):<br/>
|
315
|
+
Grunt support, extension fixes + additions, packaging improvements, documentation
|
316
|
+
* [Estevão Santos](http://github.com/coreyti):<br/>
|
317
|
+
GitHub project maintainer
|