Skip to content

Commit

Permalink
feat(image dimensions): add support for setting image dimensions with…
Browse files Browse the repository at this point in the history
…in markdown syntax

This feature allows users to define the image dimensions using markdown syntax:
```
![my image](img.jpg =100x80 "image title")
```
To enable this feature, use the option `parseImgDimensions`.

Closes #143
  • Loading branch information
tivie committed Jun 17, 2015
1 parent 0ac8972 commit af82c2b
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 135 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ var thisConverterSpecificOptions = conveter.getOptions();
### Valid Options
* **omitExtraWLInCodeBlocks**: (boolean) Omits the trailing newline in a code block. Ex:
* **omitExtraWLInCodeBlocks**: (boolean) [default false] Omits the trailing newline in a code block. Ex:
This:
```html
Expand All @@ -151,8 +151,16 @@ var thisConverterSpecificOptions = conveter.getOptions();
<code><pre>var foo = 'bar';</pre></code>
```
* **prefixHeaderId**: (string/boolean) Adds a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to `true` will add a generic 'section' prefix.
* **noHeaderId**: (boolean) [default false] Disables the automatic generation of header ids. Setting to true overrides **prefixHeaderId**
* **prefixHeaderId**: (string/boolean) [default false] Adds a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to `true` will add a generic 'section' prefix.
* **parseImgDimensions**: (boolean) [default false] Enables support for setting image dimensions from within markdown syntax.
Example:
```
![my image](foo.jpg =100x80)
```
## Integration with AngularJS
Expand Down
112 changes: 48 additions & 64 deletions dist/showdown.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/showdown.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/showdown.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/showdown.min.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ showdown.Converter = function (converterOptions) {
gHtmlBlocks: [],
gUrls: {},
gTitles: {},
gDimensions: {},
gListLevel: 0,
hashLinkCounts: {},
langExtensions: langExtensions,
Expand Down
3 changes: 2 additions & 1 deletion src/showdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ var showdown = {},
defaultOptions = {
omitExtraWLInCodeBlocks: false,
prefixHeaderId: false,
noHeaderId: false
noHeaderId: false,
parseImgDimensions: false
},
globalOptions = JSON.parse(JSON.stringify(defaultOptions)); //clone default options out of laziness =P

Expand Down
82 changes: 28 additions & 54 deletions src/subParsers/images.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
showdown.subParser('images', function (text, options, globals) {
'use strict';

var writeImageTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
var inlineRegExp = /!\[(.*?)]\s?\([ \t]*()<?(\S+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(['"])(.*?)\6[ \t]*)?\)/g,
referenceRegExp = /!\[(.*?)][ ]?(?:\n[ ]*)?\[(.*?)]()()()()()/g;

wholeMatch = m1;
var altText = m2,
linkId = m3.toLowerCase(),
url = m4,
title = m7,
gUrls = globals.gUrls,
gTitles = globals.gTitles;
function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {

var gUrls = globals.gUrls,
gTitles = globals.gTitles,
gDims = globals.gDimensions;

linkId = linkId.toLowerCase();

if (!title) {
title = '';
Expand All @@ -25,11 +26,15 @@ showdown.subParser('images', function (text, options, globals) {
}
url = '#' + linkId;

if (typeof gUrls[linkId] !== 'undefined') {
if (!showdown.helper.isUndefined(gUrls[linkId])) {
url = gUrls[linkId];
if (typeof gTitles[linkId] !== 'undefined') {
if (!showdown.helper.isUndefined(gTitles[linkId])) {
title = gTitles[linkId];
}
if (!showdown.helper.isUndefined(gDims[linkId])) {
width = gDims[linkId].width;
height = gDims[linkId].height;
}
} else {
return wholeMatch;
}
Expand All @@ -45,55 +50,24 @@ showdown.subParser('images', function (text, options, globals) {
result += ' title="' + title + '"';
}

if (width && height) {
width = (width === '*') ? 'auto' : width;
height = (height === '*') ? 'auto' : height;

result += ' width="' + width + '"';
result += ' height="' + height + '"';
}

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);
text = text.replace(referenceRegExp, writeImageTag);

// Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
text = text.replace(inlineRegExp, writeImageTag);

return text;
});
26 changes: 17 additions & 9 deletions src/subParsers/stripLinkDefinitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,31 @@
showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
'use strict';

var regex = /^[ ]{0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=~0))/gm;
var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(\S+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=~0))/gm;

// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
text += '~0';

text = text.replace(regex, function (wholeMatch, m1, m2, m3, m4) {
m1 = m1.toLowerCase();
globals.gUrls[m1] = showdown.subParser('encodeAmpsAndAngles')(m2); // Link IDs are case-insensitive
if (m3) {
text = text.replace(regex, function (wholeMatch, linkId, url, width, height, blankLines, title) {
linkId = linkId.toLowerCase();
globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url); // Link IDs are case-insensitive

if (blankLines) {
// Oops, found blank lines, so it's not a title.
// Put back the parenthetical statement we stole.
return m3 + m4;
return blankLines + title;

} else if (m4) {
globals.gTitles[m1] = m4.replace(/"|'/g, '&quot;');
} else {
if (title) {
globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
}
if (options.parseImgDimensions && width && height) {
globals.gDimensions[linkId] = {
width: width,
height: height
};
}
}

// Completely remove the definition from the text
return '';
});
Expand Down
2 changes: 2 additions & 0 deletions test/features/#143.support_image_dimensions.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<p><img src="./pic/pic1_50.png" alt="my image" width="100px" height="20px" /></p>
<p><img src="./pic/pic1_50.png" alt="my image2" width="100px" height="20px" /></p>
5 changes: 5 additions & 0 deletions test/features/#143.support_image_dimensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
![my image](./pic/pic1_50.png =100pxx20px)

![my image2][1]

[1]: ./pic/pic1_50.png =100pxx20px
3 changes: 2 additions & 1 deletion test/node/showdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ describe('showdown.options', function () {
var opts = {
omitExtraWLInCodeBlocks: false,
prefixHeaderId: false,
noHeaderId: false
noHeaderId: false,
parseImgDimensions: false
};
expect(showdown.getDefaultOptions()).to.be.eql(opts);
});
Expand Down
Loading

0 comments on commit af82c2b

Please sign in to comment.