index.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. var visit = require('unist-util-visit')
  2. var definitions = require('mdast-util-definitions')
  3. var spaceSeparated = require('space-separated-tokens').parse
  4. var absolute = require('is-absolute-url')
  5. var extend = require('extend')
  6. module.exports = externalLinks
  7. var defaultTarget = '_blank'
  8. var defaultRel = ['nofollow', 'noopener', 'noreferrer']
  9. var defaultProtocols = ['http', 'https']
  10. function externalLinks(options) {
  11. var settings = options || {}
  12. var target = settings.target
  13. var rel = settings.rel
  14. var protocols = settings.protocols || defaultProtocols
  15. var content = settings.content
  16. var contentProperties = settings.contentProperties || {}
  17. if (typeof rel === 'string') {
  18. rel = spaceSeparated(rel)
  19. }
  20. if (content && typeof content === 'object' && !('length' in content)) {
  21. content = [content]
  22. }
  23. return transform
  24. function transform(tree) {
  25. var definition = definitions(tree)
  26. visit(tree, ['link', 'linkReference'], visitor)
  27. function visitor(node) {
  28. var ctx = node.type === 'link' ? node : definition(node.identifier)
  29. var protocol
  30. var data
  31. var props
  32. /* istanbul ignore if - undefined references can be injected into the tree
  33. * by plugins. */
  34. if (!ctx) return
  35. protocol = ctx.url.slice(0, ctx.url.indexOf(':'))
  36. if (absolute(ctx.url) && protocols.indexOf(protocol) !== -1) {
  37. data = node.data || (node.data = {})
  38. props = data.hProperties || (data.hProperties = {})
  39. if (target !== false) {
  40. props.target = target || defaultTarget
  41. }
  42. if (rel !== false) {
  43. props.rel = (rel || defaultRel).concat()
  44. }
  45. if (content) {
  46. // `fragment` is not a known mdast node, but unknown nodes with
  47. // children are handled as elements by `mdast-util-to-hast`:
  48. // See: <https://github.com/syntax-tree/mdast-util-to-hast#notes>.
  49. node.children.push({
  50. type: 'fragment',
  51. children: [],
  52. data: {
  53. hName: 'span',
  54. hProperties: extend(true, contentProperties),
  55. hChildren: extend(true, content)
  56. }
  57. })
  58. }
  59. }
  60. }
  61. }
  62. }