diff --git a/.eslintrc.js b/.eslintrc.js index d530ad2..a571a1d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,22 +1,36 @@ +/* eslint-disable */ + module.exports = { env: { browser: true, node: true, es6: true, }, - extends: ['eslint:recommended', 'google', '@typescript-eslint/recommended'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'prettier', + ], globals: { Atomics: 'readonly', SharedArrayBuffer: 'readonly', }, parser: '@typescript-eslint/parser', parserOptions: { - ecmaVersion: 11, - sourceType: 'module', + tsconfigRootDir: __dirname, }, plugins: ['@typescript-eslint'], rules: { - indent: ['warn', 4], + indent: 'off', 'max-len': 'off', }, + overrides: [ + { + files: ['*.ts', '*.tsx'], // Your TypeScript files extension + parserOptions: { + project: ['./tsconfig.json'], // Specify it only for TypeScript files + }, + }, + ], }; diff --git a/README.md b/README.md index f503ab8..6035a54 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,7 @@ $ yarn add affiliate Or use a CDN ([check out the codeless setup](#blogs-and-related-sites)) ```html - - + ``` ## What It Can Do @@ -43,7 +42,8 @@ Affiliate has easy [plugins](https://affiliate.js.org/plugins), including one fo Read **[the documentation](https://affiliate.js.org/)** for more advanced usage. ```js -const Affiliate = require('affiliate'); +import Affiliate from 'affiliate'; + const aff = Affiliate.create({ tags: [ { @@ -60,6 +60,7 @@ const aff = Affiliate.create({ }, ], }); + aff.attach(); ``` @@ -67,33 +68,32 @@ aff.attach(); Affiliate is simple and quick to set up, even for more complex usage. Read the docs at: **[affiliate.js.org](https://affiliate.js.org/)**. -### Blogs and Related Sites +## Blogs and Related Sites -A simplified codeless solution might better suit some blogging-style sites. +A simplified codeless solution might better suit some sites that use content module systems, such as WordPress, SquareSpace, etc. -Insert this code within the HTML `...` tag. The contents of the `data-aff` attribute will tell Affiliate what to do. +Insert this code within the HTML `...` tag. The contents of the `data-auto-affiliate` attribute will tell Affiliate what to do. ```html - ``` -#### data-aff Syntax +### data-auto-affiliate Syntax -The syntax for data-aff is a comma separated list of domains, a colon, and then comma separated list of url queries in the format `key=value`. Multiple website groups can be separated by an exclamation mark. +The syntax for data-auto-affiliate is capital `WHERE`, a comma separated list of domains, capital `SET`, and then comma separated list of URL queries in the format `key=value`. Multiple website groups can be separated by a capital `AND`. -``` -amazon.com, www.amazon.com : tag = MY-AMAZON-TAG ! example.com, shop.example.com : ref = MY-OTHER-TAG +```sql +WHERE amazon.com, www.amazon.com SET tag = MY-AMAZON-TAG AND WHERE example.com, shop.example.com SET ref = MY-OTHER-TAG ``` ## Left with Questions? -If for any reason you feel that this documentation is unclear or incomplete, [add an issue](https://github.com/russellsteadman/affiliate/issues/new) detailing what needs to be improved. It will be addressed quickly. +If for any reason you feel that this documentation is unclear or incomplete, [add an issue](https://github.com/russellsteadman/affiliate/issues/new) detailing what needs to be improved. ## Star This Project diff --git a/dist/node/Affiliate.d.ts b/dist/node/Affiliate.d.ts index 05c757f..8dcf489 100644 --- a/dist/node/Affiliate.d.ts +++ b/dist/node/Affiliate.d.ts @@ -1,4 +1,3 @@ -import URLParse from 'url-parse'; import Log from './shared/log'; export interface AffiliateConfigTag { hosts: string | string[]; @@ -9,7 +8,7 @@ export interface AffiliateConfigTag { to: string; from: string; }[]; - modify?: (url: URLParse) => URLParse | string; + modify?: (url: URL) => URL | string; } export interface AffiliateConfig { tags: AffiliateConfigTag[]; @@ -33,7 +32,7 @@ declare class Affiliate { * @function * @param {object=} nodeSet The node to traverse for links (default: document.body) */ - traverse(nodeSet?: HTMLElement): void; + traverse(nodeSet?: HTMLElement): Affiliate; /** * Modify the URL of a matching link while preserving the original link state * @@ -43,18 +42,18 @@ declare class Affiliate { * @param {object} node Anchor link node * @param {object} tag Matching configuration tag */ - modifyURL: (url: URLParse, node: HTMLAnchorElement, tag: AffiliateConfigTag) => void; + modifyURL: (url: URL, node: HTMLAnchorElement, tag: AffiliateConfigTag) => void; /** * Attach the mutation observer * * @function */ - attach: () => void; + attach: () => Affiliate; /** * Detach the mutation observer * * @function */ - detach: () => void; + detach: () => Affiliate; } export default Affiliate; diff --git a/dist/node/Affiliate.js b/dist/node/Affiliate.js index 2eeab6e..fb5f0c9 100644 --- a/dist/node/Affiliate.js +++ b/dist/node/Affiliate.js @@ -3,12 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -const url_parse_1 = __importDefault(require("url-parse")); +const features_1 = require("./shared/features"); const log_1 = __importDefault(require("./shared/log")); const nodeTools_1 = require("./shared/nodeTools"); -// Check for MutationObserver -const canObserve = typeof window === 'object' && - !(typeof window.MutationObserver === 'undefined'); /** * @class Manages stateful affiliation */ @@ -33,23 +30,28 @@ class Affiliate { * @param {object} tag Matching configuration tag */ this.modifyURL = (url, node, tag) => { - var _a; + var _a, _b; // Check if URL is already modified - let linkData = (0, nodeTools_1.getNodeData)(node); + const linkData = (0, nodeTools_1.getNodeData)(node); if (linkData.is && linkData.is === url.href) return; // Preserve the original URL - let originalURL = url.href; + const originalURL = url.href; this.log(false, 'Discovered URL: ' + url.href); // Change query variables - url.set('query', Object.assign(Object.assign({}, url.query), tag.query)); + if (tag.query) { + Object.keys((_a = tag.query) !== null && _a !== void 0 ? _a : {}).forEach((key) => { + if (typeof tag.query === 'object') + url.searchParams.set(key, tag.query[key]); + }); + } // Run the modification function if (typeof tag.modify === 'function') { try { let returnedURL = tag.modify(url); if (typeof returnedURL === 'object') returnedURL = returnedURL.href; - url = (0, url_parse_1.default)(returnedURL, true); + url = new URL(returnedURL, window === null || window === void 0 ? void 0 : window.location.origin); } catch (e) { (0, log_1.default)(true, e); @@ -57,14 +59,14 @@ class Affiliate { } // Replace certain parts of the url let modifiedUrl = url.href; - (_a = tag.replace) === null || _a === void 0 ? void 0 : _a.forEach((replacement) => { + (_b = tag.replace) === null || _b === void 0 ? void 0 : _b.forEach((replacement) => { modifiedUrl = modifiedUrl.replace(replacement.from, replacement.to); }); // Update the href tag and save the url to the DOM node node.href = modifiedUrl; (0, nodeTools_1.setNodeData)(node, { was: originalURL, - is: url, + is: url.href, }); }; /** @@ -75,15 +77,15 @@ class Affiliate { this.attach = () => { // Cannot attach twice, cannot attach for node if (this.state.attached || typeof document === 'undefined') - return; + return this; // Get readyState, or the loading state of the DOM - let { readyState } = document; + const { readyState } = document; if (readyState === 'complete' || readyState === 'interactive') { // Set attached to true this.state.attached = true; // Run through the entire body tag this.traverse(); - if (canObserve && this.observer) { + if (features_1.hasMutationObserver && this.observer) { // Attach the observer this.observer.observe(document.body, { childList: true, @@ -99,8 +101,9 @@ class Affiliate { } else { // Wait until the DOM loads - return window.addEventListener('DOMContentLoaded', this.attach); + window.addEventListener('DOMContentLoaded', this.attach); } + return this; }; /** * Detach the mutation observer @@ -108,11 +111,12 @@ class Affiliate { * @function */ this.detach = () => { - if (!canObserve || !this.observer) - return; + if (!features_1.hasMutationObserver || !this.observer) + return this; this.state.attached = false; this.observer.disconnect(); this.log(false, 'Observer disconnected.'); + return this; }; // Extend the configuration config = config !== null && config !== void 0 ? config : {}; @@ -132,35 +136,35 @@ class Affiliate { ]; }); // Set logging function - this.log = config.log ? log_1.default : () => { }; + this.log = config.log ? log_1.default : () => undefined; this.log(false, 'New Instance', config); // Check is MutationObserver is supported - if (canObserve) { + if (features_1.hasMutationObserver) { // Initialize MutationObserver this.observer = new window.MutationObserver((mutations) => { // This function is called for every DOM mutation // Has a mutation been logged let emitted = false; - for (let i in mutations) { + mutations.forEach((mutation) => { // If the attributes of the link have been modified - if (mutations[i].type === 'attributes') { + if (mutation.type === 'attributes') { // Skip links without an href - if (mutations[i].attributeName !== 'href') - continue; - let href = mutations[i].target.href; - let linkData = (0, nodeTools_1.getNodeData)(mutations[i].target); + if (mutation.attributeName !== 'href') + return; + const href = mutation.target.href; + const linkData = (0, nodeTools_1.getNodeData)(mutation.target); // Skip links without a modified href if (linkData.is && linkData.is === href) - continue; + return; } // Only calls on first mutation if (!emitted) { - this.log(false, 'DOM Mutation', mutations[i]); + this.log(false, 'DOM Mutation', mutation); emitted = true; } // Scan the node and subnodes if there are any - this.traverse(mutations[i].target); - } + this.traverse(mutation.target); + }); }); } // Set internal state @@ -173,33 +177,39 @@ class Affiliate { * @param {object=} nodeSet The node to traverse for links (default: document.body) */ traverse(nodeSet = document.body) { - var _a; if (typeof nodeSet !== 'object' || typeof nodeSet.getElementsByTagName !== 'function') - return; + return this; + if (!features_1.hasURL) { + this.log(true, 'This browser needs a URL polyfill.'); + return this; + } this.log(false, 'Traversing DOM...'); // Reduce link collection to array - let collection = nodeSet.getElementsByTagName('a'); + const collection = nodeSet.getElementsByTagName('a'); let nodes = Object.values(collection); // If the nodeSet is a single link, turn to array if (nodeSet.nodeName.toLowerCase() === 'a') nodes = [nodeSet]; + this.log(false, `Found ${nodes.length + 1} nodes...`); // Go through each link - for (let o in nodes) { + nodes.forEach((node) => { + var _a; // Check if it is actually linking - if (!nodes[o] || 'href' in nodes[o]) - continue; - // Parse the URL via url-parse - let url = (0, url_parse_1.default)((_a = nodes[o].href) !== null && _a !== void 0 ? _a : '', true); + if (!node || !('href' in node)) + return; + // Parse the URL natively + const url = new URL((_a = node.href) !== null && _a !== void 0 ? _a : '', window === null || window === void 0 ? void 0 : window.location.origin); // Only modify hosts provided. if (this.state.hosts.indexOf(url.host) === -1) - continue; - for (let i in this.state.config.tags) { - if (this.state.config.tags[i].hosts.indexOf(url.host) !== -1) { - this.modifyURL(url, nodes[o], this.state.config.tags[i]); + return; + this.state.config.tags.forEach((tag) => { + if (tag.hosts.indexOf(url.host) !== -1) { + this.modifyURL(url, node, tag); } - } - } + }); + }); + return this; } } exports.default = Affiliate; diff --git a/dist/node/Affiliate.js.map b/dist/node/Affiliate.js.map index 9ddab53..f29baa0 100644 --- a/dist/node/Affiliate.js.map +++ b/dist/node/Affiliate.js.map @@ -1 +1 @@ -{"version":3,"file":"Affiliate.js","sourceRoot":"","sources":["../../src/Affiliate.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Affiliate.js","sourceRoot":"","sources":["../../src/Affiliate.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/node/index.js b/dist/node/index.js index 74214b7..cc74704 100644 --- a/dist/node/index.js +++ b/dist/node/index.js @@ -23,7 +23,7 @@ class Generator { * @returns {object} Affiliate instance */ this.create = (config) => { - let Instance = new Affiliate_1.default(config); + const Instance = new Affiliate_1.default(config); this.state.instances.push(Instance); return Instance; }; @@ -33,9 +33,7 @@ class Generator { * @function */ this.detachAll = () => { - for (let i in this.state.instances) { - this.state.instances[i].detach(); - } + this.state.instances.forEach((instance) => instance.detach()); }; /** * Revert all traversed links to their non-affiliated state @@ -44,19 +42,19 @@ class Generator { */ this.revert = () => { this.detachAll(); - let nodes = ([].slice.call(document.body.getElementsByTagName('a'))); - for (let i in nodes) { - let linkData = (0, nodeTools_1.getNodeData)(nodes[i]); - if (linkData && linkData.was) { - nodes[i].href = linkData.was; - (0, nodeTools_1.setNodeData)(nodes[i], {}); + const nodes = Object.values(document.body.getElementsByTagName('a')); + nodes.forEach((node) => { + const linkData = (0, nodeTools_1.getNodeData)(node); + if (linkData && typeof linkData.was === 'string') { + node.href = linkData.was; + (0, nodeTools_1.setNodeData)(node, {}); } - } + }); }; try { - let config = (0, autoConfig_1.default)(); + const config = (0, autoConfig_1.default)(); if (typeof config === 'object') { - let auto = this.create(config); + const auto = this.create(config); (0, log_1.default)(false, auto); this.state.auto = auto; auto.attach(); diff --git a/dist/node/index.js.map b/dist/node/index.js.map index b5dc489..88bfc59 100644 --- a/dist/node/index.js.map +++ b/dist/node/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;AAAA,qEAA6C;AAC7C,4DAAyD;AACzD,uDAA+B;AAC/B,kDAA8D;AAE9D;;GAEG;AACH,MAAM,SAAS;IAQb;QAPA,UAAK,GAGD;YACF,SAAS,EAAE,EAAE;SACd,CAAC;QAgBF;;;;;;WAMG;QACH,WAAM,GAAG,CAAC,MAAgC,EAAE,EAAE;YAC5C,IAAI,QAAQ,GAAG,IAAI,mBAAS,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpC,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC;QAWF;;;;WAIG;QACH,cAAS,GAAG,GAAG,EAAE;YACf,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;gBAClC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aAClC;QACH,CAAC,CAAC;QAEF;;;;WAIG;QACH,WAAM,GAAG,GAAG,EAAE;YACZ,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,IAAI,KAAK,GAAwB,CAC/B,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CACvD,CAAC;YACF,KAAK,IAAI,CAAC,IAAI,KAAK,EAAE;gBACnB,IAAI,QAAQ,GAAG,IAAA,uBAAW,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrC,IAAI,QAAQ,IAAI,QAAQ,CAAC,GAAG,EAAE;oBAC5B,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC;oBAC7B,IAAA,uBAAW,EAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;iBAC3B;aACF;QACH,CAAC,CAAC;QA/DA,IAAI;YACF,IAAI,MAAM,GAAG,IAAA,oBAAU,GAAE,CAAC;YAC1B,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;gBAC9B,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC/B,IAAA,aAAG,EAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACjB,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;gBACvB,IAAI,CAAC,MAAM,EAAE,CAAC;aACf;SACF;QAAC,OAAO,CAAC,EAAE;YACV,IAAA,aAAG,EAAC,IAAI,EAAE,CAAC,CAAC,CAAC;SACd;IACH,CAAC;IAeD;;;;OAIG;IACH,IAAI,SAAS;QACX,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;CA+BF;AAED,kBAAe,IAAI,SAAS,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;AAAA,qEAA6C;AAC7C,4DAAyD;AACzD,uDAA+B;AAC/B,kDAA8D;AAE9D;;GAEG;AACH,MAAM,SAAS;IAQb;QAPA,UAAK,GAGD;YACF,SAAS,EAAE,EAAE;SACd,CAAC;QAgBF;;;;;;WAMG;QACH,WAAM,GAAG,CAAC,MAAgC,EAAE,EAAE;YAC5C,MAAM,QAAQ,GAAG,IAAI,mBAAS,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpC,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC;QAWF;;;;WAIG;QACH,cAAS,GAAG,GAAG,EAAE;YACf,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAChE,CAAC,CAAC;QAEF;;;;WAIG;QACH,WAAM,GAAG,GAAG,EAAE;YACZ,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBACrB,MAAM,QAAQ,GAAG,IAAA,uBAAW,EAAC,IAAI,CAAC,CAAC;gBACnC,IAAI,QAAQ,IAAI,OAAO,QAAQ,CAAC,GAAG,KAAK,QAAQ,EAAE;oBAChD,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC;oBACzB,IAAA,uBAAW,EAAC,IAAI,EAAE,EAAE,CAAC,CAAC;iBACvB;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QA3DA,IAAI;YACF,MAAM,MAAM,GAAG,IAAA,oBAAU,GAAE,CAAC;YAC5B,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;gBAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACjC,IAAA,aAAG,EAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACjB,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;gBACvB,IAAI,CAAC,MAAM,EAAE,CAAC;aACf;SACF;QAAC,OAAO,CAAC,EAAE;YACV,IAAA,aAAG,EAAC,IAAI,EAAE,CAAU,CAAC,CAAC;SACvB;IACH,CAAC;IAeD;;;;OAIG;IACH,IAAI,SAAS;QACX,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;CA2BF;AAED,kBAAe,IAAI,SAAS,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/node/shared/autoConfig.d.ts b/dist/node/shared/autoConfig.d.ts index e581cf1..57ddcad 100644 --- a/dist/node/shared/autoConfig.d.ts +++ b/dist/node/shared/autoConfig.d.ts @@ -1,9 +1,7 @@ declare const AutoConfig: () => { tags: { hosts: string[]; - query: { - [key: string]: string; - }; + query: Record; }[]; } | undefined; export default AutoConfig; diff --git a/dist/node/shared/autoConfig.js b/dist/node/shared/autoConfig.js index 2c0e56d..17abc02 100644 --- a/dist/node/shared/autoConfig.js +++ b/dist/node/shared/autoConfig.js @@ -1,41 +1,33 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -/* Utility function for parsing data-aff syntax */ -const breakUp = (data, delimiter) => { - if (typeof data === 'object') { - for (let i in data) { - data[i] = breakUp(data[i], delimiter); - } - } - else if (typeof data === 'string') { - data = data.split(delimiter); - for (let o in data) { - data[o] = data[o].trim(); - } - } - return data; -}; +const AUTO_CONFIG_SYNTAX_REGEX = /WHERE (.+?) SET (.+?)\s*(?:AND|$)/g; /* Setup automatic configuration */ const AutoConfig = () => { - let scriptNode = document.getElementById('aff-js'); - if (typeof scriptNode === 'object' && scriptNode !== null) { - let nodeData = scriptNode.dataset.aff; + var _a; + const scriptNode = document.getElementById('aff-js'); + if (typeof scriptNode === 'object' && scriptNode) { + const nodeData = (_a = scriptNode === null || scriptNode === void 0 ? void 0 : scriptNode.dataset) === null || _a === void 0 ? void 0 : _a.autoAffiliate; if (typeof nodeData === 'string') { - let parsedData = (breakUp(breakUp(breakUp(breakUp(nodeData, '!'), ':'), ','), '=')); - let tags = []; - for (let i in parsedData) { - let tag = { - hosts: [], - query: {}, - }; - for (let o in parsedData[i][0]) { - tag.hosts.push(parsedData[i][0][o][0]); - } - for (let u in parsedData[i][1]) { - tag.query[parsedData[i][1][u][0]] = parsedData[i][1][u][1]; - } - tags.push(tag); - } + const tags = []; + const expressions = nodeData.match(AUTO_CONFIG_SYNTAX_REGEX); + if (!expressions) + return; + Object.values(expressions).forEach((expression) => { + const components = AUTO_CONFIG_SYNTAX_REGEX.exec(expression); + if (!components || components.length !== 3) + return; + const hosts = components[1]; + const queries = components[2]; + tags.push({ + hosts: hosts.split(',').map((host) => host.trim()), + query: queries.split(',').reduce((a, b) => { + const [key, value] = b.split('='); + if (key && value) + a[key.trim()] = value.trim(); + return a; + }, {}), + }); + }); return { tags }; } } diff --git a/dist/node/shared/autoConfig.js.map b/dist/node/shared/autoConfig.js.map index bc96129..6884bf4 100644 --- a/dist/node/shared/autoConfig.js.map +++ b/dist/node/shared/autoConfig.js.map @@ -1 +1 @@ -{"version":3,"file":"autoConfig.js","sourceRoot":"","sources":["../../../src/shared/autoConfig.ts"],"names":[],"mappings":";;AAEA,kDAAkD;AAClD,MAAM,OAAO,GAA0D,CACrE,IAA0B,EAC1B,SAAiB,EACjB,EAAE;IACF,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QAC5B,KAAK,IAAI,CAAC,IAAI,IAAI,EAAE;YAClB,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;SACvC;KACF;SAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QACnC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7B,KAAK,IAAI,CAAC,IAAI,IAAI,EAAE;YAClB,IAAI,CAAC,CAAC,CAAC,GAAY,IAAI,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;SACpC;KACF;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,mCAAmC;AACnC,MAAM,UAAU,GAAG,GAAG,EAAE;IACtB,IAAI,UAAU,GAAG,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAEnD,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,EAAE;QACzD,IAAI,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC;QAEtC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;YAChC,IAAI,UAAU,GAAmB,CAC/B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CACjE,CAAC;YACF,IAAI,IAAI,GAAG,EAAE,CAAC;YAEd,KAAK,IAAI,CAAC,IAAI,UAAU,EAAE;gBACxB,IAAI,GAAG,GAGH;oBACF,KAAK,EAAE,EAAE;oBACT,KAAK,EAAE,EAAE;iBACV,CAAC;gBACF,KAAK,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;oBAC9B,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;iBACxC;gBACD,KAAK,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;oBAC9B,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;iBAC5D;gBACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;aAChB;YAED,OAAO,EAAE,IAAI,EAAE,CAAC;SACjB;KACF;AACH,CAAC,CAAC;AAEF,kBAAe,UAAU,CAAC"} \ No newline at end of file +{"version":3,"file":"autoConfig.js","sourceRoot":"","sources":["../../../src/shared/autoConfig.ts"],"names":[],"mappings":";;AAAA,MAAM,wBAAwB,GAAG,oCAAoC,CAAC;AAEtE,mCAAmC;AACnC,MAAM,UAAU,GAAG,GAAG,EAAE;;IACtB,MAAM,UAAU,GAAG,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAErD,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,EAAE;QAChD,MAAM,QAAQ,GAAG,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,OAAO,0CAAE,aAAa,CAAC;QAEpD,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;YAChC,MAAM,IAAI,GAAyD,EAAE,CAAC;YAEtE,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAE7D,IAAI,CAAC,WAAW;gBAAE,OAAO;YAEzB,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;gBAChD,MAAM,UAAU,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAE7D,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO;gBAEnD,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC5B,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;gBAE9B,IAAI,CAAC,IAAI,CAAC;oBACR,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;oBAClD,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;wBACxC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;wBAClC,IAAI,GAAG,IAAI,KAAK;4BAAE,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;wBAC/C,OAAO,CAAC,CAAC;oBACX,CAAC,EAAE,EAA4B,CAAC;iBACjC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,OAAO,EAAE,IAAI,EAAE,CAAC;SACjB;KACF;AACH,CAAC,CAAC;AAEF,kBAAe,UAAU,CAAC"} \ No newline at end of file diff --git a/dist/node/shared/features.d.ts b/dist/node/shared/features.d.ts new file mode 100644 index 0000000..d5ceb26 --- /dev/null +++ b/dist/node/shared/features.d.ts @@ -0,0 +1,2 @@ +export declare const hasMutationObserver: boolean; +export declare const hasURL: boolean; diff --git a/dist/node/shared/features.js b/dist/node/shared/features.js new file mode 100644 index 0000000..6e36478 --- /dev/null +++ b/dist/node/shared/features.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hasURL = exports.hasMutationObserver = void 0; +// Check for MutationObserver +exports.hasMutationObserver = typeof window === 'object' && + !(typeof window.MutationObserver === 'undefined'); +// Check for URL and URLSearchParams +exports.hasURL = typeof URL === 'function' && typeof URLSearchParams === 'function'; +//# sourceMappingURL=features.js.map \ No newline at end of file diff --git a/dist/node/shared/features.js.map b/dist/node/shared/features.js.map new file mode 100644 index 0000000..3f32a28 --- /dev/null +++ b/dist/node/shared/features.js.map @@ -0,0 +1 @@ +{"version":3,"file":"features.js","sourceRoot":"","sources":["../../../src/shared/features.ts"],"names":[],"mappings":";;;AAAA,6BAA6B;AAChB,QAAA,mBAAmB,GAC9B,OAAO,MAAM,KAAK,QAAQ;IAC1B,CAAC,CAAC,OAAO,MAAM,CAAC,gBAAgB,KAAK,WAAW,CAAC,CAAC;AAEpD,oCAAoC;AACvB,QAAA,MAAM,GACjB,OAAO,GAAG,KAAK,UAAU,IAAI,OAAO,eAAe,KAAK,UAAU,CAAC"} \ No newline at end of file diff --git a/dist/node/shared/log.d.ts b/dist/node/shared/log.d.ts index 75c7b25..3e1b908 100644 --- a/dist/node/shared/log.d.ts +++ b/dist/node/shared/log.d.ts @@ -3,4 +3,4 @@ * * @module affiliate/src/Log */ -export default function (isError: boolean, ...args: any): void; +export default function (isError: boolean, ...args: (string | number | object)[]): void; diff --git a/dist/node/shared/log.js.map b/dist/node/shared/log.js.map index 7bfc7bd..2f1dbd3 100644 --- a/dist/node/shared/log.js.map +++ b/dist/node/shared/log.js.map @@ -1 +1 @@ -{"version":3,"file":"log.js","sourceRoot":"","sources":["../../../src/shared/log.ts"],"names":[],"mappings":";;AAAA;;;;GAIG;AACH,mBAAyB,OAAgB,EAAE,GAAG,IAAS;IACrD,MAAM,MAAM,GAAG,cAAc,CAAC;IAE9B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;QAC/B,IAAI,OAAO,EAAE;YACX,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;SAChC;aAAM;YACL,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;SAC9B;KACF;AACH,CAAC;AAVD,4BAUC"} \ No newline at end of file +{"version":3,"file":"log.js","sourceRoot":"","sources":["../../../src/shared/log.ts"],"names":[],"mappings":";;AAAA;;;;GAIG;AACH,mBACE,OAAgB,EAChB,GAAG,IAAkC;IAErC,MAAM,MAAM,GAAG,cAAc,CAAC;IAE9B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;QAC/B,IAAI,OAAO,EAAE;YACX,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;SAChC;aAAM;YACL,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;SAC9B;KACF;AACH,CAAC;AAbD,4BAaC"} \ No newline at end of file diff --git a/dist/node/shared/nodeTools.d.ts b/dist/node/shared/nodeTools.d.ts index 23d69c4..69ed953 100644 --- a/dist/node/shared/nodeTools.d.ts +++ b/dist/node/shared/nodeTools.d.ts @@ -1,7 +1,7 @@ -declare const NODE_DATA_KEY = "_aff_data"; +declare const NODE_DATA_KEY = "_aff"; declare type DataNode = Node & { - [NODE_DATA_KEY]?: Record; + [NODE_DATA_KEY]?: Record; }; -export declare const getNodeData: (node: DataNode) => Record; -export declare const setNodeData: (node: DataNode, data: Record) => void; +export declare const getNodeData: (node: DataNode) => Record; +export declare const setNodeData: (node: DataNode, data: Record) => void; export {}; diff --git a/dist/node/shared/nodeTools.js b/dist/node/shared/nodeTools.js index 3be7abb..f89b2c1 100644 --- a/dist/node/shared/nodeTools.js +++ b/dist/node/shared/nodeTools.js @@ -1,7 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setNodeData = exports.getNodeData = void 0; -const NODE_DATA_KEY = '_aff_data'; +const NODE_DATA_KEY = '_aff'; const getNodeData = (node) => { var _a; return (_a = node[NODE_DATA_KEY]) !== null && _a !== void 0 ? _a : {}; diff --git a/dist/node/shared/nodeTools.js.map b/dist/node/shared/nodeTools.js.map index b93d9ba..caa0f5f 100644 --- a/dist/node/shared/nodeTools.js.map +++ b/dist/node/shared/nodeTools.js.map @@ -1 +1 @@ -{"version":3,"file":"nodeTools.js","sourceRoot":"","sources":["../../../src/shared/nodeTools.ts"],"names":[],"mappings":";;;AAAA,MAAM,aAAa,GAAG,WAAW,CAAC;AAI3B,MAAM,WAAW,GAAG,CAAC,IAAc,EAAuB,EAAE;;IACjE,OAAO,MAAA,IAAI,CAAC,aAAa,CAAC,mCAAI,EAAE,CAAC;AACnC,CAAC,CAAC;AAFW,QAAA,WAAW,eAEtB;AAEK,MAAM,WAAW,GAAG,CACzB,IAAc,EACd,IAAyB,EACnB,EAAE;IACR,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC,CAAC;AALW,QAAA,WAAW,eAKtB"} \ No newline at end of file +{"version":3,"file":"nodeTools.js","sourceRoot":"","sources":["../../../src/shared/nodeTools.ts"],"names":[],"mappings":";;;AAAA,MAAM,aAAa,GAAG,MAAM,CAAC;AAItB,MAAM,WAAW,GAAG,CAAC,IAAc,EAA0B,EAAE;;IACpE,OAAO,MAAA,IAAI,CAAC,aAAa,CAAC,mCAAI,EAAE,CAAC;AACnC,CAAC,CAAC;AAFW,QAAA,WAAW,eAEtB;AAEK,MAAM,WAAW,GAAG,CACzB,IAAc,EACd,IAA4B,EACtB,EAAE;IACR,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC,CAAC;AALW,QAAA,WAAW,eAKtB"} \ No newline at end of file diff --git a/dist/web/affiliate.web.js b/dist/web/affiliate.web.js index d7f845e..c5da925 100644 --- a/dist/web/affiliate.web.js +++ b/dist/web/affiliate.web.js @@ -1,2 +1,2 @@ -(()=>{"use strict";var t={735:function(t,e,o){function r(t){return function(t){if(Array.isArray(t))return n(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return n(t,e);var o=Object.prototype.toString.call(t).slice(8,-1);return"Object"===o&&t.constructor&&(o=t.constructor.name),"Map"===o||"Set"===o?Array.from(t):"Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?n(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function n(t,e){(null==e||e>t.length)&&(e=t.length);for(var o=0,r=new Array(e);o0&&void 0!==arguments[0]?arguments[0]:document.body;if("object"===s(e)&&"function"==typeof e.getElementsByTagName){this.log(!1,"Traversing DOM...");var o=e.getElementsByTagName("a"),r=Object.values(o);"a"===e.nodeName.toLowerCase()&&(r=[e]),this.log(!1,"Found ".concat(r.length+1," nodes...")),r.forEach((function(e){var o;if(e&&"href"in e){var r=(0,u.default)(null!==(o=e.href)&&void 0!==o?o:"",!0);-1!==t.state.hosts.indexOf(r.host)&&t.state.config.tags.forEach((function(o){-1!==o.hosts.indexOf(r.host)&&t.modifyURL(r,e,o)}))}}))}}}],o&&a(e.prototype,o),t}();e.default=p},309:function(t,e,o){function r(t,e){(null==e||e>t.length)&&(e=t.length);for(var o=0,r=new Array(e);o{function o(t){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},o(t)}Object.defineProperty(e,"__esModule",{value:!0});var r=function t(e,r){if("object"===o(e))for(var n in e)e[n]=t(e[n],r);else if("string"==typeof e)for(var a in e=e.split(r))e[a]=e[a].trim();return e};e.default=function(){var t=document.getElementById("aff-js");if("object"===o(t)&&null!==t){var e=t.dataset.aff;if("string"==typeof e){var n=r(r(r(r(e,"!"),":"),","),"="),a=[];for(var s in n){var i={hosts:[],query:{}};for(var u in n[s][0])i.hosts.push(n[s][0][u][0]);for(var c in n[s][1])i.query[n[s][1][c][0]]=n[s][1][c][1];a.push(i)}return{tags:a}}}}},223:(t,e)=>{function o(t){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},o(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(t){var e="[Affiliate] ";if("object"===("undefined"==typeof console?"undefined":o(console))){for(var r=arguments.length,n=new Array(r>1?r-1:0),a=1;a{Object.defineProperty(e,"__esModule",{value:!0}),e.setNodeData=e.getNodeData=void 0;e.getNodeData=function(t){var e;return null!==(e=t._aff_data)&&void 0!==e?e:{}},e.setNodeData=function(t,e){var o,r,n;Object.assign(t,(n=e,(r="_aff_data")in(o={})?Object.defineProperty(o,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):o[r]=n,o))}},157:(t,e)=>{var o=Object.prototype.hasOwnProperty;function r(t){try{return decodeURIComponent(t.replace(/\+/g," "))}catch(t){return null}}e.stringify=function(t,e){e=e||"";var r,n,a=[];for(n in"string"!=typeof e&&(e="?"),t)if(o.call(t,n)){if((r=t[n])||null!=r&&!isNaN(r)||(r=""),n=encodeURIComponent(n),r=encodeURIComponent(r),null===n||null===r)continue;a.push(n+"="+r)}return a.length?e+a.join("&"):""},e.parse=function(t){for(var e,o=/([^=?&]+)=?([^&]*)/g,n={};e=o.exec(t);){var a=r(e[1]),s=r(e[2]);null===a||null===s||a in n||(n[a]=s)}return n}},96:t=>{t.exports=function(t,e){if(e=e.split(":")[0],!(t=+t))return!1;switch(e){case"http":case"ws":return 80!==t;case"https":case"wss":return 443!==t;case"ftp":return 21!==t;case"gopher":return 70!==t;case"file":return!1}return 0!==t}},899:(t,e,o)=>{var r=o(96),n=o(157),a=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,s=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i,i=/^[a-zA-Z]:/,u=new RegExp("^[\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF]+");function c(t){return(t||"").toString().replace(u,"")}var f=[["#","hash"],["?","query"],function(t,e){return h(e.protocol)?t.replace(/\\/g,"/"):t},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d+)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],l={hash:1,query:1};function p(t){var e,r=("undefined"!=typeof window?window:void 0!==o.g?o.g:"undefined"!=typeof self?self:{}).location||{},n={},s=typeof(t=t||r);if("blob:"===t.protocol)n=new d(unescape(t.pathname),{});else if("string"===s)for(e in n=new d(t,{}),l)delete n[e];else if("object"===s){for(e in t)e in l||(n[e]=t[e]);void 0===n.slashes&&(n.slashes=a.test(t.href))}return n}function h(t){return"file:"===t||"ftp:"===t||"http:"===t||"https:"===t||"ws:"===t||"wss:"===t}function y(t,e){t=c(t),e=e||{};var o,r=s.exec(t),n=r[1]?r[1].toLowerCase():"",a=!!r[2],i=!!r[3],u=0;return a?i?(o=r[2]+r[3]+r[4],u=r[2].length+r[3].length):(o=r[2]+r[4],u=r[2].length):i?(o=r[3]+r[4],u=r[3].length):o=r[4],"file:"===n?u>=2&&(o=o.slice(2)):h(n)?o=r[4]:n?a&&(o=o.slice(2)):u>=2&&h(e.protocol)&&(o=r[4]),{protocol:n,slashes:a||h(n),slashesCount:u,rest:o}}function d(t,e,o){if(t=c(t),!(this instanceof d))return new d(t,e,o);var a,s,u,l,v,b,m=f.slice(),g=typeof e,w=this,j=0;for("object"!==g&&"string"!==g&&(o=e,e=null),o&&"function"!=typeof o&&(o=n.parse),a=!(s=y(t||"",e=p(e))).protocol&&!s.slashes,w.slashes=s.slashes||a&&e.slashes,w.protocol=s.protocol||e.protocol||"",t=s.rest,("file:"===s.protocol&&(2!==s.slashesCount||i.test(t))||!s.slashes&&(s.protocol||s.slashesCount<2||!h(w.protocol)))&&(m[3]=[/(.*)/,"pathname"]);j{"use strict";var t={735:function(t,e,r){function o(t){return function(t){if(Array.isArray(t))return n(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return n(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?n(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function n(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,o=new Array(e);r0&&void 0!==arguments[0]?arguments[0]:document.body;if("object"!==a(e)||"function"!=typeof e.getElementsByTagName)return this;if(!f.hasURL)return this.log(!0,"This browser needs a URL polyfill."),this;this.log(!1,"Traversing DOM...");var r=e.getElementsByTagName("a"),o=Object.values(r);return"a"===e.nodeName.toLowerCase()&&(o=[e]),this.log(!1,"Found ".concat(o.length+1," nodes...")),o.forEach((function(e){var r;if(e&&"href"in e){var o=new URL(null!==(r=e.href)&&void 0!==r?r:"",null===window||void 0===window?void 0:window.location.origin);-1!==t.state.hosts.indexOf(o.host)&&t.state.config.tags.forEach((function(r){-1!==r.hosts.indexOf(o.host)&&t.modifyURL(o,e,r)}))}})),this}}],r&&i(e.prototype,r),t}();e.default=l},309:function(t,e,r){function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,o=new Array(e);r{function r(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,o=new Array(e);r{function r(t){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},r(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.hasURL=e.hasMutationObserver=void 0,e.hasMutationObserver="object"===("undefined"==typeof window?"undefined":r(window))&&!(void 0===window.MutationObserver),e.hasURL="function"==typeof URL&&"function"==typeof URLSearchParams},223:(t,e)=>{function r(t){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},r(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(t){var e="[Affiliate] ";if("object"===("undefined"==typeof console?"undefined":r(console))){for(var o=arguments.length,n=new Array(o>1?o-1:0),a=1;a{Object.defineProperty(e,"__esModule",{value:!0}),e.setNodeData=e.getNodeData=void 0;e.getNodeData=function(t){var e;return null!==(e=t._aff)&&void 0!==e?e:{}},e.setNodeData=function(t,e){var r,o,n;Object.assign(t,(n=e,(o="_aff")in(r={})?Object.defineProperty(r,o,{value:n,enumerable:!0,configurable:!0,writable:!0}):r._aff=n,r))}}},e={},r=function r(o){var n=e[o];if(void 0!==n)return n.exports;var a=e[o]={exports:{}};return t[o].call(a.exports,a,a.exports,r),a.exports}(309);window.Affiliate=r.default})(); //# sourceMappingURL=affiliate.web.js.map \ No newline at end of file diff --git a/dist/web/affiliate.web.js.map b/dist/web/affiliate.web.js.map index d989bd2..c1fabf4 100644 --- a/dist/web/affiliate.web.js.map +++ b/dist/web/affiliate.web.js.map @@ -1 +1 @@ -{"version":3,"file":"affiliate.web.js","mappings":"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","sources":["webpack://Affiliate/../src/Affiliate.ts","webpack://Affiliate/../src/index.ts","webpack://Affiliate/../src/shared/autoConfig.ts","webpack://Affiliate/../src/shared/log.ts","webpack://Affiliate/../src/shared/nodeTools.ts","webpack://Affiliate/../node_modules/querystringify/index.js","webpack://Affiliate/../node_modules/requires-port/index.js","webpack://Affiliate/../node_modules/url-parse/index.js","webpack://Affiliate/webpack/bootstrap","webpack://Affiliate/webpack/runtime/global","webpack://Affiliate/webpack/startup"],"sourcesContent":["import URLParse from 'url-parse';\nimport Log from './shared/log';\nimport { getNodeData, setNodeData } from './shared/nodeTools';\n\n// Check for MutationObserver\nconst canObserve =\n typeof window === 'object' &&\n !(typeof window.MutationObserver === 'undefined');\n\nexport interface AffiliateConfigTag {\n hosts: string | string[];\n query?: { [key: string]: string };\n replace?: {\n to: string;\n from: string;\n }[];\n modify?: (url: URLParse) => URLParse | string;\n}\n\nexport interface AffiliateConfig {\n tags: AffiliateConfigTag[];\n log?: boolean;\n}\n\n/**\n * @class Manages stateful affiliation\n */\nclass Affiliate {\n state: {\n attached: boolean;\n config: AffiliateConfig;\n hosts: string[];\n } = {\n attached: false,\n config: {\n tags: [],\n },\n hosts: [],\n };\n observer: MutationObserver | undefined = undefined;\n log: typeof Log;\n\n constructor(config?: Partial) {\n // Extend the configuration\n config = config ?? {};\n config.tags = config.tags ?? [];\n\n config.tags.map((tag, i) => {\n if (!config || !config.tags) return;\n\n // Convert a single host to an array\n if (typeof tag.hosts === 'string') tag.hosts = [tag.hosts];\n\n // Extend proper tag configuration\n config.tags[i] = {\n query: {},\n replace: [],\n ...tag,\n };\n\n // Append hosts to full list\n this.state.hosts = [\n ...this.state.hosts,\n ...(config.tags[i].hosts),\n ];\n });\n\n // Set logging function\n this.log = config.log ? Log : () => {};\n\n this.log(false, 'New Instance', config);\n\n // Check is MutationObserver is supported\n if (canObserve) {\n // Initialize MutationObserver\n this.observer = new window.MutationObserver((mutations) => {\n // This function is called for every DOM mutation\n\n // Has a mutation been logged\n let emitted = false;\n\n for (let i in mutations) {\n // If the attributes of the link have been modified\n if (mutations[i].type === 'attributes') {\n // Skip links without an href\n if (mutations[i].attributeName !== 'href') continue;\n\n let href = (mutations[i].target).href;\n let linkData = getNodeData(mutations[i].target);\n\n // Skip links without a modified href\n if (linkData.is && linkData.is === href) continue;\n }\n\n // Only calls on first mutation\n if (!emitted) {\n this.log(false, 'DOM Mutation', mutations[i]);\n emitted = true;\n }\n\n // Scan the node and subnodes if there are any\n this.traverse(mutations[i].target);\n }\n });\n }\n\n // Set internal state\n this.state.config = config;\n }\n\n /**\n * Manual function to search the DOM for unaffiliated links\n *\n * @function\n * @param {object=} nodeSet The node to traverse for links (default: document.body)\n */\n traverse(nodeSet: HTMLElement = document.body) {\n if (\n typeof nodeSet !== 'object' ||\n typeof nodeSet.getElementsByTagName !== 'function'\n )\n return;\n\n this.log(false, 'Traversing DOM...');\n\n // Reduce link collection to array\n let collection = nodeSet.getElementsByTagName('a');\n let nodes = Object.values(collection);\n\n // If the nodeSet is a single link, turn to array\n if (nodeSet.nodeName.toLowerCase() === 'a') nodes = [nodeSet];\n\n this.log(false, `Found ${nodes.length + 1} nodes...`);\n\n // Go through each link\n nodes.forEach((node) => {\n // Check if it is actually linking\n if (!node || !('href' in node)) return;\n\n // Parse the URL via url-parse\n let url = URLParse((node).href ?? '', true);\n\n // Only modify hosts provided.\n if (this.state.hosts.indexOf(url.host) === -1) return;\n this.state.config.tags.forEach((tag) => {\n if (tag.hosts.indexOf(url.host) !== -1) {\n this.modifyURL(url, node, tag);\n }\n });\n });\n }\n\n /**\n * Modify the URL of a matching link while preserving the original link state\n *\n * @private\n * @function\n * @param {string} url Original url string\n * @param {object} node Anchor link node\n * @param {object} tag Matching configuration tag\n */\n modifyURL = (\n url: URLParse,\n node: HTMLAnchorElement,\n tag: AffiliateConfigTag,\n ) => {\n // Check if URL is already modified\n let linkData = getNodeData(node);\n if (linkData.is && linkData.is === url.href) return;\n\n // Preserve the original URL\n let originalURL = url.href;\n\n this.log(false, 'Discovered URL: ' + url.href);\n\n // Change query variables\n url.set('query', { ...url.query, ...tag.query });\n\n // Run the modification function\n if (typeof tag.modify === 'function') {\n try {\n let returnedURL = tag.modify(url);\n if (typeof returnedURL === 'object') returnedURL = returnedURL.href;\n url = URLParse(returnedURL, true);\n } catch (e) {\n Log(true, e);\n }\n }\n\n // Replace certain parts of the url\n let modifiedUrl = url.href;\n tag.replace?.forEach((replacement) => {\n modifiedUrl = modifiedUrl.replace(replacement.from, replacement.to);\n });\n\n // Update the href tag and save the url to the DOM node\n node.href = modifiedUrl;\n setNodeData(node, {\n was: originalURL,\n is: url,\n });\n };\n\n /**\n * Attach the mutation observer\n *\n * @function\n */\n attach: () => void = () => {\n // Cannot attach twice, cannot attach for node\n if (this.state.attached || typeof document === 'undefined') return;\n\n // Get readyState, or the loading state of the DOM\n let { readyState } = document;\n\n if (readyState === 'complete' || readyState === 'interactive') {\n // Set attached to true\n this.state.attached = true;\n\n // Run through the entire body tag\n this.traverse();\n\n if (canObserve && this.observer) {\n // Attach the observer\n this.observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n attributeFilter: ['href'],\n });\n } else {\n this.log(false, 'Browser does not support MutationObserver.');\n }\n } else {\n // Wait until the DOM loads\n return window.addEventListener('DOMContentLoaded', this.attach);\n }\n };\n\n /**\n * Detach the mutation observer\n *\n * @function\n */\n detach = () => {\n if (!canObserve || !this.observer) return;\n this.state.attached = false;\n this.observer.disconnect();\n this.log(false, 'Observer disconnected.');\n };\n}\n\nexport default Affiliate;\n","import AutoConfig from './shared/autoConfig';\nimport Affiliate, { AffiliateConfig } from './Affiliate';\nimport Log from './shared/log';\nimport { getNodeData, setNodeData } from './shared/nodeTools';\n\n/**\n * @class Set up the global Affiliate export\n */\nclass Generator {\n state: {\n instances: Affiliate[];\n auto?: Affiliate;\n } = {\n instances: [],\n };\n\n constructor() {\n try {\n let config = AutoConfig();\n if (typeof config === 'object') {\n let auto = this.create(config);\n Log(false, auto);\n this.state.auto = auto;\n auto.attach();\n }\n } catch (e) {\n Log(true, e);\n }\n }\n\n /**\n * Create a new Affiliate instance\n *\n * @function\n * @param {object} config Configuration options for Affiliate\n * @returns {object} Affiliate instance\n */\n create = (config: Partial) => {\n let Instance = new Affiliate(config);\n this.state.instances.push(Instance);\n return Instance;\n };\n\n /**\n * Expose the instance list\n *\n * @type {Array.}\n */\n get instances() {\n return [...this.state.instances];\n }\n\n /**\n * Detach automatic link traversal\n *\n * @function\n */\n detachAll = () => {\n for (let i in this.state.instances) {\n this.state.instances[i].detach();\n }\n };\n\n /**\n * Revert all traversed links to their non-affiliated state\n *\n * @function\n */\n revert = () => {\n this.detachAll();\n let nodes = (\n [].slice.call(document.body.getElementsByTagName('a'))\n );\n for (let i in nodes) {\n let linkData = getNodeData(nodes[i]);\n if (linkData && linkData.was) {\n nodes[i].href = linkData.was;\n setNodeData(nodes[i], {});\n }\n }\n };\n}\n\nexport default new Generator();\n","type BreakUpData = string | Array;\n\n/* Utility function for parsing data-aff syntax */\nconst breakUp: (data: BreakUpData, delimiter: string) => BreakUpData = (\n data: BreakUpData | string,\n delimiter: string\n) => {\n if (typeof data === 'object') {\n for (let i in data) {\n data[i] = breakUp(data[i], delimiter);\n }\n } else if (typeof data === 'string') {\n data = data.split(delimiter);\n for (let o in data) {\n data[o] = (data[o]).trim();\n }\n }\n return data;\n};\n\n/* Setup automatic configuration */\nconst AutoConfig = () => {\n let scriptNode = document.getElementById('aff-js');\n\n if (typeof scriptNode === 'object' && scriptNode !== null) {\n let nodeData = scriptNode.dataset.aff;\n\n if (typeof nodeData === 'string') {\n let parsedData = (\n breakUp(breakUp(breakUp(breakUp(nodeData, '!'), ':'), ','), '=')\n );\n let tags = [];\n\n for (let i in parsedData) {\n let tag: {\n hosts: string[];\n query: { [key: string]: string };\n } = {\n hosts: [],\n query: {},\n };\n for (let o in parsedData[i][0]) {\n tag.hosts.push(parsedData[i][0][o][0]);\n }\n for (let u in parsedData[i][1]) {\n tag.query[parsedData[i][1][u][0]] = parsedData[i][1][u][1];\n }\n tags.push(tag);\n }\n\n return { tags };\n }\n }\n};\n\nexport default AutoConfig;\n","/**\n * log handles formatting and doesn't throw errors is console is undefined\n *\n * @module affiliate/src/Log\n */\nexport default function (isError: boolean, ...args: any) {\n const textId = '[Affiliate] ';\n\n if (typeof console === 'object') {\n if (isError) {\n console.error(textId, ...args);\n } else {\n console.log(textId, ...args);\n }\n }\n}\n","const NODE_DATA_KEY = '_aff_data';\n\ntype DataNode = Node & { [NODE_DATA_KEY]?: Record };\n\nexport const getNodeData = (node: DataNode): Record => {\n return node[NODE_DATA_KEY] ?? {};\n};\n\nexport const setNodeData = (\n node: DataNode,\n data: Record,\n): void => {\n Object.assign(node, { [NODE_DATA_KEY]: data });\n};\n","'use strict';\n\nvar has = Object.prototype.hasOwnProperty\n , undef;\n\n/**\n * Decode a URI encoded string.\n *\n * @param {String} input The URI encoded string.\n * @returns {String|Null} The decoded string.\n * @api private\n */\nfunction decode(input) {\n try {\n return decodeURIComponent(input.replace(/\\+/g, ' '));\n } catch (e) {\n return null;\n }\n}\n\n/**\n * Attempts to encode a given input.\n *\n * @param {String} input The string that needs to be encoded.\n * @returns {String|Null} The encoded string.\n * @api private\n */\nfunction encode(input) {\n try {\n return encodeURIComponent(input);\n } catch (e) {\n return null;\n }\n}\n\n/**\n * Simple query string parser.\n *\n * @param {String} query The query string that needs to be parsed.\n * @returns {Object}\n * @api public\n */\nfunction querystring(query) {\n var parser = /([^=?&]+)=?([^&]*)/g\n , result = {}\n , part;\n\n while (part = parser.exec(query)) {\n var key = decode(part[1])\n , value = decode(part[2]);\n\n //\n // Prevent overriding of existing properties. This ensures that build-in\n // methods like `toString` or __proto__ are not overriden by malicious\n // querystrings.\n //\n // In the case if failed decoding, we want to omit the key/value pairs\n // from the result.\n //\n if (key === null || value === null || key in result) continue;\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Transform a query string to an object.\n *\n * @param {Object} obj Object that should be transformed.\n * @param {String} prefix Optional prefix.\n * @returns {String}\n * @api public\n */\nfunction querystringify(obj, prefix) {\n prefix = prefix || '';\n\n var pairs = []\n , value\n , key;\n\n //\n // Optionally prefix with a '?' if needed\n //\n if ('string' !== typeof prefix) prefix = '?';\n\n for (key in obj) {\n if (has.call(obj, key)) {\n value = obj[key];\n\n //\n // Edge cases where we actually want to encode the value to an empty\n // string instead of the stringified value.\n //\n if (!value && (value === null || value === undef || isNaN(value))) {\n value = '';\n }\n\n key = encodeURIComponent(key);\n value = encodeURIComponent(value);\n\n //\n // If we failed to encode the strings, we should bail out as we don't\n // want to add invalid strings to the query.\n //\n if (key === null || value === null) continue;\n pairs.push(key +'='+ value);\n }\n }\n\n return pairs.length ? prefix + pairs.join('&') : '';\n}\n\n//\n// Expose the module.\n//\nexports.stringify = querystringify;\nexports.parse = querystring;\n","'use strict';\n\n/**\n * Check if we're required to add a port number.\n *\n * @see https://url.spec.whatwg.org/#default-port\n * @param {Number|String} port Port number we need to check\n * @param {String} protocol Protocol we need to check against.\n * @returns {Boolean} Is it a default port for the given protocol\n * @api private\n */\nmodule.exports = function required(port, protocol) {\n protocol = protocol.split(':')[0];\n port = +port;\n\n if (!port) return false;\n\n switch (protocol) {\n case 'http':\n case 'ws':\n return port !== 80;\n\n case 'https':\n case 'wss':\n return port !== 443;\n\n case 'ftp':\n return port !== 21;\n\n case 'gopher':\n return port !== 70;\n\n case 'file':\n return false;\n }\n\n return port !== 0;\n};\n","'use strict';\n\nvar required = require('requires-port')\n , qs = require('querystringify')\n , slashes = /^[A-Za-z][A-Za-z0-9+-.]*:\\/\\//\n , protocolre = /^([a-z][a-z0-9.+-]*:)?(\\/\\/)?([\\\\/]+)?([\\S\\s]*)/i\n , windowsDriveLetter = /^[a-zA-Z]:/\n , whitespace = '[\\\\x09\\\\x0A\\\\x0B\\\\x0C\\\\x0D\\\\x20\\\\xA0\\\\u1680\\\\u180E\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200A\\\\u202F\\\\u205F\\\\u3000\\\\u2028\\\\u2029\\\\uFEFF]'\n , left = new RegExp('^'+ whitespace +'+');\n\n/**\n * Trim a given string.\n *\n * @param {String} str String to trim.\n * @public\n */\nfunction trimLeft(str) {\n return (str ? str : '').toString().replace(left, '');\n}\n\n/**\n * These are the parse rules for the URL parser, it informs the parser\n * about:\n *\n * 0. The char it Needs to parse, if it's a string it should be done using\n * indexOf, RegExp using exec and NaN means set as current value.\n * 1. The property we should set when parsing this value.\n * 2. Indication if it's backwards or forward parsing, when set as number it's\n * the value of extra chars that should be split off.\n * 3. Inherit from location if non existing in the parser.\n * 4. `toLowerCase` the resulting value.\n */\nvar rules = [\n ['#', 'hash'], // Extract from the back.\n ['?', 'query'], // Extract from the back.\n function sanitize(address, url) { // Sanitize what is left of the address\n return isSpecial(url.protocol) ? address.replace(/\\\\/g, '/') : address;\n },\n ['/', 'pathname'], // Extract from the back.\n ['@', 'auth', 1], // Extract from the front.\n [NaN, 'host', undefined, 1, 1], // Set left over value.\n [/:(\\d+)$/, 'port', undefined, 1], // RegExp the back.\n [NaN, 'hostname', undefined, 1, 1] // Set left over.\n];\n\n/**\n * These properties should not be copied or inherited from. This is only needed\n * for all non blob URL's as a blob URL does not include a hash, only the\n * origin.\n *\n * @type {Object}\n * @private\n */\nvar ignore = { hash: 1, query: 1 };\n\n/**\n * The location object differs when your code is loaded through a normal page,\n * Worker or through a worker using a blob. And with the blobble begins the\n * trouble as the location object will contain the URL of the blob, not the\n * location of the page where our code is loaded in. The actual origin is\n * encoded in the `pathname` so we can thankfully generate a good \"default\"\n * location from it so we can generate proper relative URL's again.\n *\n * @param {Object|String} loc Optional default location object.\n * @returns {Object} lolcation object.\n * @public\n */\nfunction lolcation(loc) {\n var globalVar;\n\n if (typeof window !== 'undefined') globalVar = window;\n else if (typeof global !== 'undefined') globalVar = global;\n else if (typeof self !== 'undefined') globalVar = self;\n else globalVar = {};\n\n var location = globalVar.location || {};\n loc = loc || location;\n\n var finaldestination = {}\n , type = typeof loc\n , key;\n\n if ('blob:' === loc.protocol) {\n finaldestination = new Url(unescape(loc.pathname), {});\n } else if ('string' === type) {\n finaldestination = new Url(loc, {});\n for (key in ignore) delete finaldestination[key];\n } else if ('object' === type) {\n for (key in loc) {\n if (key in ignore) continue;\n finaldestination[key] = loc[key];\n }\n\n if (finaldestination.slashes === undefined) {\n finaldestination.slashes = slashes.test(loc.href);\n }\n }\n\n return finaldestination;\n}\n\n/**\n * Check whether a protocol scheme is special.\n *\n * @param {String} The protocol scheme of the URL\n * @return {Boolean} `true` if the protocol scheme is special, else `false`\n * @private\n */\nfunction isSpecial(scheme) {\n return (\n scheme === 'file:' ||\n scheme === 'ftp:' ||\n scheme === 'http:' ||\n scheme === 'https:' ||\n scheme === 'ws:' ||\n scheme === 'wss:'\n );\n}\n\n/**\n * @typedef ProtocolExtract\n * @type Object\n * @property {String} protocol Protocol matched in the URL, in lowercase.\n * @property {Boolean} slashes `true` if protocol is followed by \"//\", else `false`.\n * @property {String} rest Rest of the URL that is not part of the protocol.\n */\n\n/**\n * Extract protocol information from a URL with/without double slash (\"//\").\n *\n * @param {String} address URL we want to extract from.\n * @param {Object} location\n * @return {ProtocolExtract} Extracted information.\n * @private\n */\nfunction extractProtocol(address, location) {\n address = trimLeft(address);\n location = location || {};\n\n var match = protocolre.exec(address);\n var protocol = match[1] ? match[1].toLowerCase() : '';\n var forwardSlashes = !!match[2];\n var otherSlashes = !!match[3];\n var slashesCount = 0;\n var rest;\n\n if (forwardSlashes) {\n if (otherSlashes) {\n rest = match[2] + match[3] + match[4];\n slashesCount = match[2].length + match[3].length;\n } else {\n rest = match[2] + match[4];\n slashesCount = match[2].length;\n }\n } else {\n if (otherSlashes) {\n rest = match[3] + match[4];\n slashesCount = match[3].length;\n } else {\n rest = match[4]\n }\n }\n\n if (protocol === 'file:') {\n if (slashesCount >= 2) {\n rest = rest.slice(2);\n }\n } else if (isSpecial(protocol)) {\n rest = match[4];\n } else if (protocol) {\n if (forwardSlashes) {\n rest = rest.slice(2);\n }\n } else if (slashesCount >= 2 && isSpecial(location.protocol)) {\n rest = match[4];\n }\n\n return {\n protocol: protocol,\n slashes: forwardSlashes || isSpecial(protocol),\n slashesCount: slashesCount,\n rest: rest\n };\n}\n\n/**\n * Resolve a relative URL pathname against a base URL pathname.\n *\n * @param {String} relative Pathname of the relative URL.\n * @param {String} base Pathname of the base URL.\n * @return {String} Resolved pathname.\n * @private\n */\nfunction resolve(relative, base) {\n if (relative === '') return base;\n\n var path = (base || '/').split('/').slice(0, -1).concat(relative.split('/'))\n , i = path.length\n , last = path[i - 1]\n , unshift = false\n , up = 0;\n\n while (i--) {\n if (path[i] === '.') {\n path.splice(i, 1);\n } else if (path[i] === '..') {\n path.splice(i, 1);\n up++;\n } else if (up) {\n if (i === 0) unshift = true;\n path.splice(i, 1);\n up--;\n }\n }\n\n if (unshift) path.unshift('');\n if (last === '.' || last === '..') path.push('');\n\n return path.join('/');\n}\n\n/**\n * The actual URL instance. Instead of returning an object we've opted-in to\n * create an actual constructor as it's much more memory efficient and\n * faster and it pleases my OCD.\n *\n * It is worth noting that we should not use `URL` as class name to prevent\n * clashes with the global URL instance that got introduced in browsers.\n *\n * @constructor\n * @param {String} address URL we want to parse.\n * @param {Object|String} [location] Location defaults for relative paths.\n * @param {Boolean|Function} [parser] Parser for the query string.\n * @private\n */\nfunction Url(address, location, parser) {\n address = trimLeft(address);\n\n if (!(this instanceof Url)) {\n return new Url(address, location, parser);\n }\n\n var relative, extracted, parse, instruction, index, key\n , instructions = rules.slice()\n , type = typeof location\n , url = this\n , i = 0;\n\n //\n // The following if statements allows this module two have compatibility with\n // 2 different API:\n //\n // 1. Node.js's `url.parse` api which accepts a URL, boolean as arguments\n // where the boolean indicates that the query string should also be parsed.\n //\n // 2. The `URL` interface of the browser which accepts a URL, object as\n // arguments. The supplied object will be used as default values / fall-back\n // for relative paths.\n //\n if ('object' !== type && 'string' !== type) {\n parser = location;\n location = null;\n }\n\n if (parser && 'function' !== typeof parser) parser = qs.parse;\n\n location = lolcation(location);\n\n //\n // Extract protocol information before running the instructions.\n //\n extracted = extractProtocol(address || '', location);\n relative = !extracted.protocol && !extracted.slashes;\n url.slashes = extracted.slashes || relative && location.slashes;\n url.protocol = extracted.protocol || location.protocol || '';\n address = extracted.rest;\n\n //\n // When the authority component is absent the URL starts with a path\n // component.\n //\n if (\n extracted.protocol === 'file:' && (\n extracted.slashesCount !== 2 || windowsDriveLetter.test(address)) ||\n (!extracted.slashes &&\n (extracted.protocol ||\n extracted.slashesCount < 2 ||\n !isSpecial(url.protocol)))\n ) {\n instructions[3] = [/(.*)/, 'pathname'];\n }\n\n for (; i < instructions.length; i++) {\n instruction = instructions[i];\n\n if (typeof instruction === 'function') {\n address = instruction(address, url);\n continue;\n }\n\n parse = instruction[0];\n key = instruction[1];\n\n if (parse !== parse) {\n url[key] = address;\n } else if ('string' === typeof parse) {\n if (~(index = address.indexOf(parse))) {\n if ('number' === typeof instruction[2]) {\n url[key] = address.slice(0, index);\n address = address.slice(index + instruction[2]);\n } else {\n url[key] = address.slice(index);\n address = address.slice(0, index);\n }\n }\n } else if ((index = parse.exec(address))) {\n url[key] = index[1];\n address = address.slice(0, index.index);\n }\n\n url[key] = url[key] || (\n relative && instruction[3] ? location[key] || '' : ''\n );\n\n //\n // Hostname, host and protocol should be lowercased so they can be used to\n // create a proper `origin`.\n //\n if (instruction[4]) url[key] = url[key].toLowerCase();\n }\n\n //\n // Also parse the supplied query string in to an object. If we're supplied\n // with a custom parser as function use that instead of the default build-in\n // parser.\n //\n if (parser) url.query = parser(url.query);\n\n //\n // If the URL is relative, resolve the pathname against the base URL.\n //\n if (\n relative\n && location.slashes\n && url.pathname.charAt(0) !== '/'\n && (url.pathname !== '' || location.pathname !== '')\n ) {\n url.pathname = resolve(url.pathname, location.pathname);\n }\n\n //\n // Default to a / for pathname if none exists. This normalizes the URL\n // to always have a /\n //\n if (url.pathname.charAt(0) !== '/' && isSpecial(url.protocol)) {\n url.pathname = '/' + url.pathname;\n }\n\n //\n // We should not add port numbers if they are already the default port number\n // for a given protocol. As the host also contains the port number we're going\n // override it with the hostname which contains no port number.\n //\n if (!required(url.port, url.protocol)) {\n url.host = url.hostname;\n url.port = '';\n }\n\n //\n // Parse down the `auth` for the username and password.\n //\n url.username = url.password = '';\n if (url.auth) {\n instruction = url.auth.split(':');\n url.username = instruction[0] || '';\n url.password = instruction[1] || '';\n }\n\n url.origin = url.protocol !== 'file:' && isSpecial(url.protocol) && url.host\n ? url.protocol +'//'+ url.host\n : 'null';\n\n //\n // The href is just the compiled result.\n //\n url.href = url.toString();\n}\n\n/**\n * This is convenience method for changing properties in the URL instance to\n * insure that they all propagate correctly.\n *\n * @param {String} part Property we need to adjust.\n * @param {Mixed} value The newly assigned value.\n * @param {Boolean|Function} fn When setting the query, it will be the function\n * used to parse the query.\n * When setting the protocol, double slash will be\n * removed from the final url if it is true.\n * @returns {URL} URL instance for chaining.\n * @public\n */\nfunction set(part, value, fn) {\n var url = this;\n\n switch (part) {\n case 'query':\n if ('string' === typeof value && value.length) {\n value = (fn || qs.parse)(value);\n }\n\n url[part] = value;\n break;\n\n case 'port':\n url[part] = value;\n\n if (!required(value, url.protocol)) {\n url.host = url.hostname;\n url[part] = '';\n } else if (value) {\n url.host = url.hostname +':'+ value;\n }\n\n break;\n\n case 'hostname':\n url[part] = value;\n\n if (url.port) value += ':'+ url.port;\n url.host = value;\n break;\n\n case 'host':\n url[part] = value;\n\n if (/:\\d+$/.test(value)) {\n value = value.split(':');\n url.port = value.pop();\n url.hostname = value.join(':');\n } else {\n url.hostname = value;\n url.port = '';\n }\n\n break;\n\n case 'protocol':\n url.protocol = value.toLowerCase();\n url.slashes = !fn;\n break;\n\n case 'pathname':\n case 'hash':\n if (value) {\n var char = part === 'pathname' ? '/' : '#';\n url[part] = value.charAt(0) !== char ? char + value : value;\n } else {\n url[part] = value;\n }\n break;\n\n default:\n url[part] = value;\n }\n\n for (var i = 0; i < rules.length; i++) {\n var ins = rules[i];\n\n if (ins[4]) url[ins[1]] = url[ins[1]].toLowerCase();\n }\n\n url.origin = url.protocol !== 'file:' && isSpecial(url.protocol) && url.host\n ? url.protocol +'//'+ url.host\n : 'null';\n\n url.href = url.toString();\n\n return url;\n}\n\n/**\n * Transform the properties back in to a valid and full URL string.\n *\n * @param {Function} stringify Optional query stringify function.\n * @returns {String} Compiled version of the URL.\n * @public\n */\nfunction toString(stringify) {\n if (!stringify || 'function' !== typeof stringify) stringify = qs.stringify;\n\n var query\n , url = this\n , protocol = url.protocol;\n\n if (protocol && protocol.charAt(protocol.length - 1) !== ':') protocol += ':';\n\n var result = protocol + (url.slashes || isSpecial(url.protocol) ? '//' : '');\n\n if (url.username) {\n result += url.username;\n if (url.password) result += ':'+ url.password;\n result += '@';\n }\n\n result += url.host + url.pathname;\n\n query = 'object' === typeof url.query ? stringify(url.query) : url.query;\n if (query) result += '?' !== query.charAt(0) ? '?'+ query : query;\n\n if (url.hash) result += url.hash;\n\n return result;\n}\n\nUrl.prototype = { set: set, toString: toString };\n\n//\n// Expose the URL parser and some additional properties that might be useful for\n// others or testing.\n//\nUrl.extractProtocol = extractProtocol;\nUrl.location = lolcation;\nUrl.trimLeft = trimLeft;\nUrl.qs = qs;\n\nmodule.exports = Url;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(309);\n"],"names":["canObserve","window","MutationObserver","Affiliate","config","state","attached","tags","hosts","observer","undefined","modifyURL","url","node","tag","linkData","getNodeData","is","href","originalURL","log","set","query","modify","returnedURL","e","modifiedUrl","replace","forEach","replacement","from","to","setNodeData","was","attach","document","readyState","addEventListener","traverse","observe","body","childList","subtree","attributes","characterData","attributeFilter","detach","disconnect","map","i","this","mutations","emitted","type","attributeName","target","nodeSet","getElementsByTagName","collection","nodes","Object","values","nodeName","toLowerCase","length","indexOf","host","Generator","instances","create","Instance","push","detachAll","revert","slice","call","auto","breakUp","data","delimiter","o","split","trim","scriptNode","getElementById","nodeData","dataset","aff","parsedData","u","isError","textId","console","args","error","assign","has","prototype","hasOwnProperty","decode","input","decodeURIComponent","exports","stringify","obj","prefix","value","key","pairs","isNaN","encodeURIComponent","join","parse","part","parser","result","exec","module","port","protocol","required","qs","slashes","protocolre","windowsDriveLetter","left","RegExp","trimLeft","str","toString","rules","address","isSpecial","NaN","ignore","hash","lolcation","loc","location","g","self","finaldestination","Url","unescape","pathname","test","scheme","extractProtocol","rest","match","forwardSlashes","otherSlashes","slashesCount","relative","extracted","instruction","index","instructions","charAt","base","path","concat","last","unshift","up","splice","resolve","hostname","username","password","auth","origin","fn","pop","char","ins","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","globalThis","Function","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"affiliate.web.js","mappings":"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","sources":["webpack://Affiliate/../src/Affiliate.ts","webpack://Affiliate/../src/index.ts","webpack://Affiliate/../src/shared/autoConfig.ts","webpack://Affiliate/../src/shared/features.ts","webpack://Affiliate/../src/shared/log.ts","webpack://Affiliate/../src/shared/nodeTools.ts","webpack://Affiliate/webpack/bootstrap","webpack://Affiliate/webpack/startup"],"sourcesContent":["import { hasMutationObserver, hasURL } from './shared/features';\nimport Log from './shared/log';\nimport { getNodeData, setNodeData } from './shared/nodeTools';\n\nexport interface AffiliateConfigTag {\n hosts: string | string[];\n query?: { [key: string]: string };\n replace?: {\n to: string;\n from: string;\n }[];\n modify?: (url: URL) => URL | string;\n}\n\nexport interface AffiliateConfig {\n tags: AffiliateConfigTag[];\n log?: boolean;\n}\n\n/**\n * @class Manages stateful affiliation\n */\nclass Affiliate {\n state: {\n attached: boolean;\n config: AffiliateConfig;\n hosts: string[];\n } = {\n attached: false,\n config: {\n tags: [],\n },\n hosts: [],\n };\n observer: MutationObserver | undefined = undefined;\n log: typeof Log;\n\n constructor(config?: Partial) {\n // Extend the configuration\n config = config ?? {};\n config.tags = config.tags ?? [];\n\n config.tags.map((tag, i) => {\n if (!config || !config.tags) return;\n\n // Convert a single host to an array\n if (typeof tag.hosts === 'string') tag.hosts = [tag.hosts];\n\n // Extend proper tag configuration\n config.tags[i] = {\n query: {},\n replace: [],\n ...tag,\n };\n\n // Append hosts to full list\n this.state.hosts = [\n ...this.state.hosts,\n ...(config.tags[i].hosts),\n ];\n });\n\n // Set logging function\n this.log = config.log ? Log : () => undefined;\n\n this.log(false, 'New Instance', config);\n\n // Check is MutationObserver is supported\n if (hasMutationObserver) {\n // Initialize MutationObserver\n this.observer = new window.MutationObserver((mutations) => {\n // This function is called for every DOM mutation\n\n // Has a mutation been logged\n let emitted = false;\n\n mutations.forEach((mutation) => {\n // If the attributes of the link have been modified\n if (mutation.type === 'attributes') {\n // Skip links without an href\n if (mutation.attributeName !== 'href') return;\n\n const href = (mutation.target).href;\n const linkData = getNodeData(mutation.target);\n\n // Skip links without a modified href\n if (linkData.is && linkData.is === href) return;\n }\n\n // Only calls on first mutation\n if (!emitted) {\n this.log(false, 'DOM Mutation', mutation);\n emitted = true;\n }\n\n // Scan the node and subnodes if there are any\n this.traverse(mutation.target);\n });\n });\n }\n\n // Set internal state\n this.state.config = config;\n }\n\n /**\n * Manual function to search the DOM for unaffiliated links\n *\n * @function\n * @param {object=} nodeSet The node to traverse for links (default: document.body)\n */\n traverse(nodeSet: HTMLElement = document.body): Affiliate {\n if (\n typeof nodeSet !== 'object' ||\n typeof nodeSet.getElementsByTagName !== 'function'\n )\n return this;\n\n if (!hasURL) {\n this.log(true, 'This browser needs a URL polyfill.');\n return this;\n }\n\n this.log(false, 'Traversing DOM...');\n\n // Reduce link collection to array\n const collection = nodeSet.getElementsByTagName('a');\n let nodes = Object.values(collection);\n\n // If the nodeSet is a single link, turn to array\n if (nodeSet.nodeName.toLowerCase() === 'a') nodes = [nodeSet];\n\n this.log(false, `Found ${nodes.length + 1} nodes...`);\n\n // Go through each link\n nodes.forEach((node) => {\n // Check if it is actually linking\n if (!node || !('href' in node)) return;\n\n // Parse the URL natively\n const url = new URL(\n (node).href ?? '',\n window?.location.origin,\n );\n\n // Only modify hosts provided.\n if (this.state.hosts.indexOf(url.host) === -1) return;\n this.state.config.tags.forEach((tag) => {\n if (tag.hosts.indexOf(url.host) !== -1) {\n this.modifyURL(url, node, tag);\n }\n });\n });\n\n return this;\n }\n\n /**\n * Modify the URL of a matching link while preserving the original link state\n *\n * @private\n * @function\n * @param {string} url Original url string\n * @param {object} node Anchor link node\n * @param {object} tag Matching configuration tag\n */\n modifyURL = (url: URL, node: HTMLAnchorElement, tag: AffiliateConfigTag) => {\n // Check if URL is already modified\n const linkData = getNodeData(node);\n if (linkData.is && linkData.is === url.href) return;\n\n // Preserve the original URL\n const originalURL = url.href;\n\n this.log(false, 'Discovered URL: ' + url.href);\n\n // Change query variables\n if (tag.query) {\n Object.keys(tag.query ?? {}).forEach((key) => {\n if (typeof tag.query === 'object')\n url.searchParams.set(key, tag.query[key]);\n });\n }\n\n // Run the modification function\n if (typeof tag.modify === 'function') {\n try {\n let returnedURL = tag.modify(url);\n if (typeof returnedURL === 'object') returnedURL = returnedURL.href;\n url = new URL(returnedURL, window?.location.origin);\n } catch (e) {\n Log(true, e as Error);\n }\n }\n\n // Replace certain parts of the url\n let modifiedUrl = url.href;\n tag.replace?.forEach((replacement) => {\n modifiedUrl = modifiedUrl.replace(replacement.from, replacement.to);\n });\n\n // Update the href tag and save the url to the DOM node\n node.href = modifiedUrl;\n setNodeData(node, {\n was: originalURL,\n is: url.href,\n });\n };\n\n /**\n * Attach the mutation observer\n *\n * @function\n */\n attach = (): Affiliate => {\n // Cannot attach twice, cannot attach for node\n if (this.state.attached || typeof document === 'undefined') return this;\n\n // Get readyState, or the loading state of the DOM\n const { readyState } = document;\n\n if (readyState === 'complete' || readyState === 'interactive') {\n // Set attached to true\n this.state.attached = true;\n\n // Run through the entire body tag\n this.traverse();\n\n if (hasMutationObserver && this.observer) {\n // Attach the observer\n this.observer.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n attributeFilter: ['href'],\n });\n } else {\n this.log(false, 'Browser does not support MutationObserver.');\n }\n } else {\n // Wait until the DOM loads\n window.addEventListener('DOMContentLoaded', this.attach);\n }\n\n return this;\n };\n\n /**\n * Detach the mutation observer\n *\n * @function\n */\n detach = (): Affiliate => {\n if (!hasMutationObserver || !this.observer) return this;\n this.state.attached = false;\n this.observer.disconnect();\n this.log(false, 'Observer disconnected.');\n return this;\n };\n}\n\nexport default Affiliate;\n","import AutoConfig from './shared/autoConfig';\nimport Affiliate, { AffiliateConfig } from './Affiliate';\nimport Log from './shared/log';\nimport { getNodeData, setNodeData } from './shared/nodeTools';\n\n/**\n * @class Set up the global Affiliate export\n */\nclass Generator {\n state: {\n instances: Affiliate[];\n auto?: Affiliate;\n } = {\n instances: [],\n };\n\n constructor() {\n try {\n const config = AutoConfig();\n if (typeof config === 'object') {\n const auto = this.create(config);\n Log(false, auto);\n this.state.auto = auto;\n auto.attach();\n }\n } catch (e) {\n Log(true, e as Error);\n }\n }\n\n /**\n * Create a new Affiliate instance\n *\n * @function\n * @param {object} config Configuration options for Affiliate\n * @returns {object} Affiliate instance\n */\n create = (config: Partial) => {\n const Instance = new Affiliate(config);\n this.state.instances.push(Instance);\n return Instance;\n };\n\n /**\n * Expose the instance list\n *\n * @type {Array.}\n */\n get instances() {\n return [...this.state.instances];\n }\n\n /**\n * Detach automatic link traversal\n *\n * @function\n */\n detachAll = () => {\n this.state.instances.forEach((instance) => instance.detach());\n };\n\n /**\n * Revert all traversed links to their non-affiliated state\n *\n * @function\n */\n revert = () => {\n this.detachAll();\n const nodes = Object.values(document.body.getElementsByTagName('a'));\n nodes.forEach((node) => {\n const linkData = getNodeData(node);\n if (linkData && typeof linkData.was === 'string') {\n node.href = linkData.was;\n setNodeData(node, {});\n }\n });\n };\n}\n\nexport default new Generator();\n","const AUTO_CONFIG_SYNTAX_REGEX = /WHERE (.+?) SET (.+?)\\s*(?:AND|$)/g;\n\n/* Setup automatic configuration */\nconst AutoConfig = () => {\n const scriptNode = document.getElementById('aff-js');\n\n if (typeof scriptNode === 'object' && scriptNode) {\n const nodeData = scriptNode?.dataset?.autoAffiliate;\n\n if (typeof nodeData === 'string') {\n const tags: { hosts: string[]; query: Record }[] = [];\n\n const expressions = nodeData.match(AUTO_CONFIG_SYNTAX_REGEX);\n\n if (!expressions) return;\n\n Object.values(expressions).forEach((expression) => {\n const components = AUTO_CONFIG_SYNTAX_REGEX.exec(expression);\n\n if (!components || components.length !== 3) return;\n\n const hosts = components[1];\n const queries = components[2];\n\n tags.push({\n hosts: hosts.split(',').map((host) => host.trim()),\n query: queries.split(',').reduce((a, b) => {\n const [key, value] = b.split('=');\n if (key && value) a[key.trim()] = value.trim();\n return a;\n }, {} as Record),\n });\n });\n\n return { tags };\n }\n }\n};\n\nexport default AutoConfig;\n","// Check for MutationObserver\nexport const hasMutationObserver =\n typeof window === 'object' &&\n !(typeof window.MutationObserver === 'undefined');\n\n// Check for URL and URLSearchParams\nexport const hasURL =\n typeof URL === 'function' && typeof URLSearchParams === 'function';\n","/**\n * log handles formatting and doesn't throw errors is console is undefined\n *\n * @module affiliate/src/Log\n */\nexport default function (\n isError: boolean,\n ...args: (string | number | object)[]\n) {\n const textId = '[Affiliate] ';\n\n if (typeof console === 'object') {\n if (isError) {\n console.error(textId, ...args);\n } else {\n console.log(textId, ...args);\n }\n }\n}\n","const NODE_DATA_KEY = '_aff';\n\ntype DataNode = Node & { [NODE_DATA_KEY]?: Record };\n\nexport const getNodeData = (node: DataNode): Record => {\n return node[NODE_DATA_KEY] ?? {};\n};\n\nexport const setNodeData = (\n node: DataNode,\n data: Record,\n): void => {\n Object.assign(node, { [NODE_DATA_KEY]: data });\n};\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(309);\n"],"names":["Affiliate","config","state","attached","tags","hosts","observer","undefined","modifyURL","url","node","tag","linkData","getNodeData","is","href","originalURL","log","query","Object","keys","forEach","key","searchParams","set","modify","returnedURL","URL","window","location","origin","e","modifiedUrl","replace","replacement","from","to","setNodeData","was","attach","document","readyState","traverse","hasMutationObserver","observe","body","childList","subtree","attributes","characterData","attributeFilter","addEventListener","detach","disconnect","map","i","this","MutationObserver","mutations","emitted","mutation","type","attributeName","target","nodeSet","getElementsByTagName","hasURL","collection","nodes","values","nodeName","toLowerCase","length","indexOf","host","Generator","instances","create","Instance","push","detachAll","instance","revert","auto","AUTO_CONFIG_SYNTAX_REGEX","scriptNode","getElementById","nodeData","dataset","autoAffiliate","expressions","match","expression","components","exec","queries","split","trim","reduce","a","b","value","URLSearchParams","isError","textId","console","args","error","data","assign","__webpack_module_cache__","__webpack_exports__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","call"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/_config.yml b/docs/_config.yml index 7cc884f..0e089ab 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -4,4 +4,4 @@ show_downloads: true google_analytics: UA-72546719-11 theme: jekyll-theme-cayman author: Russell Steadman -author_email: russell@unatetra.com \ No newline at end of file +author_email: steadman.21@osu.edu diff --git a/docs/index.md b/docs/index.md index dadcd67..0b6fb2b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,22 +6,42 @@ Affiliate is a platform agnostic link affiliator. Simplify affiliating links wit ## Installation +Use NPM or Yarn + ```bash $ npm install --save affiliate $ yarn add affiliate ``` -Or use a CDN +Or use a CDN ([check out the codeless setup](#blogs-and-related-sites)) + +```html + +``` + +## What It Can Do + +Affiliate can modify query tags (e.g. setting `?tag=my-tag`, which is the most common method for affiliate tags), modify URL paths, and modify host names. + +```html +Original +``` ```html - - +New Query Tags +Modified URL Path +Modified Host Name ``` +Affiliate has easy [plugins](https://affiliate.js.org/plugins), including one for [Amazon](https://affiliate.js.org/plugins/amazon), which simplify adding affiliate links even more. + ## Configuration ```js -const Affiliate = require('affiliate'); // window.Affiliate if using a CDN +import Affiliate from 'affiliate'; // window.Affiliate is automatically accessible if using a CDN + const aff = Affiliate.create({ log: true, // enable logging tags: [ @@ -49,35 +69,36 @@ const aff = Affiliate.create({ }, ], }); + aff.attach(); ``` After passing the configuration to Affiliate, it will search the DOM and automatically and change links. Then whenever the DOM is modified, it will search through the modifications and change those links for no-hassle affiliation. -#### config.log +### config.log A boolean of whether or not to enable verbose logging. -#### config.tags[].hosts +### config.tags[].hosts An array of the hosts to match. -#### config.tags[].query +### config.tags[].query An object to update the query of the url. -#### config.tags[].replace +### config.tags[].replace An array of objects with a `from` key that is a regex or string and a `to` key that is the value that will replace the `from` key. -#### config.tags[].modify +### config.tags[].modify This exposes an instance of the [`url-parse`](https://www.npmjs.com/package/url-parse#usage) library. This can be used to update individual parts of the URL, such as the hostname or hash. It expects the instance or a URL string to be returned. ## Affiliate API ```js -const Affiliate = require('affiliate'); +import Affiliate from 'affiliate'; let newInstance = Affiliate.create(config); // creates a new Affiliate instance let instances = Affiliate.instances; // an array of all instances @@ -91,8 +112,9 @@ newInstance.detach(); // stops listening to DOM events ## Example ```js -const Affiliate = require('affiliate'); // window.Affiliate if using a CDN -let aff = Affiliate.create({ +import Affiliate from 'affiliate'; // window.Affiliate if using a CDN + +const aff = Affiliate.create({ log: false, tags: [ { @@ -103,6 +125,7 @@ let aff = Affiliate.create({ }, ], }); + aff.attach(); ``` @@ -115,33 +138,33 @@ Will become... ```html You should try the -Chocolate Passport. + + Chocolate Passport + +. ``` -### Blogs and Related Sites +## Blogs and Related Sites -A simplified codeless solution might better suit some blogging-style sites. +A simplified codeless solution might better suit some sites that use content module systems, such as WordPress, SquareSpace, etc. -Insert this code into the page ``. The contents of the `data-aff` attribute will tell Affiliate what to do. +Insert this code within the HTML `...` tag. The contents of the `data-auto-affiliate` attribute will tell Affiliate what to do. ```html - ``` -#### data-aff Syntax +### data-auto-affiliate Syntax -The syntax for data-aff is a comma separated list of domains, a colon, and then comma separated list of url queries in the format `key=value`. Multiple website groups can be separated by an exclamation mark. +The syntax for data-auto-affiliate is capital `WHERE`, a comma separated list of domains, capital `SET`, and then comma separated list of URL queries in the format `key=value`. Multiple website groups can be separated by a capital `AND`. -``` -amazon.com, www.amazon.com : tag = MY-AMAZON-TAG ! example.com, shop.example.com : ref = MY-OTHER-TAG +```sql +WHERE amazon.com, www.amazon.com SET tag = MY-AMAZON-TAG AND WHERE example.com, shop.example.com SET ref = MY-OTHER-TAG ``` ## Plugins @@ -150,7 +173,7 @@ Plugins make some more complex affiliation tasks super simple. Check out a list ## Left with Questions? -If for any reason you feel that this documentation is unclear or incomplete, [add an issue](https://github.com/russellsteadman/affiliate/issues/new) detailing what needs to be improved. It will be addressed quickly. +If for any reason you feel that this documentation is unclear or incomplete, [add an issue](https://github.com/russellsteadman/affiliate/issues/new) detailing what needs to be improved. ## Star This Project @@ -158,4 +181,4 @@ Like this project? Let me know by [putting a star on it](https://github.com/russ ## License -MIT (C) [Russell Steadman](https://www.russellsteadman.com/?utm_source=aff_repo&utm_medium=index_copy). Learn more in the [LICENSE](https://github.com/russellsteadman/affiliate/blob/master/LICENSE) file. +MIT (C) [Russell Steadman](https://www.russellsteadman.com/?utm_source=aff_repo&utm_medium=readme_copy). Learn more in the [LICENSE](https://github.com/russellsteadman/affiliate/blob/master/LICENSE) file. diff --git a/docs/plugins/amazon.md b/docs/plugins/amazon.md index 15f6da5..eac2411 100644 --- a/docs/plugins/amazon.md +++ b/docs/plugins/amazon.md @@ -9,7 +9,7 @@ Make sure [Affiliate](https://affiliate.js.org/) is already installed. Read the ## Installation ```bash -$ npm install --save affiliate affiliate-plugin-amazon +$ npm install affiliate affiliate-plugin-amazon $ yarn add affiliate affiliate-plugin-amazon ``` diff --git a/package-lock.json b/package-lock.json index a53573f..a18bd79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,13 @@ { "name": "affiliate", - "version": "4.0.0-beta0", + "version": "4.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "affiliate", - "version": "4.0.0-beta0", + "version": "4.0.0", "license": "MIT", - "dependencies": { - "url-parse": "^1.5.3" - }, "devDependencies": { "@babel/core": "^7.15.8", "@babel/plugin-proposal-class-properties": "^7.14.5", @@ -24,17 +21,18 @@ "@typescript-eslint/parser": "^5.0.0", "babel-jest": "^27.2.5", "babel-loader": "^8.2.2", - "core-js": "^3.18.2", - "eslint": "^8.0.0", + "core-js": "^3.18.3", + "eslint": "^8.0.1", "eslint-config-google": "^0.14.0", + "eslint-config-prettier": "^8.3.0", "fork-ts-checker-webpack-plugin": "^6.3.4", "jest": "^27.2.5", "jest-environment-puppeteer": "^6.0.0", "puppeteer": "^10.4.0", "regenerator-runtime": "^0.13.9", "ts-loader": "^9.2.6", - "typescript": "^4.4.3", - "webpack": "^5.58.1", + "typescript": "^4.4.4", + "webpack": "^5.58.2", "webpack-cli": "^4.9.0" } }, @@ -1686,9 +1684,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.2.tgz", - "integrity": "sha512-x1ZXdEFsvTcnbTZgqcWUL9w2ybgZCw/qbKTPQnab+XnYA2bMQpJCh+/bBzCRfDJaJdlrrQlOk49jNtru9gL/6Q==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.3.tgz", + "integrity": "sha512-DHI1wDPoKCBPoLZA3qDR91+3te/wDSc1YhKg3jR8NxKKRJq2hwHwcWv31cSwSYvIBrmbENoYMWcenW8uproQqg==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -2842,15 +2840,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -3914,9 +3903,9 @@ } }, "node_modules/core-js": { - "version": "3.18.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.2.tgz", - "integrity": "sha512-zNhPOUoSgoizoSQFdX1MeZO16ORRb9FFQLts8gSYbZU5FcgXhp24iMWMxnOQo5uIaIG7/6FA/IqJPwev1o9ZXQ==", + "version": "3.18.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.3.tgz", + "integrity": "sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw==", "dev": true, "hasInstallScript": true, "funding": { @@ -4379,12 +4368,12 @@ } }, "node_modules/eslint": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.0.0.tgz", - "integrity": "sha512-03spzPzMAO4pElm44m60Nj08nYonPGQXmw6Ceai/S4QK82IgwWO1EXx1s9namKzVlbVu3Jf81hb+N+8+v21/HQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.0.1.tgz", + "integrity": "sha512-LsgcwZgQ72vZ+SMp4K6pAnk2yFDWL7Ti4pJaRvsZ0Hsw2h8ZjUIW38a9AFn2cZXdBMlScMFYYgsSp4ttFI/0bA==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.0.2", + "@eslint/eslintrc": "^1.0.3", "@humanwhocodes/config-array": "^0.6.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -4445,6 +4434,18 @@ "eslint": ">=5.16.0" } }, + "node_modules/eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -4485,6 +4486,15 @@ "node": ">=10" } }, + "node_modules/eslint-visitor-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", + "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -4571,15 +4581,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/eslint/node_modules/estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", @@ -4684,15 +4685,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -8774,11 +8766,6 @@ } } }, - "node_modules/querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -8936,11 +8923,6 @@ "node": ">=0.10.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, "node_modules/resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -9823,9 +9805,9 @@ } }, "node_modules/typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -9927,15 +9909,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-parse": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", - "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -10043,9 +10016,9 @@ } }, "node_modules/webpack": { - "version": "5.58.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.58.1.tgz", - "integrity": "sha512-4Z/dmbTU+VmkCb2XNgW7wkE5TfEcSooclprn/UEuVeAkwHhn07OcgUsyaKHGtCY/VobjnsYBlyhKeMLiSoOqPg==", + "version": "5.58.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.58.2.tgz", + "integrity": "sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.0", @@ -11612,9 +11585,9 @@ "dev": true }, "@eslint/eslintrc": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.2.tgz", - "integrity": "sha512-x1ZXdEFsvTcnbTZgqcWUL9w2ybgZCw/qbKTPQnab+XnYA2bMQpJCh+/bBzCRfDJaJdlrrQlOk49jNtru9gL/6Q==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.3.tgz", + "integrity": "sha512-DHI1wDPoKCBPoLZA3qDR91+3te/wDSc1YhKg3jR8NxKKRJq2hwHwcWv31cSwSYvIBrmbENoYMWcenW8uproQqg==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -12496,14 +12469,6 @@ "requires": { "@typescript-eslint/types": "5.0.0", "eslint-visitor-keys": "^3.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", - "dev": true - } } }, "@webassemblyjs/ast": { @@ -13362,9 +13327,9 @@ } }, "core-js": { - "version": "3.18.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.2.tgz", - "integrity": "sha512-zNhPOUoSgoizoSQFdX1MeZO16ORRb9FFQLts8gSYbZU5FcgXhp24iMWMxnOQo5uIaIG7/6FA/IqJPwev1o9ZXQ==", + "version": "3.18.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.3.tgz", + "integrity": "sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw==", "dev": true }, "core-js-compat": { @@ -13715,12 +13680,12 @@ } }, "eslint": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.0.0.tgz", - "integrity": "sha512-03spzPzMAO4pElm44m60Nj08nYonPGQXmw6Ceai/S4QK82IgwWO1EXx1s9namKzVlbVu3Jf81hb+N+8+v21/HQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.0.1.tgz", + "integrity": "sha512-LsgcwZgQ72vZ+SMp4K6pAnk2yFDWL7Ti4pJaRvsZ0Hsw2h8ZjUIW38a9AFn2cZXdBMlScMFYYgsSp4ttFI/0bA==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.0.2", + "@eslint/eslintrc": "^1.0.3", "@humanwhocodes/config-array": "^0.6.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -13820,12 +13785,6 @@ "estraverse": "^5.2.0" } }, - "eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", - "dev": true - }, "estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", @@ -13895,6 +13854,13 @@ "dev": true, "requires": {} }, + "eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true, + "requires": {} + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -13922,6 +13888,12 @@ } } }, + "eslint-visitor-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", + "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", + "dev": true + }, "espree": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.0.0.tgz", @@ -13931,14 +13903,6 @@ "acorn": "^8.5.0", "acorn-jsx": "^5.3.1", "eslint-visitor-keys": "^3.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz", - "integrity": "sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==", - "dev": true - } } }, "esprima": { @@ -17021,11 +16985,6 @@ } } }, - "querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==" - }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -17144,11 +17103,6 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -17808,9 +17762,9 @@ } }, "typescript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", - "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", "dev": true }, "unbzip2-stream": { @@ -17878,15 +17832,6 @@ "punycode": "^2.1.0" } }, - "url-parse": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", - "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -17975,9 +17920,9 @@ "dev": true }, "webpack": { - "version": "5.58.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.58.1.tgz", - "integrity": "sha512-4Z/dmbTU+VmkCb2XNgW7wkE5TfEcSooclprn/UEuVeAkwHhn07OcgUsyaKHGtCY/VobjnsYBlyhKeMLiSoOqPg==", + "version": "5.58.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.58.2.tgz", + "integrity": "sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", diff --git a/package.json b/package.json index 807a7a7..adf8a2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "affiliate", - "version": "4.0.0-beta0", + "version": "4.0.0", "description": "A platform agnostic tool to quickly add affiliate links onto your website", "main": "dist/node/index.js", "repository": "https://github.com/russellsteadman/affiliate.git", @@ -25,17 +25,18 @@ "@typescript-eslint/parser": "^5.0.0", "babel-jest": "^27.2.5", "babel-loader": "^8.2.2", - "core-js": "^3.18.2", - "eslint": "^8.0.0", + "core-js": "^3.18.3", + "eslint": "^8.0.1", "eslint-config-google": "^0.14.0", + "eslint-config-prettier": "^8.3.0", "fork-ts-checker-webpack-plugin": "^6.3.4", "jest": "^27.2.5", "jest-environment-puppeteer": "^6.0.0", "puppeteer": "^10.4.0", "regenerator-runtime": "^0.13.9", "ts-loader": "^9.2.6", - "typescript": "^4.4.3", - "webpack": "^5.58.1", + "typescript": "^4.4.4", + "webpack": "^5.58.2", "webpack-cli": "^4.9.0" }, "keywords": [ @@ -57,9 +58,6 @@ "build": "webpack --config config/webpack.config.js && tsc -p .", "test": "jest" }, - "dependencies": { - "url-parse": "^1.5.3" - }, "jest": { "clearMocks": true, "collectCoverage": false, diff --git a/src/Affiliate.ts b/src/Affiliate.ts index 5dc7c47..98d7749 100644 --- a/src/Affiliate.ts +++ b/src/Affiliate.ts @@ -1,12 +1,7 @@ -import URLParse from 'url-parse'; +import { hasMutationObserver, hasURL } from './shared/features'; import Log from './shared/log'; import { getNodeData, setNodeData } from './shared/nodeTools'; -// Check for MutationObserver -const canObserve = - typeof window === 'object' && - !(typeof window.MutationObserver === 'undefined'); - export interface AffiliateConfigTag { hosts: string | string[]; query?: { [key: string]: string }; @@ -14,7 +9,7 @@ export interface AffiliateConfigTag { to: string; from: string; }[]; - modify?: (url: URLParse) => URLParse | string; + modify?: (url: URL) => URL | string; } export interface AffiliateConfig { @@ -66,12 +61,12 @@ class Affiliate { }); // Set logging function - this.log = config.log ? Log : () => {}; + this.log = config.log ? Log : () => undefined; this.log(false, 'New Instance', config); // Check is MutationObserver is supported - if (canObserve) { + if (hasMutationObserver) { // Initialize MutationObserver this.observer = new window.MutationObserver((mutations) => { // This function is called for every DOM mutation @@ -79,28 +74,28 @@ class Affiliate { // Has a mutation been logged let emitted = false; - for (let i in mutations) { + mutations.forEach((mutation) => { // If the attributes of the link have been modified - if (mutations[i].type === 'attributes') { + if (mutation.type === 'attributes') { // Skip links without an href - if (mutations[i].attributeName !== 'href') continue; + if (mutation.attributeName !== 'href') return; - let href = (mutations[i].target).href; - let linkData = getNodeData(mutations[i].target); + const href = (mutation.target).href; + const linkData = getNodeData(mutation.target); // Skip links without a modified href - if (linkData.is && linkData.is === href) continue; + if (linkData.is && linkData.is === href) return; } // Only calls on first mutation if (!emitted) { - this.log(false, 'DOM Mutation', mutations[i]); + this.log(false, 'DOM Mutation', mutation); emitted = true; } // Scan the node and subnodes if there are any - this.traverse(mutations[i].target); - } + this.traverse(mutation.target); + }); }); } @@ -114,17 +109,22 @@ class Affiliate { * @function * @param {object=} nodeSet The node to traverse for links (default: document.body) */ - traverse(nodeSet: HTMLElement = document.body) { + traverse(nodeSet: HTMLElement = document.body): Affiliate { if ( typeof nodeSet !== 'object' || typeof nodeSet.getElementsByTagName !== 'function' ) - return; + return this; + + if (!hasURL) { + this.log(true, 'This browser needs a URL polyfill.'); + return this; + } this.log(false, 'Traversing DOM...'); // Reduce link collection to array - let collection = nodeSet.getElementsByTagName('a'); + const collection = nodeSet.getElementsByTagName('a'); let nodes = Object.values(collection); // If the nodeSet is a single link, turn to array @@ -137,8 +137,11 @@ class Affiliate { // Check if it is actually linking if (!node || !('href' in node)) return; - // Parse the URL via url-parse - let url = URLParse((node).href ?? '', true); + // Parse the URL natively + const url = new URL( + (node).href ?? '', + window?.location.origin, + ); // Only modify hosts provided. if (this.state.hosts.indexOf(url.host) === -1) return; @@ -148,6 +151,8 @@ class Affiliate { } }); }); + + return this; } /** @@ -159,31 +164,32 @@ class Affiliate { * @param {object} node Anchor link node * @param {object} tag Matching configuration tag */ - modifyURL = ( - url: URLParse, - node: HTMLAnchorElement, - tag: AffiliateConfigTag, - ) => { + modifyURL = (url: URL, node: HTMLAnchorElement, tag: AffiliateConfigTag) => { // Check if URL is already modified - let linkData = getNodeData(node); + const linkData = getNodeData(node); if (linkData.is && linkData.is === url.href) return; // Preserve the original URL - let originalURL = url.href; + const originalURL = url.href; this.log(false, 'Discovered URL: ' + url.href); // Change query variables - url.set('query', { ...url.query, ...tag.query }); + if (tag.query) { + Object.keys(tag.query ?? {}).forEach((key) => { + if (typeof tag.query === 'object') + url.searchParams.set(key, tag.query[key]); + }); + } // Run the modification function if (typeof tag.modify === 'function') { try { let returnedURL = tag.modify(url); if (typeof returnedURL === 'object') returnedURL = returnedURL.href; - url = URLParse(returnedURL, true); + url = new URL(returnedURL, window?.location.origin); } catch (e) { - Log(true, e); + Log(true, e as Error); } } @@ -197,7 +203,7 @@ class Affiliate { node.href = modifiedUrl; setNodeData(node, { was: originalURL, - is: url, + is: url.href, }); }; @@ -206,12 +212,12 @@ class Affiliate { * * @function */ - attach: () => void = () => { + attach = (): Affiliate => { // Cannot attach twice, cannot attach for node - if (this.state.attached || typeof document === 'undefined') return; + if (this.state.attached || typeof document === 'undefined') return this; // Get readyState, or the loading state of the DOM - let { readyState } = document; + const { readyState } = document; if (readyState === 'complete' || readyState === 'interactive') { // Set attached to true @@ -220,7 +226,7 @@ class Affiliate { // Run through the entire body tag this.traverse(); - if (canObserve && this.observer) { + if (hasMutationObserver && this.observer) { // Attach the observer this.observer.observe(document.body, { childList: true, @@ -234,8 +240,10 @@ class Affiliate { } } else { // Wait until the DOM loads - return window.addEventListener('DOMContentLoaded', this.attach); + window.addEventListener('DOMContentLoaded', this.attach); } + + return this; }; /** @@ -243,11 +251,12 @@ class Affiliate { * * @function */ - detach = () => { - if (!canObserve || !this.observer) return; + detach = (): Affiliate => { + if (!hasMutationObserver || !this.observer) return this; this.state.attached = false; this.observer.disconnect(); this.log(false, 'Observer disconnected.'); + return this; }; } diff --git a/src/index.ts b/src/index.ts index ffbc789..82a4912 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,15 +16,15 @@ class Generator { constructor() { try { - let config = AutoConfig(); + const config = AutoConfig(); if (typeof config === 'object') { - let auto = this.create(config); + const auto = this.create(config); Log(false, auto); this.state.auto = auto; auto.attach(); } } catch (e) { - Log(true, e); + Log(true, e as Error); } } @@ -36,7 +36,7 @@ class Generator { * @returns {object} Affiliate instance */ create = (config: Partial) => { - let Instance = new Affiliate(config); + const Instance = new Affiliate(config); this.state.instances.push(Instance); return Instance; }; @@ -56,9 +56,7 @@ class Generator { * @function */ detachAll = () => { - for (let i in this.state.instances) { - this.state.instances[i].detach(); - } + this.state.instances.forEach((instance) => instance.detach()); }; /** @@ -68,16 +66,14 @@ class Generator { */ revert = () => { this.detachAll(); - let nodes = ( - [].slice.call(document.body.getElementsByTagName('a')) - ); - for (let i in nodes) { - let linkData = getNodeData(nodes[i]); - if (linkData && linkData.was) { - nodes[i].href = linkData.was; - setNodeData(nodes[i], {}); + const nodes = Object.values(document.body.getElementsByTagName('a')); + nodes.forEach((node) => { + const linkData = getNodeData(node); + if (linkData && typeof linkData.was === 'string') { + node.href = linkData.was; + setNodeData(node, {}); } - } + }); }; } diff --git a/src/shared/autoConfig.ts b/src/shared/autoConfig.ts index c0ed713..ce0f240 100644 --- a/src/shared/autoConfig.ts +++ b/src/shared/autoConfig.ts @@ -1,52 +1,36 @@ -type BreakUpData = string | Array; - -/* Utility function for parsing data-aff syntax */ -const breakUp: (data: BreakUpData, delimiter: string) => BreakUpData = ( - data: BreakUpData | string, - delimiter: string -) => { - if (typeof data === 'object') { - for (let i in data) { - data[i] = breakUp(data[i], delimiter); - } - } else if (typeof data === 'string') { - data = data.split(delimiter); - for (let o in data) { - data[o] = (data[o]).trim(); - } - } - return data; -}; +const AUTO_CONFIG_SYNTAX_REGEX = /WHERE (.+?) SET (.+?)\s*(?:AND|$)/g; /* Setup automatic configuration */ const AutoConfig = () => { - let scriptNode = document.getElementById('aff-js'); + const scriptNode = document.getElementById('aff-js'); - if (typeof scriptNode === 'object' && scriptNode !== null) { - let nodeData = scriptNode.dataset.aff; + if (typeof scriptNode === 'object' && scriptNode) { + const nodeData = scriptNode?.dataset?.autoAffiliate; if (typeof nodeData === 'string') { - let parsedData = ( - breakUp(breakUp(breakUp(breakUp(nodeData, '!'), ':'), ','), '=') - ); - let tags = []; - - for (let i in parsedData) { - let tag: { - hosts: string[]; - query: { [key: string]: string }; - } = { - hosts: [], - query: {}, - }; - for (let o in parsedData[i][0]) { - tag.hosts.push(parsedData[i][0][o][0]); - } - for (let u in parsedData[i][1]) { - tag.query[parsedData[i][1][u][0]] = parsedData[i][1][u][1]; - } - tags.push(tag); - } + const tags: { hosts: string[]; query: Record }[] = []; + + const expressions = nodeData.match(AUTO_CONFIG_SYNTAX_REGEX); + + if (!expressions) return; + + Object.values(expressions).forEach((expression) => { + const components = AUTO_CONFIG_SYNTAX_REGEX.exec(expression); + + if (!components || components.length !== 3) return; + + const hosts = components[1]; + const queries = components[2]; + + tags.push({ + hosts: hosts.split(',').map((host) => host.trim()), + query: queries.split(',').reduce((a, b) => { + const [key, value] = b.split('='); + if (key && value) a[key.trim()] = value.trim(); + return a; + }, {} as Record), + }); + }); return { tags }; } diff --git a/src/shared/features.ts b/src/shared/features.ts new file mode 100644 index 0000000..aee16a5 --- /dev/null +++ b/src/shared/features.ts @@ -0,0 +1,8 @@ +// Check for MutationObserver +export const hasMutationObserver = + typeof window === 'object' && + !(typeof window.MutationObserver === 'undefined'); + +// Check for URL and URLSearchParams +export const hasURL = + typeof URL === 'function' && typeof URLSearchParams === 'function'; diff --git a/src/shared/log.ts b/src/shared/log.ts index 3c11787..e6dc7b1 100644 --- a/src/shared/log.ts +++ b/src/shared/log.ts @@ -3,7 +3,10 @@ * * @module affiliate/src/Log */ -export default function (isError: boolean, ...args: any) { +export default function ( + isError: boolean, + ...args: (string | number | object)[] +) { const textId = '[Affiliate] '; if (typeof console === 'object') { diff --git a/src/shared/nodeTools.ts b/src/shared/nodeTools.ts index c334b78..f1322ee 100644 --- a/src/shared/nodeTools.ts +++ b/src/shared/nodeTools.ts @@ -1,14 +1,14 @@ -const NODE_DATA_KEY = '_aff_data'; +const NODE_DATA_KEY = '_aff'; -type DataNode = Node & { [NODE_DATA_KEY]?: Record }; +type DataNode = Node & { [NODE_DATA_KEY]?: Record }; -export const getNodeData = (node: DataNode): Record => { +export const getNodeData = (node: DataNode): Record => { return node[NODE_DATA_KEY] ?? {}; }; export const setNodeData = ( node: DataNode, - data: Record, + data: Record, ): void => { Object.assign(node, { [NODE_DATA_KEY]: data }); }; diff --git a/tests/auto-browser.test.js b/tests/auto-browser.test.js index bb4b62e..47fd78d 100644 --- a/tests/auto-browser.test.js +++ b/tests/auto-browser.test.js @@ -43,8 +43,8 @@ window.optionOne = { } ], modify: function (url) { - url.set('pathname', url.pathname + '-tag'); - url.set('hostname', 'tst.' + url.hostname); + url.pathname = url.pathname + '-tag'; + url.hostname = 'tst.' + url.hostname; return url; } } @@ -70,8 +70,8 @@ window.optionTwo = { } ], modify: function (url) { - url.set('pathname', url.pathname + '-tag2'); - url.set('hostname', 'tst2.' + url.hostname); + url.pathname = url.pathname + '-tag2'; + url.hostname = 'tst2.' + url.hostname; return url; } } @@ -183,7 +183,7 @@ test('Instance can mutate links', async () => { ); }); -test('Instance can use data-aff', async () => { +test('Instance can use data-auto-affiliate', async () => { await page.goto(LANDING_PAGE); await page.evaluate(UTILITIES); @@ -199,11 +199,11 @@ test('Instance can use data-aff', async () => { (document, Affiliate) => { var script = document.createElement('script'); script.setAttribute( - 'data-aff', - 'amazon.com, www.amazon.com : tag = my-amz-tag', + 'data-auto-affiliate', + 'WHERE amazon.com, www.amazon.com SET tag = my-amz-tag', ); script.setAttribute('id', 'aff-js'); - script.setAttribute('async', ''); + // script.setAttribute('async', ''); script.innerHTML = Affiliate; document.head.appendChild(script); },