From 34508a1c2d690f3552b4f8feef739483a7f3ccee Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 7 Oct 2024 08:47:45 -0400 Subject: [PATCH] Add demo.js to npm build To help people to get quickly started with using the package. --- platform/nodejs/index.js | 1 + platform/npm/demo.js | 120 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 platform/npm/demo.js diff --git a/platform/nodejs/index.js b/platform/nodejs/index.js index 5fad3bec2..56aa74f42 100644 --- a/platform/nodejs/index.js +++ b/platform/nodejs/index.js @@ -119,6 +119,7 @@ function pslInit(raw) { /******************************************************************************/ function compileList({ name, raw }, compiler, writer, options = {}) { + if ( typeof raw !== 'string' || raw === '' ) { return; } const lineIter = new LineIterator(raw); const events = Array.isArray(options.events) ? options.events : undefined; diff --git a/platform/npm/demo.js b/platform/npm/demo.js new file mode 100644 index 000000000..ebe314b2f --- /dev/null +++ b/platform/npm/demo.js @@ -0,0 +1,120 @@ +/******************************************************************************* + * + * A simple demo to quickly get started. + * + * Command line: + * + * mkdir myproject + * cd myproject + * npm install @gorhill/ubo-core + * cp node_modules/@gorhill/ubo-core/demo.js . + * + * There will be a `demo.js` file in your `myproject` folder, which you can + * modify and execute: + * + * node demo.js + * + * Since the demo here uses ES module syntax, you may want to add the following + * to the generated package.json file to avoid the warning: + * + * "type": "module", + * + * The demo will fetch filter lists from EasyList server, then serialize the + * content of the static network filtering engine into a local `./cache/` + * folder. + * + * The serialized data will be reused if available in order to avoid fetching + * from remote server each time it is executed. + * + * This demo is kept as simple as possible, so there is not a lot of error + * handling. + * + * */ + +import fs from 'fs/promises'; +import { StaticNetFilteringEngine } from '@gorhill/ubo-core'; + +/******************************************************************************/ + +async function main() { + const pathToSelfie = 'cache/selfie.txt'; + + const snfe = await StaticNetFilteringEngine.create(); + + // Up to date serialization data (aka selfie) available? + let selfie; + const ageInDays = await fs.stat(pathToSelfie).then(stat => { + const fileDate = new Date(stat.mtime); + return (Date.now() - fileDate.getTime()) / (7 * 24 * 60 * 60); + }).catch(( ) => Number.MAX_SAFE_INTEGER); + + // Use a selfie if available and not older than 7 days + if ( ageInDays <= 7 ) { + selfie = await fs.readFile(pathToSelfie, { encoding: 'utf8' }) + .then(data => typeof data === 'string' && data !== '' && data) + .catch(( ) => { }); + if ( typeof selfie === 'string' ) { + await snfe.deserialize(selfie); + } + } + + // Fetch filter lists if no up to date selfie available + if ( !selfie ) { + console.log(`Fetching lists...`); + await snfe.useLists([ + fetch('https://easylist.to/easylist/easylist.txt') + .then(r => { + return r.text(); + }).then(raw => { + console.log(`easylist fetched`); + return { name: 'easylist', raw }; + }).catch(reason => { + console.error(reason); + }), + fetch('https://easylist.to/easylist/easyprivacy.txt') + .then(r => { + return r.text(); + }).then(raw => { + console.log(`easyprivacy fetched`); + return { name: 'easyprivacy', raw }; + }).catch(reason => { + console.error(reason); + }), + ]); + const selfie = await snfe.serialize(); + await fs.mkdir('cache', { recursive: true }); + await fs.writeFile(pathToSelfie, selfie); + } + + // List of tests to perform + const tests = [ + { + originURL: 'https://www.bloomberg.com/', + url: 'https://www.google-analytics.com/gs.js', + type: 'script', + }, { + originURL: 'https://www.bloomberg.com/', + url: 'https://securepubads.g.doubleclick.net/tag/js/gpt.js', + type: 'script', + }, { + originURL: 'https://www.bloomberg.com/', + url: 'https://bloomberg.com/main.css', + type: 'stylesheet', + } + ]; + + // Test each entry for a match against the content of the engine + for ( const test of tests ) { + console.log('\nRequest details:', test); + const r = snfe.matchRequest(test); + if ( r === 1 ) { // Blocked + console.log('Blocked:', snfe.toLogData()); + } else if ( r === 2 ) { // Unblocked + console.log('Unblocked:', snfe.toLogData()); + } else { // Not blocked + console.log('Not blocked'); + } + } +} + +main();