Skip to content

Commit

Permalink
Significantly improved type declarations
Browse files Browse the repository at this point in the history
Fixes #376
  • Loading branch information
Nick Frasser committed Feb 4, 2022
1 parent b8611c9 commit 9733da4
Show file tree
Hide file tree
Showing 15 changed files with 329 additions and 201 deletions.
44 changes: 25 additions & 19 deletions packages/linkify-element/src/linkify-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const HTML_NODE = 1, TXT_NODE = 3;

/**
* @param {HTMLElement} parent
* @param {Text | HTMLElement} oldChild
* @param {Text | HTMLElement | ChildNode} oldChild
* @param {Array<Text | HTMLElement>} newChildren
*/
function replaceChildWithChildren(parent, oldChild, newChildren) {
Expand All @@ -20,21 +20,21 @@ function replaceChildWithChildren(parent, oldChild, newChildren) {
}

/**
* @param {MultiToken[]} tokens
* @param {Object} opts
* @param {Document} doc A
* @param {import('linkifyjs').MultiToken[]} tokens
* @param {import('linkifyjs').Options} options
* @param {Document} doc Document implementation
* @returns {Array<Text | HTMLElement>}
*/
function tokensToNodes(tokens, opts, doc) {
function tokensToNodes(tokens, options, doc) {
const result = [];
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];
if (token.t === 'nl' && opts.get('nl2br')) {
if (token.t === 'nl' && options.get('nl2br')) {
result.push(doc.createElement('br'));
} else if (!token.isLink || !opts.check(token)) {
} else if (!token.isLink || !options.check(token)) {
result.push(doc.createTextNode(token.toString()));
} else {
result.push(opts.render(token));
result.push(options.render(token));
}
}

Expand All @@ -43,20 +43,20 @@ function tokensToNodes(tokens, opts, doc) {

/**
* Requires document.createElement
* @param {HTMLElement} element
* @param {Options} opts
* @param {HTMLElement | ChildNode} element
* @param {import('linkifyjs').Options} options
* @param {Document} doc
* @returns {HTMLElement}
*/
function linkifyElementHelper(element, opts, doc) {
function linkifyElementHelper(element, options, doc) {

// Can the element be linkified?
if (!element || element.nodeType !== HTML_NODE) {
throw new Error(`Cannot linkify ${element} - Invalid DOM Node type`);
}

// Is this element already a link?
if (element.tagName === 'A' || opts.ignoreTags.indexOf(element.tagName) >= 0) {
if (element.tagName === 'A' || options.ignoreTags.indexOf(element.tagName) >= 0) {
// No need to linkify
return element;
}
Expand All @@ -68,7 +68,7 @@ function linkifyElementHelper(element, opts, doc) {

switch (childElement.nodeType) {
case HTML_NODE:
linkifyElementHelper(childElement, opts, doc);
linkifyElementHelper(childElement, options, doc);
break;
case TXT_NODE: {
str = childElement.nodeValue;
Expand All @@ -79,7 +79,7 @@ function linkifyElementHelper(element, opts, doc) {
break;
}

nodes = tokensToNodes(tokens, opts, doc);
nodes = tokensToNodes(tokens, options, doc);

// Swap out the current child for the set of nodes
replaceChildWithChildren(element, childElement, nodes);
Expand Down Expand Up @@ -123,11 +123,11 @@ function getDefaultRender(doc) {
* convert them to anchor tags.
*
* @param {HTMLElement} element A DOM node to linkify
* @param {Object} opts linkify options
* @param {import('linkifyjs').Opts} [opts] linkify options
* @param {Document} [doc] (optional) window.document implementation, if differs from global
* @returns {HTMLElement}
*/
export default function linkifyElement(element, opts, doc = null) {
export default function linkifyElement(element, opts = null, doc = null) {
try {
doc = doc || document || window && window.document || global && global.document;
} catch (e) { /* do nothing for now */ }
Expand All @@ -140,12 +140,18 @@ export default function linkifyElement(element, opts, doc = null) {
);
}

opts = new Options(opts, getDefaultRender(doc));
return linkifyElementHelper(element, opts, doc);
const options = new Options(opts, getDefaultRender(doc));
return linkifyElementHelper(element, options, doc);
}

// Maintain reference to the recursive helper to cache option-normalization
// Maintain reference to the recursive helper and option-normalization for use
// in linkify-jquery
linkifyElement.helper = linkifyElementHelper;
linkifyElement.getDefaultRender = getDefaultRender;

/**
* @param {import('linkifyjs').Opts | import('linkifyjs').Options} opts
* @param {Document} doc
*/
linkifyElement.normalize = (opts, doc) => new Options(opts, getDefaultRender(doc));

2 changes: 1 addition & 1 deletion packages/linkify-element/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"allowJs": true,
"declaration": true,
"emitDeclarationOnly": true,
"maxNodeModuleJsDepth": 1,
"maxNodeModuleJsDepth": 2,
"outDir": "."
}
}
18 changes: 10 additions & 8 deletions packages/linkify-html/src/linkify-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Doctype = 'Doctype';

/**
* @param {string} str html string to link
* @param {object} [opts] linkify options
* @param {import('linkifyjs').Opts} [opts] linkify options
* @returns {string} resulting string
*/
export default function linkifyHtml(str, opts = {}) {
Expand All @@ -21,7 +21,7 @@ export default function linkifyHtml(str, opts = {}) {
const linkifiedTokens = [];
const linkified = [];

opts = new Options(opts, defaultRender);
const options = new Options(opts, defaultRender);

// Linkify the tokens given by the parser
for (let i = 0; i < tokens.length; i++) {
Expand All @@ -32,7 +32,7 @@ export default function linkifyHtml(str, opts = {}) {

// Ignore all the contents of ignored tags
const tagName = token.tagName.toUpperCase();
const isIgnored = tagName === 'A' || opts.ignoreTags.indexOf(tagName) >= 0;
const isIgnored = tagName === 'A' || options.ignoreTags.indexOf(tagName) >= 0;
if (!isIgnored) { continue; }

let preskipLen = linkifiedTokens.length;
Expand All @@ -43,7 +43,7 @@ export default function linkifyHtml(str, opts = {}) {
linkifiedTokens.push(token);
} else {
// Valid text token, linkify it!
const linkifedChars = linkifyChars(token.chars, opts);
const linkifedChars = linkifyChars(token.chars, options);
linkifiedTokens.push.apply(linkifiedTokens, linkifedChars);
}
}
Expand Down Expand Up @@ -91,27 +91,29 @@ export default function linkifyHtml(str, opts = {}) {
/**
`tokens` and `token` in this section referes to tokens returned by
`linkify.tokenize`. `linkified` will contain HTML Parser-style tokens
@param {string}
@param {import('linkifyjs').Options}
*/
function linkifyChars(str, opts) {
function linkifyChars(str, options) {
const tokens = linkify.tokenize(str);
const result = [];

for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];

if (token.t === 'nl' && opts.nl2br) {
if (token.t === 'nl' && options.nl2br) {
result.push({
type: StartTag,
tagName: 'br',
attributes: [],
selfClosing: true
});
} else if (!token.isLink || !opts.check(token)) {
} else if (!token.isLink || !options.check(token)) {
result.push({ type: Chars, chars: token.toString() });
} else {
result.push({
type: LinkifyResult,
rendered: opts.render(token)
rendered: options.render(token)
});
}
}
Expand Down
32 changes: 15 additions & 17 deletions packages/linkify-jquery/src/linkify-jquery.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ export default function apply($, doc = false) {
}

function jqLinkify(opts) {
opts = linkifyElement.normalize(opts, doc);
const options = linkifyElement.normalize(opts, doc);
return this.each(function () {
linkifyElement.helper(this, opts, doc);
linkifyElement.helper(this, options, doc);
});
}

Expand All @@ -44,58 +44,56 @@ export default function apply($, doc = false) {
const target = data.linkify;
const nl2br = data.linkifyNl2br;

let options = {
const opts = {
nl2br: !!nl2br && nl2br !== 0 && nl2br !== 'false'
};

if ('linkifyAttributes' in data) {
options.attributes = data.linkifyAttributes;
opts.attributes = data.linkifyAttributes;
}

if ('linkifyDefaultProtocol' in data) {
options.defaultProtocol = data.linkifyDefaultProtocol;
opts.defaultProtocol = data.linkifyDefaultProtocol;
}

if ('linkifyEvents' in data) {
options.events = data.linkifyEvents;
opts.events = data.linkifyEvents;
}

if ('linkifyFormat' in data) {
options.format = data.linkifyFormat;
opts.format = data.linkifyFormat;
}

if ('linkifyFormatHref' in data) {
options.formatHref = data.linkifyFormatHref;
opts.formatHref = data.linkifyFormatHref;
}

if ('linkifyTagname' in data) {
options.tagName = data.linkifyTagname;
opts.tagName = data.linkifyTagname;
}

if ('linkifyTarget' in data) {
options.target = data.linkifyTarget;
opts.target = data.linkifyTarget;
}

if ('linkifyRel' in data) {
options.rel = data.linkifyRel;
opts.rel = data.linkifyRel;
}

if ('linkifyValidate' in data) {
options.validate = data.linkifyValidate;
opts.validate = data.linkifyValidate;
}

if ('linkifyIgnoreTags' in data) {
options.ignoreTags = data.linkifyIgnoreTags;
opts.ignoreTags = data.linkifyIgnoreTags;
}

if ('linkifyClassName' in data) {
options.className = data.linkifyClassName;
opts.className = data.linkifyClassName;
}

options = linkifyElement.normalize(options);

const $target = target === 'this' ? $this : $this.find(target);
$target.linkify(options);
$target.linkify(opts);
});
});
}
Expand Down
2 changes: 1 addition & 1 deletion packages/linkify-react/src/linkify-react.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function linkifyReactElement(element, opts, elementId = 0) {
/**
* @template P
* @template {string | React.JSXElementConstructor<P>} T
* @param {P & { as?: T, tagName?: T, tagName?: T, options?: any, children?: React.ReactNode}} props
* @param {P & { as?: T, tagName?: T, tagName?: T, options?: import('linkifyjs').Opts, children?: React.ReactNode}} props
* @returns {React.ReactElement<P, T>}
*/
const Linkify = (props) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/linkify-string/src/linkify-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function defaultRender({ tagName, attributes, content }) {
* interface if you need to parse HTML entities.
*
* @param {string} str string to linkify
* @param {object} [opts] overridable options
* @param {import('linkifyjs').Opts} [opts] overridable options
* @returns {string}
*/
function linkifyStr(str, opts = {}) {
Expand Down
12 changes: 10 additions & 2 deletions packages/linkifyjs/src/assign.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
const assign = Object.assign || ((target, properties) => {
/**
* @template A
* @template B
* @param {A} target
* @param {B} properties
* @return {A & B}
*/
const assign = (target, properties) => {
for (const key in properties) {
target[key] = properties[key];
}
});
return target;
};

export default assign;
Loading

0 comments on commit 9733da4

Please sign in to comment.