Skip to content

Commit

Permalink
Merge pull request #133 from richardfrost/config_ui_updates
Browse files Browse the repository at this point in the history
Config ui updates
  • Loading branch information
richardfrost authored Apr 15, 2019
2 parents 12b089c + 9a784f5 commit 20dff15
Show file tree
Hide file tree
Showing 11 changed files with 1,579 additions and 2,872 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@
# Testing
/test/built/*
/test/.nyc_output/*
/test/coverage/*
/test/coverage/*

# Built shared libs
/src/script/lib/*.js
1 change: 1 addition & 0 deletions bin/watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function compileScript(file) {
try {
console.log('Building Typescript...');
execSync('npm run build');
console.log('done.');
} catch(err) {
console.log('Error: ', err);
}
Expand Down
4,278 changes: 1,457 additions & 2,821 deletions package-lock.json

Large diffs are not rendered by default.

48 changes: 24 additions & 24 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "advancedprofanityfilter",
"version": "2.1.0",
"version": "2.1.1",
"description": "A browser extension to filter profanity from webpages.",
"main": "filter.js",
"repository": {
Expand Down Expand Up @@ -40,31 +40,31 @@
"watch": "node bin/watch.js"
},
"devDependencies": {
"@babel/cli": "^7.2.0",
"@babel/core": "^7.2.0",
"@babel/plugin-proposal-class-properties": "^7.2.3",
"@babel/plugin-proposal-object-rest-spread": "^7.2.0",
"@babel/polyfill": "^7.2.5",
"@babel/preset-env": "^7.2.3",
"@babel/preset-typescript": "^7.1.0",
"@babel/register": "^7.0.0",
"@types/chrome": "latest",
"@typescript-eslint/eslint-plugin": "^1.1.1",
"@typescript-eslint/parser": "^1.1.1",
"adm-zip": "^0.4.11",
"babel-loader": "^8.0.4",
"chai": "latest",
"chokidar": "^2.0.4",
"@babel/cli": "^7.4.3",
"@babel/core": "^7.4.3",
"@babel/plugin-proposal-class-properties": "^7.4.0",
"@babel/plugin-proposal-object-rest-spread": "^7.4.3",
"@babel/polyfill": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"@babel/preset-typescript": "^7.3.3",
"@babel/register": "^7.4.0",
"@types/chrome": "^0.0.81",
"@typescript-eslint/eslint-plugin": "^1.6.0",
"@typescript-eslint/parser": "^1.6.0",
"adm-zip": "git+https://github.com/cthackers/adm-zip.git",
"babel-loader": "^8.0.5",
"chai": "^4.2.0",
"chokidar": "^2.1.5",
"download": "^7.1.0",
"eslint": "^5.2.0",
"fs-extra": "^7.0.0",
"marked": "^0.5.1",
"mocha": "latest",
"nyc": "latest",
"eslint": "^5.16.0",
"fs-extra": "^7.0.1",
"marked": "^0.5.2",
"mocha": "^6.0.2",
"nyc": "^13.3.0",
"terser-webpack-plugin": "^1.2.3",
"typescript": "^3.2.2",
"webpack": "^4.28.1",
"webpack-cli": "^3.1.2"
"typescript": "^3.4.2",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0"
},
"babel": {
"presets": [
Expand Down
8 changes: 6 additions & 2 deletions src/script/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,18 @@ export default class Config {
'dammit': { matchMethod: 1, repeat: false, sub: 'dangit' },
'damn': { matchMethod: 1, repeat: false, sub: 'dang' },
'dumbass': { matchMethod: 1, repeat: true, sub: 'idiot' },
'fag': { matchMethod: 0, repeat: true, sub: 'slur' },
'faggot': { matchMethod: 1, repeat: true, sub: 'slur' },
'fags': { matchMethod: 0, repeat: true, sub: 'slurs' },
'fuck': { matchMethod: 1, repeat: true, sub: 'fudge' },
'goddammit': { matchMethod: 1, repeat: true, sub: 'goshdangit' },
'hell': { matchMethod: 0, repeat: true, sub: 'heck' },
'jackass': { matchMethod: 1, repeat: true, sub: 'idiot' },
'jesus christ': { matchMethod: 1, repeat: true, sub: 'deity' },
'jesus': { matchMethod: 1, repeat: true, sub: 'deity' },
'nigga': { matchMethod: 1, repeat: true, sub: 'ethnic slur' },
'nigger': { matchMethod: 1, repeat: true, sub: 'ethnic slur' },
'nigga': { matchMethod: 0, repeat: true, sub: 'ethnic slur' },
'nigger': { matchMethod: 0, repeat: true, sub: 'ethnic slur' },
'niggers': { matchMethod: 0, repeat: true, sub: 'ethnic slur' },
'piss': { matchMethod: 1, repeat: true, sub: 'pee' },
'pissed': { matchMethod: 1, repeat: true, sub: 'ticked' },
'pussies': { matchMethod: 0, repeat: true, sub: 'softies' },
Expand Down
8 changes: 8 additions & 0 deletions src/script/lib/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ export function isVersionOlder(version: Version, minimum: Version): boolean {
return false;
}

export function readFile(file) {
return new Promise((resolve, reject) => {
let fr = new FileReader();
fr.onload = () => { resolve(fr.result); };
fr.readAsText(file);
});
}

export function removeFromArray(array: string[], element: string) {
return array.filter(e => e !== element);
}
72 changes: 57 additions & 15 deletions src/script/optionPage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { dynamicList, escapeHTML, exportToFile } from './lib/helper';
import { dynamicList, escapeHTML, exportToFile, readFile } from './lib/helper';
import WebConfig from './webConfig';
import { Filter } from './lib/filter';
import OptionAuth from './optionAuth';
Expand Down Expand Up @@ -142,6 +142,18 @@ export default class OptionPage {
}
}

configInlineToggle() {
let input = document.getElementById('configInlineInput') as HTMLInputElement;
let configText = document.getElementById('configText') as HTMLTextAreaElement;
if (input.checked) {
OptionPage.show(configText);
option.exportConfig();
} else {
OptionPage.hide(configText);
configText.value = '';
}
}

confirm(evt, action) {
let ok = document.getElementById('confirmModalOK');
ok.removeEventListener('click', importConfig);
Expand All @@ -151,8 +163,6 @@ export default class OptionPage {

switch(action) {
case 'importConfig': {
let configText = document.getElementById('configText') as HTMLTextAreaElement;
if (!configText.value) return false;
OptionPage.configureConfirmModal('Are you sure you want to overwrite your existing settings?');
ok.addEventListener('click', importConfig);
break;
Expand Down Expand Up @@ -244,20 +254,45 @@ export default class OptionPage {
}

exportConfig() {
let configText = document.getElementById('configText') as HTMLTextAreaElement;
configText.value = JSON.stringify(this.cfg, null, 2);
let input = document.getElementById('configInlineInput') as HTMLInputElement;

if (input.checked) { // inline editor
let configText = document.getElementById('configText') as HTMLTextAreaElement;
configText.value = JSON.stringify(this.cfg, null, 2);
} else {
let date = new Date;
let today = `${date.getUTCFullYear()}-${('0'+(date.getUTCMonth()+1)).slice(-2)}-${('0'+(date.getUTCDate()+1)).slice(-2)}`;
exportToFile(JSON.stringify(this.cfg, null, 2), `apf-backup-${today}.json`);
}
}

async importConfig(e) {
let input = document.getElementById('configInlineInput') as HTMLInputElement;
if (input.checked) { // inline editor
let configText = document.getElementById('configText') as HTMLTextAreaElement;
this.importConfigText(configText.value);
} else {
let importFileInput = document.getElementById('importFileInput') as HTMLInputElement;
importFileInput.click();
}
}

async importConfigFile(e) {
let file = e.target.files[0];
let importFileInput = document.getElementById('importFileInput') as HTMLInputElement;
let fileText = await readFile(file) as string;
option.importConfigText(fileText);
importFileInput.value = '';
}

async importConfig(evt) {
async importConfigText(cfg: string) {
let self = this;

try {
let configText = document.getElementById('configText') as HTMLTextAreaElement;
let importedCfg = new WebConfig(JSON.parse(configText.value));
let importedCfg = new WebConfig(JSON.parse(cfg));
let migration = new DataMigration(importedCfg);
migration.runImportMigrations();

let resetSuccess = await self.restoreDefaults(evt, true);
let resetSuccess = await self.restoreDefaults(null, true);

if (resetSuccess) {
self.cfg = importedCfg;
Expand All @@ -268,11 +303,9 @@ export default class OptionPage {
} else {
OptionPage.showErrorModal('Failed to import settings.');
}
} else {
OptionPage.showErrorModal('Failed to import settings.');
}
} catch (e) {
OptionPage.showErrorModal();
} catch(e) {
OptionPage.showErrorModal('Failed to import settings.');
}
}

Expand Down Expand Up @@ -420,7 +453,14 @@ export default class OptionPage {

Object.keys(option.cfg.words).sort().forEach(word => {
let filteredWord = word;
if (this.cfg.filterWordList) filteredWord = filter.replaceText(word, false);
if (filter.cfg.filterWordList) {
if (filter.cfg.words[word].matchMethod == 4) { // Regexp
filteredWord = filter.cfg.words[word].sub || filter.cfg.defaultSubstitution;
} else {
filteredWord = filter.replaceText(word, false);
}
}

wordListHTML += `<option value="${word}" data-filtered="${filteredWord}">${escapeHTML(filteredWord)}</option>`;
});

Expand Down Expand Up @@ -727,6 +767,8 @@ document.querySelectorAll('#audioSubtitleSelection input').forEach(el => { el.ad
document.getElementById('bookmarkletFile').addEventListener('click', e => { option.exportBookmarkletFile(); });
document.getElementById('bookmarkletHostedURL').addEventListener('input', e => { option.createBookmarklet(); });
// Config
document.getElementById('configInlineInput').addEventListener('click', e => { option.configInlineToggle(); });
document.getElementById('importFileInput').addEventListener('change', e => { option.importConfigFile(e); });
document.getElementById('configReset').addEventListener('click', e => { option.confirm(e, 'restoreDefaults'); });
document.getElementById('configExport').addEventListener('click', e => { option.exportConfig(); });
document.getElementById('configImport').addEventListener('click', e => { option.confirm(e, 'importConfig'); });
Expand Down
6 changes: 3 additions & 3 deletions src/script/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Domain from './domain';

interface Summary {
[word: string]: {
clean: string;
filtered: string;
count: number;
};
}
Expand Down Expand Up @@ -159,8 +159,8 @@ class Popup {
let tableInnerHTML = '';
if (Object.keys(summary).length > 0) {
tableInnerHTML = '<table class="w3-table w3-striped w3-border w3-bordered w3-card w3-small"><tr class="w3-flat-peter-river"><th colspan="2" class="w3-center">Filtered Words</th></tr>';
Object.keys(summary).forEach(key => {
tableInnerHTML += `<tr><td class="w3-tooltip"><span style="position:absolute;left:0;bottom:18px" class="w3-text w3-tag">${escapeHTML(key)}</span>${escapeHTML(summary[key].clean)}</td><td class="w3-right">${summary[key].count}</td></tr>`;
Object.keys(summary).sort((a,b) => summary[b].count - summary[a].count).forEach(key => {
tableInnerHTML += `<tr><td class="w3-tooltip"><span style="position:absolute;left:0;bottom:18px" class="w3-text w3-tag">${escapeHTML(key)}</span>${escapeHTML(summary[key].filtered)}</td><td class="w3-right">${summary[key].count}</td></tr>`;
});
tableInnerHTML += '</table>';
}
Expand Down
9 changes: 8 additions & 1 deletion src/script/webFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,14 @@ export default class WebFilter extends Filter {
if (this.summary[word]) {
this.summary[word].count += 1;
} else {
this.summary[word] = { clean: filter.replaceText(word, false), count: 1 };
let result;
if (this.cfg.words[word].matchMethod == 4) { // Regexp
result = this.cfg.words[word].sub || this.cfg.defaultSubstitution;
} else {
result = filter.replaceText(word, false);
}

this.summary[word] = { filtered: result, count: 1 };
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/static/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"short_name": "Profanity Filter",
"author": "Richard Frost",
"manifest_version": 2,
"version": "2.1.0",
"version": "2.1.1",
"description": "Advanced Profanity Filter helps to clean up bad language on the websites you and your family visit.",
"icons": {
"16": "img/icon16.png",
Expand Down
14 changes: 10 additions & 4 deletions src/static/optionPage.html
Original file line number Diff line number Diff line change
Expand Up @@ -306,15 +306,18 @@ <h4 class="sectionHeader">Bookmarklet:</h4>
</div>

<div id="configPage" class="w3-container w3-hide">
<h4 class="sectionHeader">Configuration</h4>
<label style="display:block;"><input id="configInlineInput" type="checkbox" class="w3-check"> Inline Editor</label>
<div style="padding-top:16px;padding-bottom:16px;width:500px;">
<input type="file" id="importFileInput" accept=".json" style="display:none"/>
<button id="configExport" class="w3-btn w3-round-large w3-flat-peter-river">EXPORT</button>
<button id="configImport" class="w3-btn w3-round-large w3-flat-peter-river">IMPORT</button>
<button id="configReset" class="w3-btn w3-round-large w3-flat-pomegranate w3-right">RESTORE DEFAULTS</button>
</div>
<textarea id="configText" class="w3-input w3-border w3-card" style="width:500px;height:550px;" spellcheck="false"></textarea>
<textarea id="configText" class="w3-input w3-border w3-card w3-hide" style="width:500px;height:550px;" spellcheck="false"></textarea>

<div id="setPasswordContainer" style="padding-top:16px;width:500px;">
<label for="setPassword">Password</label>
<div id="setPasswordContainer" style="width:500px;">
<h4 class="sectionHeader">Password</h4>
<input id="setPassword" class="w3-input w3-border small" style="display:inline">
<button id="setPasswordBtn" class="w3-btn w3-round-large w3-flat-pomegranate w3-right">REMOVE</button>
</div>
Expand Down Expand Up @@ -374,6 +377,7 @@ <h3 id="general-settings">General Settings</h3>
<li><strong>Show number of filtered words</strong> - Show a counter on the extension button with the number of filtered words.</li>
<li><strong>Show summary of filtered words</strong> - Show a summary of the words filtered on the current page.</li>
<li><strong>Filter word list in Options</strong> - This option will filter the word list in the options page.</li>
<li><strong>Show update notification</strong> - Show a notification when the extension gets updated.</li>
</ul>
<h3 id="default-settings-for-new-word-phrases-">Default Settings (for new word/phrases)</h3>
<ul>
Expand Down Expand Up @@ -412,13 +416,15 @@ <h1 id="audio-experimental-">Audio (Experimental)</h1>
</ul>
</li>
<li><strong>Subtitles</strong> - Controls which subtitles will be visible.<ul>
<li>Show all subtitles (<em>default</em>)</li>
<li>Show all subtitles (_default_)</li>
<li>Show only filtered subtitles - Least distracting</li>
<li>Show only unfiltered subtitles</li>
<li>Hide all subtitles - This may make it difficult to know what is happening when the audio is muted</li>
</ul>
</li>
</ul>
<h1 id="bookmarklet">Bookmarklet</h1>
<p>The bookmarklet allows you to run a minimal version of the filter on devices that can&#39;t install the full version. It is an advanced tool, and requires several steps to set it up. Learn more <a href="https://github.com/richardfrost/AdvancedProfanityFilter/wiki/Bookmarklet">here</a>.</p>
<h1 id="config">Config</h1>
<p>This tab allows you to control your configuration for the filter.</p>
<ul>
Expand Down

0 comments on commit 20dff15

Please sign in to comment.