Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

markdown-it-link-attributes

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

markdown-it-link-attributes - npm Package Compare versions

Comparing version 3.0.0 to 4.0.0

.eslintrc

84

dist/markdown-it-link-attributes.js
(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)});

@@ -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/"

@@ -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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc