@bartificer/linkify 2.3.2 → 2.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/docs/LinkData.class.mjs.html +150 -0
- package/docs/LinkTemplate.class.mjs.html +141 -0
- package/docs/Linkifier.class.mjs.html +411 -0
- package/docs/PageData.class.mjs.html +272 -0
- package/docs/data/search.json +1 -0
- package/docs/defaults.mjs.html +101 -0
- package/docs/externals.jsdoc.html +37 -0
- package/docs/fonts/Inconsolata-Regular.ttf +0 -0
- package/docs/fonts/OpenSans-Regular.ttf +0 -0
- package/docs/fonts/WorkSans-Bold.ttf +0 -0
- package/docs/index.html +28 -0
- package/docs/index.js.html +49 -0
- package/docs/module-LinkData.LinkData.html +13 -0
- package/docs/module-LinkData.html +3 -0
- package/docs/module-LinkTemplate.LinkTemplate.html +3 -0
- package/docs/module-LinkTemplate.html +3 -0
- package/docs/module-Linkifier.Linkifier.html +3 -0
- package/docs/module-Linkifier.html +3 -0
- package/docs/module-PageData.PageData.html +15 -0
- package/docs/module-PageData.html +3 -0
- package/docs/module-cheerio.html +3 -0
- package/docs/module-defaults.html +3 -0
- package/docs/module-linkify.html +3 -0
- package/docs/module-mustache.html +3 -0
- package/docs/module-node-fetch.html +3 -0
- package/docs/module-title-case.html +3 -0
- package/docs/module-urijs.html +3 -0
- package/docs/module-url-slug.html +3 -0
- package/docs/module-utilities.html +3 -0
- package/docs/scripts/core.js +726 -0
- package/docs/scripts/core.min.js +23 -0
- package/docs/scripts/resize.js +90 -0
- package/docs/scripts/search.js +265 -0
- package/docs/scripts/search.min.js +6 -0
- package/docs/scripts/third-party/Apache-License-2.0.txt +202 -0
- package/docs/scripts/third-party/fuse.js +9 -0
- package/docs/scripts/third-party/hljs-line-num-original.js +369 -0
- package/docs/scripts/third-party/hljs-line-num.js +1 -0
- package/docs/scripts/third-party/hljs-original.js +5171 -0
- package/docs/scripts/third-party/hljs.js +1 -0
- package/docs/scripts/third-party/popper.js +5 -0
- package/docs/scripts/third-party/tippy.js +1 -0
- package/docs/scripts/third-party/tocbot.js +672 -0
- package/docs/scripts/third-party/tocbot.min.js +1 -0
- package/docs/styles/clean-jsdoc-theme-base.css +1159 -0
- package/docs/styles/clean-jsdoc-theme-dark.css +412 -0
- package/docs/styles/clean-jsdoc-theme-light.css +482 -0
- package/docs/styles/clean-jsdoc-theme-scrollbar.css +30 -0
- package/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
- package/docs/styles/clean-jsdoc-theme.min.css +1 -0
- package/docs/utilities.mjs.html +151 -0
- package/examples/clipboardURLToMarkdown.mjs +74 -0
- package/examples/debugClipboardURL.mjs +7 -0
- package/package.json +8 -3
- package/src/LinkData.class.mjs +13 -0
- package/src/LinkTemplate.class.mjs +14 -0
- package/src/Linkifier.class.mjs +22 -2
- package/src/PageData.class.mjs +13 -0
- package/src/defaults.mjs +11 -0
- package/src/externals.jsdoc +35 -0
- package/src/index.js +40 -5
- package/src/utilities.mjs +21 -7
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
<!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Source: Linkifier.class.mjs</title><!--[if lt IE 9]>
|
|
2
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
3
|
+
<![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(locationPathname=document.location.pathname).substr(0,locationPathname.lastIndexOf("/")+1)</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.5 13.202L13 15.535v3.596L19.197 15 16.5 13.202zM14.697 12L12 10.202 9.303 12 12 13.798 14.697 12zM20 10.869L18.303 12 20 13.131V10.87zM19.197 9L13 4.869v3.596l3.5 2.333L19.197 9zM7.5 10.798L11 8.465V4.869L4.803 9 7.5 10.798zM4.803 15L11 19.131v-3.596l-3.5-2.333L4.803 15zM4 13.131L5.697 12 4 10.869v2.262zM2 9a1 1 0 0 1 .445-.832l9-6a1 1 0 0 1 1.11 0l9 6A1 1 0 0 1 22 9v6a1 1 0 0 1-.445.832l-9 6a1 1 0 0 1-1.11 0l-9-6A1 1 0 0 1 2 15V9z"/></symbol><symbol id="close-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></symbol><symbol id="menu-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z"/></symbol></defs></svg></head><body data-theme="fallback-light"><div class="sidebar-container"><div class="sidebar" id="sidebar"><a href="/" class="sidebar-title sidebar-title-anchor">Bartificer Linkifier</a><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-LinkData.html">LinkData</a></div><div class="sidebar-section-children"><a href="module-LinkTemplate.html">LinkTemplate</a></div><div class="sidebar-section-children"><a href="module-Linkifier.html">Linkifier</a></div><div class="sidebar-section-children"><a href="module-PageData.html">PageData</a></div><div class="sidebar-section-children"><a href="module-defaults.html">defaults</a></div><div class="sidebar-section-children"><a href="module-linkify.html">linkify</a></div><div class="sidebar-section-children"><a href="module-utilities.html">utilities</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-LinkData.LinkData.html">LinkData</a></div><div class="sidebar-section-children"><a href="module-LinkTemplate.LinkTemplate.html">LinkTemplate</a></div><div class="sidebar-section-children"><a href="module-Linkifier.Linkifier.html">Linkifier</a></div><div class="sidebar-section-children"><a href="module-PageData.PageData.html">PageData</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-externals"><div>Externals</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-cheerio.html">cheerio</a></div><div class="sidebar-section-children"><a href="module-mustache.html">mustache</a></div><div class="sidebar-section-children"><a href="module-node-fetch.html">node-fetch</a></div><div class="sidebar-section-children"><a href="module-title-case.html">title-case</a></div><div class="sidebar-section-children"><a href="module-urijs.html">urijs</a></div><div class="sidebar-section-children"><a href="module-url-slug.html">url-slug</a></div></div></div></div></div><div class="navbar-container" id="VuAckcnZhf"><nav class="navbar"><div class="navbar-left-items"></div><div class="navbar-right-items"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#dark-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div><nav></nav></nav></div><div class="toc-container"><div class="toc-content"><span class="bold">On this page</span><div id="eed4d2a0bfd64539bb9df78095dec881"></div></div></div><div class="body-wrapper"><div class="main-content"><div class="main-wrapper"><section id="source-page" class="source-page"><header><h1 id="title" class="has-anchor">Linkifier.class.mjs</h1></header><article><pre class="prettyprint source lang-js"><code>/**
|
|
4
|
+
* @file The definition of the main Linkifier class which provides the link rendering functionality with the help of the other classes and modules.
|
|
5
|
+
* @author Bart Busschots <opensource@bartificer.ie>
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Linkifier's core link rendering functionality.
|
|
10
|
+
* @module Linkifier
|
|
11
|
+
* @requires LinkData
|
|
12
|
+
* @requires LinkTemplate
|
|
13
|
+
* @requires PageData
|
|
14
|
+
* @requires module:node-fetch
|
|
15
|
+
* @requires module:cheerio
|
|
16
|
+
* @requires module:mustache
|
|
17
|
+
*/
|
|
18
|
+
import { PageData } from './PageData.class.mjs';
|
|
19
|
+
import { LinkData } from './LinkData.class.mjs';
|
|
20
|
+
import { LinkTemplate } from './LinkTemplate.class.mjs';
|
|
21
|
+
import * as utilities from "./utilities.mjs";
|
|
22
|
+
import * as defaults from "./defaults.mjs";
|
|
23
|
+
|
|
24
|
+
import fetch from 'node-fetch';
|
|
25
|
+
import * as cheerio from 'cheerio';
|
|
26
|
+
import Mustache from 'mustache';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The class providing the link rendering functionality. Instances of this class capture the settings for generating links, and, generate links using these settings.
|
|
30
|
+
*/
|
|
31
|
+
export class Linkifier {
|
|
32
|
+
constructor(){
|
|
33
|
+
/**
|
|
34
|
+
* A mapping of domain names to data transformation functions.
|
|
35
|
+
*
|
|
36
|
+
* @private
|
|
37
|
+
* @type {Object.<FQDN, dataTransformer>}
|
|
38
|
+
*/
|
|
39
|
+
this._pageDataToLinkDataTransmformers = {
|
|
40
|
+
'.' : function(pData){
|
|
41
|
+
let text = pData.title;
|
|
42
|
+
if(pData.h1s.length === 1){
|
|
43
|
+
text = pData.mainHeading;
|
|
44
|
+
}
|
|
45
|
+
return new LinkData(pData.url, text);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A mapping of domains names to default template names.
|
|
51
|
+
*
|
|
52
|
+
* @private
|
|
53
|
+
* @type {Object.<FQDN, templateName>}
|
|
54
|
+
*/
|
|
55
|
+
this._pageDataToLinkTemplateName = {
|
|
56
|
+
'.' : 'html' // default to the 'html' template for all domains unless otherwise specified
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The registered link templates.
|
|
61
|
+
*
|
|
62
|
+
* @private
|
|
63
|
+
* @type {Object.<templateName, module:@bartificer/linkify.LinkTemplate>}
|
|
64
|
+
*/
|
|
65
|
+
this._linkTemplates = {};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The loaded list of words with customised capitalisations.
|
|
69
|
+
*
|
|
70
|
+
* @private
|
|
71
|
+
* @type {string[]}
|
|
72
|
+
*/
|
|
73
|
+
this._speciallyCapitalisedWords = [];
|
|
74
|
+
defaults.speciallyCapitalisedWords.map(word => this._speciallyCapitalisedWords.push(word));
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* A collection of utility functions.
|
|
78
|
+
*
|
|
79
|
+
* @private
|
|
80
|
+
* @type {Object.<string, Function>}
|
|
81
|
+
*/
|
|
82
|
+
this._utilities = utilities;
|
|
83
|
+
|
|
84
|
+
//
|
|
85
|
+
// -- Create and register the default templates --
|
|
86
|
+
//
|
|
87
|
+
for (const [name, template] of Object.entries(defaults.linkTemplates)) {
|
|
88
|
+
this.registerTemplate(name, template);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @type {Object.<string, Function>}
|
|
94
|
+
*/
|
|
95
|
+
get utilities() {
|
|
96
|
+
return this._utilities;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @see Linfifier.utilities
|
|
101
|
+
*/
|
|
102
|
+
get util(){
|
|
103
|
+
return this._utilities;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @returns {string[]} The current list of known words with special capitalisations.
|
|
108
|
+
*/
|
|
109
|
+
get speciallyCapitalisedWords(){
|
|
110
|
+
const ans = [];
|
|
111
|
+
this._speciallyCapitalisedWords.map(word => ans.push(word));
|
|
112
|
+
return ans;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @param {string[]} words - a list of words with special capitalisations
|
|
117
|
+
*/
|
|
118
|
+
set speciallyCapitalisedWords(words){
|
|
119
|
+
// TO DO - add validation
|
|
120
|
+
|
|
121
|
+
this._speciallyCapitalisedWords = words;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Register a data transformer function for a given domain.
|
|
126
|
+
*
|
|
127
|
+
* @param {domainName} domain - The domain for which this transformer should be
|
|
128
|
+
* used.
|
|
129
|
+
* @param {dataTransformer} transformerFn - The data transformer callback.
|
|
130
|
+
* @throws {ValidationError} A validation error is thrown if either parameter
|
|
131
|
+
* is missing or invalid.
|
|
132
|
+
*/
|
|
133
|
+
registerTransformer(domain, transformerFn){
|
|
134
|
+
// TO DO - add validation
|
|
135
|
+
|
|
136
|
+
let fqdn = String(domain);
|
|
137
|
+
if(!fqdn.match(/[.]$/)){
|
|
138
|
+
fqdn += '.';
|
|
139
|
+
}
|
|
140
|
+
this._pageDataToLinkDataTransmformers[fqdn] = transformerFn;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get the data transformer function for a given domain.
|
|
145
|
+
*
|
|
146
|
+
* Note that domains are searched from the subdomain up. For example, if passed
|
|
147
|
+
* the domain `www.bartificer.net` the function will first look for a
|
|
148
|
+
* transformer for the domain `www.bartificer.net`, if there's no transformer
|
|
149
|
+
* registered for that domain it will look for a transformer for the domain
|
|
150
|
+
* `bartificer.net`, if there's no transformer for that domain either it will
|
|
151
|
+
* return the default transformer.
|
|
152
|
+
*
|
|
153
|
+
* @param {domainName} domain - The domain to get the data transformer for.
|
|
154
|
+
* @returns {dataTransformer}
|
|
155
|
+
* @throws {ValidationError} A validation error is thrown unless a valid domain
|
|
156
|
+
* name is passed.
|
|
157
|
+
*/
|
|
158
|
+
getTransformerForDomain(domain){
|
|
159
|
+
// TO DO - add validation
|
|
160
|
+
|
|
161
|
+
let fqdn = String(domain);
|
|
162
|
+
if(!fqdn.match(/[.]$/)){
|
|
163
|
+
fqdn += '.';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// return the most exact match
|
|
167
|
+
while(fqdn.match(/[.][^.]+[.]$/)){
|
|
168
|
+
if(this._pageDataToLinkDataTransmformers[fqdn]){
|
|
169
|
+
//console.log(`returning transformer for '${fqdn}'`);
|
|
170
|
+
return this._pageDataToLinkDataTransmformers[fqdn];
|
|
171
|
+
}
|
|
172
|
+
//console.log(`no transformer found for '${fqdn}'`);
|
|
173
|
+
fqdn = fqdn.replace(/^[^.]+[.]/, '');
|
|
174
|
+
}
|
|
175
|
+
//console.log('returning default transformer');
|
|
176
|
+
return this._pageDataToLinkDataTransmformers['.'];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* A list of the names of the registered link templates.
|
|
181
|
+
* @type {string[]}
|
|
182
|
+
*/
|
|
183
|
+
get templateNames() {
|
|
184
|
+
return Object.keys(this._linkTemplates);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @returns {string} The name of the default template.
|
|
189
|
+
*/
|
|
190
|
+
get defaultTemplateName(){
|
|
191
|
+
return this._pageDataToLinkTemplateName['.'];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* @param {string} templateName - The name of the default template to use.
|
|
196
|
+
* @throws {ValidationError} A validation error is thrown if the template name is missing, invalid, or doesn't correspond to a registered template.
|
|
197
|
+
*/
|
|
198
|
+
set defaultTemplateName(templateName){
|
|
199
|
+
const tplName = String(templateName);
|
|
200
|
+
if(!this._linkTemplates[tplName]){
|
|
201
|
+
throw new ValidationError(`No template named '${tplName}' is registered`);
|
|
202
|
+
}
|
|
203
|
+
this._pageDataToLinkTemplateName['.'] = tplName;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* The default link template.
|
|
208
|
+
* @type {LinkTemplate}
|
|
209
|
+
*/
|
|
210
|
+
get defaultTemplate(){
|
|
211
|
+
return this._linkTemplates[this._pageDataToLinkTemplateName['.']];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Register a link template.
|
|
216
|
+
*
|
|
217
|
+
* @param {templateName} name
|
|
218
|
+
* @param {module:@bartificer/linkify.LinkTemplate} template
|
|
219
|
+
* @throws {ValidationError} A validation error is thrown unless both a valid
|
|
220
|
+
* name and template object are passed.
|
|
221
|
+
*/
|
|
222
|
+
registerTemplate(name, template){
|
|
223
|
+
// TO DO - add validation
|
|
224
|
+
const tplName = String(name);
|
|
225
|
+
|
|
226
|
+
this._linkTemplates[tplName] = template;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Get a registered link template by name.
|
|
231
|
+
*
|
|
232
|
+
* @param {string} templateName
|
|
233
|
+
* @returns {LinkTemplate}
|
|
234
|
+
* @throws {ValidationError} A validation error is thrown unless a valid name is passed and corresponds to a registered template.
|
|
235
|
+
*/
|
|
236
|
+
getTemplate(templateName){
|
|
237
|
+
const tplName = String(templateName);
|
|
238
|
+
|
|
239
|
+
if(!this._linkTemplates[tplName]){
|
|
240
|
+
throw new ValidationError(`No template named '${tplName}' is registered`);
|
|
241
|
+
}
|
|
242
|
+
return this._linkTemplates[tplName];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Register a default template for use with a given domain. This template will
|
|
247
|
+
* override the overall default for this domain and all its subdomains.
|
|
248
|
+
*
|
|
249
|
+
* @param {domainName} domain - The domain for which this template should be used by default.
|
|
250
|
+
* @param {templateName} templateName - The name of the template to use.
|
|
251
|
+
* @throws {ValidationError} A validation error is thrown if either parameter
|
|
252
|
+
* is missing or invalid.
|
|
253
|
+
*/
|
|
254
|
+
registerDefaultTemplateMapping(domain, templateName){
|
|
255
|
+
// TO DO - add validation
|
|
256
|
+
|
|
257
|
+
let fqdn = String(domain);
|
|
258
|
+
if(!fqdn.match(/[.]$/)){
|
|
259
|
+
fqdn += '.';
|
|
260
|
+
}
|
|
261
|
+
this._pageDataToLinkTemplateName[fqdn] = templateName;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get the data transformer function for a given domain.
|
|
266
|
+
*
|
|
267
|
+
* Note that domains are searched from the subdomain up. For example, if passed
|
|
268
|
+
* the domain `www.bartificer.net` the function will first look for a
|
|
269
|
+
* transformer for the domain `www.bartificer.net`, if there's no transformer
|
|
270
|
+
* registered for that domain it will look for a transformer for the domain
|
|
271
|
+
* `bartificer.net`, if there's no transformer for that domain either it will
|
|
272
|
+
* return the default transformer.
|
|
273
|
+
*
|
|
274
|
+
* @param {domainName} domain - The domain to get the data transformer for.
|
|
275
|
+
* @returns {dataTransformer}
|
|
276
|
+
* @throws {ValidationError} A validation error is thrown unless a valid domain
|
|
277
|
+
* name is passed.
|
|
278
|
+
*/
|
|
279
|
+
getTemplateNameForDomain(domain){
|
|
280
|
+
// TO DO - add validation
|
|
281
|
+
|
|
282
|
+
let fqdn = String(domain);
|
|
283
|
+
if(!fqdn.match(/[.]$/)){
|
|
284
|
+
fqdn += '.';
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// return the most exact match
|
|
288
|
+
while(fqdn.match(/[.][^.]+[.]$/)){
|
|
289
|
+
if(this._pageDataToLinkTemplateName[fqdn]){
|
|
290
|
+
let tplName = this._pageDataToLinkTemplateName[fqdn];
|
|
291
|
+
|
|
292
|
+
// make sure the template exists
|
|
293
|
+
if(!this._linkTemplates[tplName]){
|
|
294
|
+
console.warn(`No template named '${tplName}' is registered, falling back to global default '${this._pageDataToLinkTemplateName['.']}'`);
|
|
295
|
+
return this._pageDataToLinkTemplateName['.'];
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
//console.log(`returning template name for '${fqdn}'`);
|
|
299
|
+
return this._pageDataToLinkTemplateName[fqdn];
|
|
300
|
+
}
|
|
301
|
+
//console.log(`no template name found for '${fqdn}'`);
|
|
302
|
+
fqdn = fqdn.replace(/^[^.]+[.]/, '');
|
|
303
|
+
}
|
|
304
|
+
//console.log('returning default template name');
|
|
305
|
+
return this._pageDataToLinkTemplateName['.'];
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Fetch the page data for a given URL.
|
|
310
|
+
*
|
|
311
|
+
* @async
|
|
312
|
+
* @param {URL} url
|
|
313
|
+
* @returns {PageData}
|
|
314
|
+
* @throws {ValidationError} A validation error is thrown unless a valid URL is
|
|
315
|
+
* passed.
|
|
316
|
+
*/
|
|
317
|
+
async fetchPageData(url){
|
|
318
|
+
// TO DO - add validation
|
|
319
|
+
|
|
320
|
+
let ans = new PageData(url);
|
|
321
|
+
|
|
322
|
+
// then try load the contents form the web
|
|
323
|
+
let webDownloadResponseBody = '';
|
|
324
|
+
try {
|
|
325
|
+
let webDownloadResponse = await fetch(url);
|
|
326
|
+
if(!webDownloadResponse.ok){
|
|
327
|
+
throw new Error(`HTTP ${webDownloadResponse.status}: ${webDownloadResponse.statusText}`);
|
|
328
|
+
}
|
|
329
|
+
webDownloadResponseBody = await webDownloadResponse.text();
|
|
330
|
+
} catch (err) {
|
|
331
|
+
// fall back to extracting the title from the URL slug
|
|
332
|
+
console.warn(`Falling back to de-slugifying URL (${err.message})`);
|
|
333
|
+
ans.title = this.utilities.extractSlug(url, this._speciallyCapitalisedWords) || 'Untitled';
|
|
334
|
+
return ans;
|
|
335
|
+
}
|
|
336
|
+
let $ = cheerio.load(webDownloadResponseBody);
|
|
337
|
+
ans.title = $('title').text().trim();
|
|
338
|
+
$('h1').each(function(){
|
|
339
|
+
ans.h1($(this).text().trim());
|
|
340
|
+
});
|
|
341
|
+
$('h2').each(function(){
|
|
342
|
+
ans.h2($(this).text().trim());
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
// return the answer
|
|
346
|
+
return ans;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Generate a link given a URL. By default the registered template for the
|
|
351
|
+
* URL's domain will be used, or, if none is registered, the overall
|
|
352
|
+
* default will be used (`html`).
|
|
353
|
+
*
|
|
354
|
+
* @async
|
|
355
|
+
* @param {URL} url
|
|
356
|
+
* @param {templateName} [templateName='html']
|
|
357
|
+
* @returns {string}
|
|
358
|
+
* @throws {ValidationError} A validation error is thrown unless a valid URL is
|
|
359
|
+
* passed.
|
|
360
|
+
*/
|
|
361
|
+
async generateLink(url, templateName){
|
|
362
|
+
// TO DO - add validation
|
|
363
|
+
|
|
364
|
+
//
|
|
365
|
+
// -- resolve the template name to use for this URL --
|
|
366
|
+
//
|
|
367
|
+
let tplName = '';
|
|
368
|
+
|
|
369
|
+
// resolve the template — if a template name is passed, try use it,
|
|
370
|
+
// otherwise resolve the default for this URL's domain
|
|
371
|
+
if(templateName && typeof templateName === 'string'){
|
|
372
|
+
tplName = templateName;
|
|
373
|
+
|
|
374
|
+
// make sure the template exists
|
|
375
|
+
if(!this._linkTemplates[tplName]){
|
|
376
|
+
console.warn(`No template named '${tplName}' is registered, falling back to global default '${this._pageDataToLinkTemplateName['.']}'`);
|
|
377
|
+
tplName = this._pageDataToLinkTemplateName['.'];
|
|
378
|
+
}
|
|
379
|
+
} else {
|
|
380
|
+
tplName = this.getTemplateNameForDomain((new URL(url)).hostname);
|
|
381
|
+
}
|
|
382
|
+
const template = this._linkTemplates[tplName];
|
|
383
|
+
|
|
384
|
+
// get the page data
|
|
385
|
+
const pageData = await this.fetchPageData(url);
|
|
386
|
+
|
|
387
|
+
// transform the page data to link data
|
|
388
|
+
const linkData = this.getTransformerForDomain(pageData.uri.hostname())(pageData);
|
|
389
|
+
|
|
390
|
+
// apply field-specific filters to the link data
|
|
391
|
+
const fieldNames = ['url', 'text', 'description'];
|
|
392
|
+
const templateData = linkData.asPlainObject();
|
|
393
|
+
for(let fieldName of fieldNames){
|
|
394
|
+
let fieldFilters = template.filtersFor(fieldName);
|
|
395
|
+
for(let filterFn of fieldFilters){
|
|
396
|
+
templateData[fieldName] = filterFn(templateData[fieldName]);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// apply the universal filters to all the link data fields
|
|
401
|
+
let globalFilters = template.filtersFor('all');
|
|
402
|
+
for(let filterFn of globalFilters){
|
|
403
|
+
for(let fieldName of fieldNames){
|
|
404
|
+
templateData[fieldName] = filterFn(templateData[fieldName]);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// render the link
|
|
409
|
+
return Mustache.render(this._linkTemplates[tplName].templateString, templateData);
|
|
410
|
+
}
|
|
411
|
+
};</code></pre></article></section></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><a href="/" class="sidebar-title sidebar-title-anchor">Bartificer Linkifier</a><div class="mobile-nav-links"></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-modules"><div>Modules</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-LinkData.html">LinkData</a></div><div class="sidebar-section-children"><a href="module-LinkTemplate.html">LinkTemplate</a></div><div class="sidebar-section-children"><a href="module-Linkifier.html">Linkifier</a></div><div class="sidebar-section-children"><a href="module-PageData.html">PageData</a></div><div class="sidebar-section-children"><a href="module-defaults.html">defaults</a></div><div class="sidebar-section-children"><a href="module-linkify.html">linkify</a></div><div class="sidebar-section-children"><a href="module-utilities.html">utilities</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-LinkData.LinkData.html">LinkData</a></div><div class="sidebar-section-children"><a href="module-LinkTemplate.LinkTemplate.html">LinkTemplate</a></div><div class="sidebar-section-children"><a href="module-Linkifier.Linkifier.html">Linkifier</a></div><div class="sidebar-section-children"><a href="module-PageData.PageData.html">PageData</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-externals"><div>Externals</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="module-cheerio.html">cheerio</a></div><div class="sidebar-section-children"><a href="module-mustache.html">mustache</a></div><div class="sidebar-section-children"><a href="module-node-fetch.html">node-fetch</a></div><div class="sidebar-section-children"><a href="module-title-case.html">title-case</a></div><div class="sidebar-section-children"><a href="module-urijs.html">urijs</a></div><div class="sidebar-section-children"><a href="module-url-slug.html">url-slug</a></div></div></div><div class="mobile-navbar-actions"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#dark-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div></div></div><script type="text/javascript" src="scripts/core.min.js"></script><script src="scripts/search.min.js" defer="defer"></script><script src="scripts/third-party/fuse.js" defer="defer"></script><script type="text/javascript">var tocbotInstance=tocbot.init({tocSelector:"#eed4d2a0bfd64539bb9df78095dec881",contentSelector:".main-content",headingSelector:"h1, h2, h3",hasInnerContainers:!0,scrollContainer:".main-content",headingsOffset:130,onClick:bringLinkToView})</script></body></html>
|