An MIT-licensed ES6 Javascript module for generating links in any format from a URL.
This code was written by Bart Busschots to speed up the creation of shownotes for the Let's Talk Apple and the Security Bits segments on the NosillaCast. It is released open-source as a courtesy to other podcasters and bloggers who regularly need to covert URLs into nicely formatted links.
Pull requests and issues are welcomed, but on the understanding that this is a volunteer-maintained package, and all responses will be at the maintainer's discression as and when they have time. Realistically, you won't hear back from days or weeks, and if life is very hectic, perhaps even months.
Given this reality, do not use this repository for anything mission-critical!.
This module's reason for existing is to take a URL, fetch and parse the web page's HTML to extract the page and section titles, pass the extracted data through a transformer function appropriate for the domain to extract the page's title, then render that to a link in any language using a desired template.
This is not a module for simply converting a URL to a generic link. What makes it different is:
- Link titles are automatically exctracted from the actual web page using customiusable data transformers
- Links can be rendered in any language using customisible templates.
- Web page processing functions and output templates are associated with domain names in a DNS-aware way
Data transformers and templates are resolved using the DNS hierarchy. For example, if you register a data transformer for the domain bartificer.ie, and then you process a link on the www.bartificer.ie domain, the module will first check if there is a transformer registered for www.bartificer.ie, if not it will find the one registered for bartificer.ie and use that. This means that the data transformer and template registered against the DNS root domain . acts as defaults for all domains that don't have their own custom settings.
To use this module you will need to write your own NodeJS script that:
- Imports this module
- Registers your required templates and data transformers
- Invokes the module's link generation function
If this is more than you need, this module is not for you!
Before you begin, make sure you have the latest LTS version of NodeJS installed!
Create an empty folder and open a shell in that folder.
First, install the module into your folder with the command:
npm install '@bartificer/linkifier';Test the module is working with a basic script that uses all the defaults and makes no customisations. Create a file named test.mjs with the following content:
import { linkify } from '@bartificer/linkify';
(async () => {
console.log(await linkify.generateLink('https://github.com/bartificer'));
})();Execute this script with the command:
node ./examples/clipboardURLToMarkdown.mjsThis should print an HTML link to this module's Git repository.
The module is very much intended to be customised, and while the module has been designed to make your customisation code concise and as self-documenting as possible, it's vital to understand the module's process for generating links.
The module's generateLink(url) function is the primary entry point, and the only required argument is a URL.
This URL will be converted to a PageData object which capture's the various titles and headings found on the page.
Based on the URL's domain, a data transformer will be resolved, and that function will convert the PageData object to a LinkData object containing just the fields needed to render a link.
Based on the URL's domain, a LinkTemplate will be resolved, and that template will be combined with the LinkData object to render the link.
flowchart TD
classDef inputNode fill:#090,color:#fff;
URL([fa:fa-circle-down URL]):::inputNode
TPLNAME([fa:fa-circle-down Template Name — Optional]):::inputNode
TPLMAP[(Domain → Default Template Mappings)]
TPLS[(Registered Tempaltes)]
TRANSMAP[(Domain → Transformer Mappings)]
FETCH{Try Fetch Page}
HAVETPLNAME{Template Name Specified?}
PARSE[fa:fa-gears Parse]
REVSLUG[fa:fa-gears Reverse Slug]
RSLVTPLNAME[fa:fa-gears Resolve Template Name]
RSLVTPL[fa:fa-gears Resolve Template]
RSLVTRANS[fa:fa-gears Resolve Transformer]
TRANS[fa:fa-gears Transform]
RENDER[fa:fa-gears Render]
PDATA{{fa:fa-table-cells PageData Object}}
LDATA{{fa:fa-table-cells LinkData Object}}
TPLNAMESTR{{fa:fa-quote-left Template Name}}
TPLOBJ{{fa:fa-table-cells Template Object}}
TRANSFN{{fa:fa-code Transformer Function}}
classDef outputNode fill:#090,color:#fff;
LINK([fa:fa-quote-left Link]):::outputNode
URL --> FETCH
TPLNAME --> HAVETPLNAME
FETCH -->|Success| PARSE
FETCH -->|Fail| REVSLUG
PARSE --> PDATA
REVSLUG --> PDATA
HAVETPLNAME -->|Yes| TPLNAMESTR
HAVETPLNAME -->|No| RSLVTPLNAME
TPLMAP --> RSLVTPLNAME
RSLVTPLNAME --> TPLNAMESTR
TPLNAMESTR --> RSLVTPL
RSLVTPL --> TPLOBJ
TPLS --> RSLVTPL
TRANSMAP --> RSLVTRANS
RSLVTRANS --> TRANSFN
PDATA --> TRANS
TRANSFN --> TRANS
TRANS --> LDATA
LDATA --> RENDER
TPLOBJ --> RENDER
RENDER --> LINK
To customise the module effectively you'll need the API documentation — bartificer.github.io/linkify.
Before rendering links, you should do the following:
- Use an expanded import with at least the following:
import {linkify, LinkData, LinkTemplate} from '@bartificer/linkify';
- If none of the out-of-the-box templates are appropriate (
linkify.templateNamesis the array of registered template names), register a custom template of you own and make it the defaukt. For example:// register a template for Markdown links with an emoji pre-fixed linkify.registerTemplate('md-emoji', '🔗 [{{{title}}}]({{{url}}})'); // make the new template the default for all domains linkfiy.registerDefaultTemplateMapping('.', 'md-emoji');
- If the default data transformer's logic does not fit with your needs, register a new default. For example:
linkify.registerTransformer('.', (pData) => { new LinkData(pData.url, pData.title.replace(/ · GitHub$/, ' on GitHub')) });
- Register all needed domain-specific custom transformers. For Example:
linkify.RegisterTransformer('some.domain', (pData) => { new LinkData(pData.url, pData.h1s[1]) });
- Very rarely, a different tempalte is required for a given domain, in that case, assign the desirec tempalte at the domain level. For example:
// create a special template for your home domain linkify.registerTemplate('md-home', '🏠 [{{{title}}}]({{{url}}})'); // set that template as the default for just your domain (and its subdomains) linkfiy.registerDefaultTemplateMapping('your.home.domain', 'md-home');
Note: these examples are written to work on a development clone of the module, to use them outside of that, change the import statements to import from '@bartificer/linkify' rather than '../dist.index.js'. Alternatively, fork, download and build the module (npm ci && npm run build).
Two real-world scripts Bart users to build shownotes are included in the /example folder in the GitHub repostitory:
clipboardURLToMarkdown.mjs— the script Bart uses to convert links to Markdown for use in show notes. This script contains a real-world example of a custom template, and, of a large collection of custom transformers registered against specific domain names for dealing with their various quirks.debugClipboardURL.mjs— the script Bart uses to help develop custom transformers for any sites that need them.