').appendTo(document.body);
83 | }
84 |
85 | // Initialize CSS for textarea
86 | if (!$textarea.data('autoexpand')) initTextarea($textarea);
87 |
88 | // Get the min-height. This takes `rows`, `min-height` and `height` into
89 | // consideration (thanks, browsers)
90 | var isFull = ($textarea.css('box-sizing') === 'border-box');
91 | var height = isFull ? $textarea.outerHeight() : $textarea.css('height');
92 | var minHeight = Math.max(minHeight, integer(height));
93 |
94 | $shadow.css({
95 | position: 'absolute',
96 | top: -10000,
97 | left: -10000,
98 | zIndex: -100,
99 | width: isFull ? $textarea.outerWidth() : $textarea.css('width'),
100 | minHeight: minHeight,
101 | visibility: 'hidden',
102 | resize: 'none',
103 | borderColor: 'red', /* [1] */
104 | borderStyle: 'solid'
105 | });
106 |
107 | var props = ['fontFamily', 'fontSize', 'lineHeight', 'boxSizing', 'paddingTop',
108 | 'paddingBottom', 'paddingLeft', 'paddingRight', 'wordWrap', 'whiteSpace',
109 | 'textWrap', 'borderWidth'];
110 |
111 | for (var i=0; i
0) val += times('
', options.extraLines);
148 |
149 | $shadow.html(val);
150 |
151 | var isFull = ($textarea.css('box-sizing') === 'border-box');
152 |
153 | var height = isFull ? $shadow.outerHeight() : $shadow.css('height');
154 | var maxHeight = integer($textarea.css('max-height'));
155 | if ((maxHeight) && (height >= maxHeight)) height = maxHeight;
156 |
157 | $textarea.css('height', height);
158 |
159 | // If we've reached your max-height, show the scrollbars
160 | if (maxHeight !== null) {
161 | if (height === maxHeight) {
162 | $textarea.css({ 'overflow-y': 'auto' });
163 | } else {
164 | $textarea.css({ 'overflow-y': 'hidden' });
165 | }
166 | }
167 | };
168 |
169 | var updateAll = function() { updateShadow.apply(this); updateHeight.apply(this); };
170 |
171 | // Bind events.
172 | $(document).on('focus', this.selector, updateAll);
173 | $(document).on('input change', this.selector, throttle(updateHeight, options.throttle));
174 | $(window).on('resize', function() { $this.each(updateAll); });
175 |
176 | // Allow manually updating the height via `.trigger('autoexpand')`
177 | $(document).on('autoexpand', this.selector, updateAll);
178 |
179 | // Trigger immediately
180 | $(function() { $this.each(updateAll); });
181 |
182 | return this;
183 | };
184 |
185 | // Converts a string (like "32px") to integer.
186 | function integer(str) {
187 | var i = parseInt(str, 10);
188 | return isNaN(i) ? null : i;
189 | }
190 |
191 | function throttle(fn, speed) {
192 | return (speed && window._ && window._.throttle) ?
193 | window._.throttle(fn, speed) :
194 | fn;
195 | }
196 |
197 | // Escapes a `string` to HTML entities.
198 | function htmlescape(string) {
199 | return string
200 | .replace(//g, '>')
202 | .replace(/&/g, '&')
203 | .replace(/\n$/, '
')
204 | .replace(/\n/g, '
')
205 | .replace(/ {2,}/g, function(space) { return times(' ', space.length -1) + ' '; });
206 | }
207 |
208 | // Repeats a `string` a `number` of times.
209 | function times(string, number) {
210 | var re = '';
211 | for(var i = 0; i < number; i++) { re = re + string; }
212 | return re;
213 | }
214 |
215 | // Adds a transition `transition` to element `$el`.
216 | function addTransition($el, transition) {
217 | var value = $el.css('transition');
218 | if (value.length) value += ', ';
219 | value += transition;
220 | return $el.css({ transition: value });
221 | }
222 |
223 | })(jQuery);
224 |
--------------------------------------------------------------------------------
/lib/meta.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Adds `base`
3 | */
4 |
5 | module.exports = function () {
6 | return function (files, ms, done) {
7 | for (var fname in files) {
8 | var file = files[fname]
9 | var depth = fname.split('/').length
10 | var base = Array(depth).join('../')
11 | base = base.substr(0, base.length - 1)
12 |
13 | file.base = base
14 | }
15 |
16 | done()
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lib/middleware.js:
--------------------------------------------------------------------------------
1 | var hljs = require('highlight.js')
2 |
3 | /*
4 | * Ran before jstransformer.
5 | */
6 |
7 | exports.addMdOptions = function () {
8 | return function (files, ms, done) {
9 | for (var fn in files) {
10 | if (/\.md$/.test(fn)) {
11 | files[fn].contents = transformMd(files[fn].contents.toString())
12 | files[fn].html = true
13 | files[fn].plugins = [
14 | require('markdown-it-decorate'),
15 | require('markdown-it-named-headings')
16 | ]
17 | }
18 | }
19 | done()
20 | }
21 | }
22 |
23 | /*
24 | * Ran after jstransformer.
25 | */
26 |
27 | exports.transformHtml = function () {
28 | return function (files, ms, done) {
29 | for (var fn in files) {
30 | if (/\.html/.test(fn)) {
31 | files[fn].contents = transformHtml(files[fn].contents.toString())
32 | }
33 | }
34 | done()
35 | }
36 | }
37 |
38 | /*
39 | * Pre-markdown transformations.
40 | */
41 |
42 | function transformMd (md) {
43 | md = md.replace(
44 | /\*( \*)+\n/g,
45 | '\n')
46 | return md
47 | }
48 |
49 | /*
50 | * Transforms HTML.
51 | */
52 |
53 | function transformHtml (html) {
54 | // Up next:
55 | html = html.replace(/
\nNext: ([^<]*)\n
$1<')
56 |
57 | // See also:
58 | html = html.replace(/
\n(See also|Also see): /g, '
\nAlso see: ')
59 |
60 | // Remove
, used to break blockquotes
61 | html = html.replace(/\n
\n/g, '\n')
62 |
63 | // Highlight
64 | html = highlightCode(html)
65 | return html
66 | }
67 |
68 | function highlightCode (html) {
69 | html = html.replace(/
([\s\S.]*?)<\/code><\/pre>/mg, function (_, lang, code) {
70 | code = code.replace(/</g, '<')
71 | code = code.replace(/>/g, '>')
72 | code = code.replace(/&/g, '&')
73 | code = code.replace(/"/g, "'")
74 | code = hljs.highlight(lang, code).value
75 |
76 | // ellipsis /*...*/
77 | code = code.replace(
78 | /