markdown-it-link-attributes
Advanced tools
Comparing version 3.0.0 to 4.0.0
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.markdownitLinkAttributes = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | ||
'use strict' | ||
"use strict"; | ||
// Adapted from https://github.com/markdown-it/markdown-it/blob/fbc6b0fed563ba7c00557ab638fd19752f8e759d/docs/architecture.md | ||
function findFirstMatchingConfig (link, configs) { | ||
var i, config | ||
var href = link.attrs[link.attrIndex('href')][1] | ||
function findFirstMatchingConfig(link, configs) { | ||
var i, config; | ||
var href = link.attrs[link.attrIndex("href")][1]; | ||
for (i = 0; i < configs.length; ++i) { | ||
config = configs[i] | ||
config = configs[i]; | ||
// if there is no pattern, config matches for all links | ||
// otherwise, only return config if href matches the pattern set | ||
if (!config.pattern || new RegExp(config.pattern).test(href)) { | ||
return config | ||
// If there is a matcher function defined then call it | ||
// Matcher Function should return a boolean indicating | ||
// whether or not it matched. If it matched, use that | ||
// configuration, otherwise, try the next one. | ||
if (typeof config.matcher === "function") { | ||
if (config.matcher(href, config)) { | ||
return config; | ||
} else { | ||
continue; | ||
} | ||
} | ||
return config; | ||
} | ||
} | ||
function applyAttributes (idx, tokens, attributes) { | ||
function applyAttributes(idx, tokens, attributes) { | ||
Object.keys(attributes).forEach(function (attr) { | ||
var attrIndex | ||
var value = attributes[attr] | ||
var attrIndex; | ||
var value = attributes[attr]; | ||
if (attr === 'className') { | ||
if (attr === "className") { | ||
// when dealing with applying classes | ||
// programatically, some programmers | ||
// may prefer to use the className syntax | ||
attr = 'class' | ||
attr = "class"; | ||
} | ||
attrIndex = tokens[idx].attrIndex(attr) | ||
attrIndex = tokens[idx].attrIndex(attr); | ||
if (attrIndex < 0) { // attr doesn't exist, add new attribute | ||
tokens[idx].attrPush([attr, value]) | ||
} else { // attr already exists, overwrite it | ||
tokens[idx].attrs[attrIndex][1] = value // replace value of existing attr | ||
if (attrIndex < 0) { | ||
// attr doesn't exist, add new attribute | ||
tokens[idx].attrPush([attr, value]); | ||
} else { | ||
// attr already exists, overwrite it | ||
tokens[idx].attrs[attrIndex][1] = value; // replace value of existing attr | ||
} | ||
}) | ||
}); | ||
} | ||
function markdownitLinkAttributes (md, configs) { | ||
function markdownitLinkAttributes(md, configs) { | ||
if (!configs) { | ||
configs = [] | ||
configs = []; | ||
} else { | ||
configs = Array.isArray(configs) ? configs : [configs] | ||
configs = Array.isArray(configs) ? configs : [configs]; | ||
} | ||
Object.freeze(configs) | ||
Object.freeze(configs); | ||
var defaultRender = md.renderer.rules.link_open || this.defaultRender | ||
var defaultRender = md.renderer.rules.link_open || this.defaultRender; | ||
md.renderer.rules.link_open = function (tokens, idx, options, env, self) { | ||
var config = findFirstMatchingConfig(tokens[idx], configs) | ||
var attributes = config && config.attrs | ||
var config = findFirstMatchingConfig(tokens[idx], configs); | ||
var attributes = config && config.attrs; | ||
if (attributes) { | ||
applyAttributes(idx, tokens, attributes) | ||
applyAttributes(idx, tokens, attributes); | ||
} | ||
// pass token to default renderer. | ||
return defaultRender(tokens, idx, options, env, self) | ||
} | ||
return defaultRender(tokens, idx, options, env, self); | ||
}; | ||
} | ||
markdownitLinkAttributes.defaultRender = function (tokens, idx, options, env, self) { | ||
return self.renderToken(tokens, idx, options) | ||
} | ||
markdownitLinkAttributes.defaultRender = function ( | ||
tokens, | ||
idx, | ||
options, | ||
env, | ||
self | ||
) { | ||
return self.renderToken(tokens, idx, options); | ||
}; | ||
module.exports = markdownitLinkAttributes | ||
module.exports = markdownitLinkAttributes; | ||
},{}]},{},[1])(1) | ||
}); |
@@ -1,1 +0,1 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.markdownitLinkAttributes=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r}()({1:[function(require,module,exports){"use strict";function findFirstMatchingConfig(link,configs){var i,config;var href=link.attrs[link.attrIndex("href")][1];for(i=0;i<configs.length;++i){config=configs[i];if(!config.pattern||new RegExp(config.pattern).test(href)){return config}}}function applyAttributes(idx,tokens,attributes){Object.keys(attributes).forEach(function(attr){var attrIndex;var value=attributes[attr];if(attr==="className"){attr="class"}attrIndex=tokens[idx].attrIndex(attr);if(attrIndex<0){tokens[idx].attrPush([attr,value])}else{tokens[idx].attrs[attrIndex][1]=value}})}function markdownitLinkAttributes(md,configs){if(!configs){configs=[]}else{configs=Array.isArray(configs)?configs:[configs]}Object.freeze(configs);var defaultRender=md.renderer.rules.link_open||this.defaultRender;md.renderer.rules.link_open=function(tokens,idx,options,env,self){var config=findFirstMatchingConfig(tokens[idx],configs);var attributes=config&&config.attrs;if(attributes){applyAttributes(idx,tokens,attributes)}return defaultRender(tokens,idx,options,env,self)}}markdownitLinkAttributes.defaultRender=function(tokens,idx,options,env,self){return self.renderToken(tokens,idx,options)};module.exports=markdownitLinkAttributes},{}]},{},[1])(1)}); | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.markdownitLinkAttributes=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r}()({1:[function(require,module,exports){"use strict";function findFirstMatchingConfig(link,configs){var i,config;var href=link.attrs[link.attrIndex("href")][1];for(i=0;i<configs.length;++i){config=configs[i];if(typeof config.matcher==="function"){if(config.matcher(href,config)){return config}else{continue}}return config}}function applyAttributes(idx,tokens,attributes){Object.keys(attributes).forEach(function(attr){var attrIndex;var value=attributes[attr];if(attr==="className"){attr="class"}attrIndex=tokens[idx].attrIndex(attr);if(attrIndex<0){tokens[idx].attrPush([attr,value])}else{tokens[idx].attrs[attrIndex][1]=value}})}function markdownitLinkAttributes(md,configs){if(!configs){configs=[]}else{configs=Array.isArray(configs)?configs:[configs]}Object.freeze(configs);var defaultRender=md.renderer.rules.link_open||this.defaultRender;md.renderer.rules.link_open=function(tokens,idx,options,env,self){var config=findFirstMatchingConfig(tokens[idx],configs);var attributes=config&&config.attrs;if(attributes){applyAttributes(idx,tokens,attributes)}return defaultRender(tokens,idx,options,env,self)}}markdownitLinkAttributes.defaultRender=function(tokens,idx,options,env,self){return self.renderToken(tokens,idx,options)};module.exports=markdownitLinkAttributes},{}]},{},[1])(1)}); |
84
index.js
@@ -1,70 +0,86 @@ | ||
'use strict' | ||
"use strict"; | ||
// Adapted from https://github.com/markdown-it/markdown-it/blob/fbc6b0fed563ba7c00557ab638fd19752f8e759d/docs/architecture.md | ||
function findFirstMatchingConfig (link, configs) { | ||
var i, config | ||
var href = link.attrs[link.attrIndex('href')][1] | ||
function findFirstMatchingConfig(link, configs) { | ||
var i, config; | ||
var href = link.attrs[link.attrIndex("href")][1]; | ||
for (i = 0; i < configs.length; ++i) { | ||
config = configs[i] | ||
config = configs[i]; | ||
// if there is no pattern, config matches for all links | ||
// otherwise, only return config if href matches the pattern set | ||
if (!config.pattern || new RegExp(config.pattern).test(href)) { | ||
return config | ||
// If there is a matcher function defined then call it | ||
// Matcher Function should return a boolean indicating | ||
// whether or not it matched. If it matched, use that | ||
// configuration, otherwise, try the next one. | ||
if (typeof config.matcher === "function") { | ||
if (config.matcher(href, config)) { | ||
return config; | ||
} else { | ||
continue; | ||
} | ||
} | ||
return config; | ||
} | ||
} | ||
function applyAttributes (idx, tokens, attributes) { | ||
function applyAttributes(idx, tokens, attributes) { | ||
Object.keys(attributes).forEach(function (attr) { | ||
var attrIndex | ||
var value = attributes[attr] | ||
var attrIndex; | ||
var value = attributes[attr]; | ||
if (attr === 'className') { | ||
if (attr === "className") { | ||
// when dealing with applying classes | ||
// programatically, some programmers | ||
// may prefer to use the className syntax | ||
attr = 'class' | ||
attr = "class"; | ||
} | ||
attrIndex = tokens[idx].attrIndex(attr) | ||
attrIndex = tokens[idx].attrIndex(attr); | ||
if (attrIndex < 0) { // attr doesn't exist, add new attribute | ||
tokens[idx].attrPush([attr, value]) | ||
} else { // attr already exists, overwrite it | ||
tokens[idx].attrs[attrIndex][1] = value // replace value of existing attr | ||
if (attrIndex < 0) { | ||
// attr doesn't exist, add new attribute | ||
tokens[idx].attrPush([attr, value]); | ||
} else { | ||
// attr already exists, overwrite it | ||
tokens[idx].attrs[attrIndex][1] = value; // replace value of existing attr | ||
} | ||
}) | ||
}); | ||
} | ||
function markdownitLinkAttributes (md, configs) { | ||
function markdownitLinkAttributes(md, configs) { | ||
if (!configs) { | ||
configs = [] | ||
configs = []; | ||
} else { | ||
configs = Array.isArray(configs) ? configs : [configs] | ||
configs = Array.isArray(configs) ? configs : [configs]; | ||
} | ||
Object.freeze(configs) | ||
Object.freeze(configs); | ||
var defaultRender = md.renderer.rules.link_open || this.defaultRender | ||
var defaultRender = md.renderer.rules.link_open || this.defaultRender; | ||
md.renderer.rules.link_open = function (tokens, idx, options, env, self) { | ||
var config = findFirstMatchingConfig(tokens[idx], configs) | ||
var attributes = config && config.attrs | ||
var config = findFirstMatchingConfig(tokens[idx], configs); | ||
var attributes = config && config.attrs; | ||
if (attributes) { | ||
applyAttributes(idx, tokens, attributes) | ||
applyAttributes(idx, tokens, attributes); | ||
} | ||
// pass token to default renderer. | ||
return defaultRender(tokens, idx, options, env, self) | ||
} | ||
return defaultRender(tokens, idx, options, env, self); | ||
}; | ||
} | ||
markdownitLinkAttributes.defaultRender = function (tokens, idx, options, env, self) { | ||
return self.renderToken(tokens, idx, options) | ||
} | ||
markdownitLinkAttributes.defaultRender = function ( | ||
tokens, | ||
idx, | ||
options, | ||
env, | ||
self | ||
) { | ||
return self.renderToken(tokens, idx, options); | ||
}; | ||
module.exports = markdownitLinkAttributes | ||
module.exports = markdownitLinkAttributes; |
{ | ||
"name": "markdown-it-link-attributes", | ||
"version": "3.0.0", | ||
"version": "4.0.0", | ||
"description": "A markdown-it plugin to configure the attributes for links", | ||
"main": "index.js", | ||
"scripts": { | ||
"prebuild": "prettier --write .", | ||
"build": "node tasks/build.js && npm run minify", | ||
"minify": "uglifyjs dist/markdown-it-link-attributes.js > dist/markdown-it-link-attributes.min.js", | ||
"lint": "standard | snazzy", | ||
"lint": "eslint", | ||
"pretest": "npm run lint && npm run build", | ||
"test": "mocha", | ||
"test": "jest", | ||
"prepublishOnly": "npm run build" | ||
@@ -30,29 +31,14 @@ }, | ||
"devDependencies": { | ||
"browserify": "^16.5.0", | ||
"chai": "^4.1.2", | ||
"chalk": "^2.1.0", | ||
"browserify": "^17.0.0", | ||
"chalk": "^4.1.0", | ||
"check-ecmascript-version-compatibility": "^0.1.1", | ||
"mocha": "^6.2.1", | ||
"rimraf": "^3.0.0", | ||
"sinon": "^7.5.0", | ||
"sinon-chai": "^3.3.0", | ||
"snazzy": "^8.0.0", | ||
"standard": "^14.3.1", | ||
"uglify-js": "^3.1.0" | ||
"eslint": "^8.5.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"jest": "^27.4.5", | ||
"markdown-it": "latest", | ||
"prettier": "^2.5.1", | ||
"rimraf": "^3.0.2", | ||
"uglify-js": "^3.14.5" | ||
}, | ||
"standard": { | ||
"globals": [ | ||
"after", | ||
"afterEach", | ||
"before", | ||
"beforeEach", | ||
"context", | ||
"describe", | ||
"expect", | ||
"it", | ||
"sandbox", | ||
"xdescribe", | ||
"xcontext", | ||
"xit" | ||
], | ||
"eslint": { | ||
"ignore": [ | ||
@@ -59,0 +45,0 @@ "dist/" |
138
README.md
@@ -21,15 +21,15 @@ # markdown-it-link-attributes | ||
```js | ||
var md = require('markdown-it')() | ||
var mila = require('markdown-it-link-attributes') | ||
var md = require("markdown-it")(); | ||
var mila = require("markdown-it-link-attributes"); | ||
md.use(mila, { | ||
attrs: { | ||
target: '_blank', | ||
rel: 'noopener' | ||
} | ||
}) | ||
target: "_blank", | ||
rel: "noopener", | ||
}, | ||
}); | ||
var result = md.render('[Example](https://example.com') | ||
var result = md.render("[Example](https://example.com"); | ||
result // <a href="https://example.com" target="_blank" rel="noopener">Example</a> | ||
result; // <a href="https://example.com" target="_blank" rel="noopener">Example</a> | ||
``` | ||
@@ -40,52 +40,54 @@ | ||
```js | ||
var md = require('markdown-it')({ | ||
linkify: true | ||
}) | ||
var md = require("markdown-it")({ | ||
linkify: true, | ||
}); | ||
md.use(mila, { | ||
target: '_blank', | ||
rel: 'noopener' | ||
}) | ||
target: "_blank", | ||
rel: "noopener", | ||
}); | ||
var html = md.render('foo https://google.com bar') | ||
html // <p>foo <a href="https://google.com" target="_blank" rel="noopener">https://google.com</a> bar</p> | ||
var html = md.render("foo https://google.com bar"); | ||
html; // <p>foo <a href="https://google.com" target="_blank" rel="noopener">https://google.com</a> bar</p> | ||
``` | ||
### Pattern | ||
### Applying classes | ||
You can also specify a pattern property. The link's href property will be checked against the pattern RegExp provided and only apply the attributes if it matches the pattern. | ||
You can apply a `class` to a link by using a `class` or a `className` property. Either one will work, but use only one, not both. | ||
```js | ||
md.use(mila, { | ||
pattern: /^https:/, | ||
attrs: { | ||
target: '_blank', | ||
rel: 'noopener' | ||
} | ||
}) | ||
class: "my-class", | ||
}, | ||
}); | ||
var matchingResult = md.render('[Matching Example](https://example.com') | ||
var ignoredResult = md.render('[Not Matching Example](http://example.com') | ||
matchingResult // <a href="https://example.com" target="_blank" rel="noopener">Matching Example</a> | ||
ignoredResult // <a href="http://example.com">Not Matching Example</a> | ||
// or | ||
md.use(mila, { | ||
attrs: { | ||
className: "my-class", | ||
}, | ||
}); | ||
``` | ||
### Applying classes | ||
### Conditionally apply attributes | ||
You can either apply a `class` to a link by using a `class` or a `className` property. Either one will work, but use only one, not both. | ||
You can choose to test a link's `href` against a matcher function. The attributes will be applied only if the matcher function returns true. | ||
```js | ||
md.use(mila, { | ||
matcher(href, config) { | ||
return href.startsWith("https:"); | ||
}, | ||
attrs: { | ||
class: 'my-class' | ||
} | ||
}) | ||
target: "_blank", | ||
rel: "noopener", | ||
}, | ||
}); | ||
// or | ||
md.use(mila, { | ||
attrs: { | ||
className: 'my-class' | ||
} | ||
}) | ||
var matchingResult = md.render("[Matching Example](https://example.com"); | ||
var ignoredResult = md.render("[Not Matching Example](http://example.com"); | ||
matchingResult; // <a href="https://example.com" target="_blank" rel="noopener">Matching Example</a> | ||
ignoredResult; // <a href="http://example.com">Not Matching Example</a> | ||
``` | ||
@@ -98,26 +100,30 @@ | ||
```js | ||
md.use(mila, [{ | ||
pattern: /^https?:\/\//, | ||
attrs: { | ||
class: 'external-link' | ||
} | ||
}, { | ||
pattern: /^\//, | ||
attrs: { | ||
class: 'absolute-link' | ||
} | ||
}, { | ||
pattern: /blue/, | ||
attrs: { | ||
class: 'link-that-contains-the-word-blue' | ||
} | ||
}]) | ||
md.use(mila, [ | ||
{ | ||
pattern: /^https?:\/\//, | ||
attrs: { | ||
class: "external-link", | ||
}, | ||
}, | ||
{ | ||
pattern: /^\//, | ||
attrs: { | ||
class: "absolute-link", | ||
}, | ||
}, | ||
{ | ||
pattern: /blue/, | ||
attrs: { | ||
class: "link-that-contains-the-word-blue", | ||
}, | ||
}, | ||
]); | ||
var externalResult = md.render('[external](https://example.com') | ||
var absoluteResult = md.render('[absolute](/some-page') | ||
var blueResult = md.render('[blue](relative/link/with/blue/in/the/name') | ||
var externalResult = md.render("[external](https://example.com"); | ||
var absoluteResult = md.render("[absolute](/some-page"); | ||
var blueResult = md.render("[blue](relative/link/with/blue/in/the/name"); | ||
externalResult // <a href="https://example.com" class="external-link">external</a> | ||
absoluteResult // <a href="/some-page" class="absolute-link">absolute</a> | ||
blueResult // <a href="relative/link/with/blue/in/the/name" class="link-that-contains-the-word-blue">blue</a> | ||
externalResult; // <a href="https://example.com" class="external-link">external</a> | ||
absoluteResult; // <a href="/some-page" class="absolute-link">absolute</a> | ||
blueResult; // <a href="relative/link/with/blue/in/the/name" class="link-that-contains-the-word-blue">blue</a> | ||
``` | ||
@@ -127,8 +133,8 @@ | ||
``` | ||
```js | ||
// This matches both the "starts with http or https" rule and the "contains the word blue" rule. | ||
// Since the http/https rule was defined first, that is the configuration that is used. | ||
var result = md.render('[external](https://example.com/blue') | ||
var result = md.render("[external](https://example.com/blue"); | ||
result // <a href="https://example.com/blue" class="external-link">external</a> | ||
result; // <a href="https://example.com/blue" class="external-link">external</a> | ||
``` | ||
@@ -139,7 +145,7 @@ | ||
_Differences in browser._ If you load script directly into the page, without a package system, the module will add itself globally as `window.markdownitLinkAttributes`. | ||
You need to load `dist/markdown-it-link-attributes.min.js`, if you don't use a build system. | ||
You need to load `dist/markdown-it-link-attributes.min.js`, if you don't use a build system. | ||
## Testing | ||
This plugin is tested against markdown-it @ 9, 10 and latest | ||
This plugin is tested against the latest version of markdown-it | ||
@@ -146,0 +152,0 @@ ## License |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
14360
10
11
153
150
1