diff --git "a/\"chrome_settings_overrides\": {" "b/\"chrome_settings_overrides\": {"
deleted file mode 100644
index 64c0635..0000000
--- "a/\"chrome_settings_overrides\": {"
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "name": "My extension",
- ...
- "chrome_settings_overrides": {
- "homepage": "http://www.homepage.com",
- "search_provider": {
- "name": "name.__MSG_url_domain__",
- "keyword": "keyword.__MSG_url_domain__",
- "search_url": "http://www.foo.__MSG_url_domain__/s?q={searchTerms}",
- "favicon_url": "http://www.foo.__MSG_url_domain__/favicon.ico",
- "suggest_url": "http://www.foo.__MSG_url_domain__/suggest?q={searchTerms}",
- "instant_url": "http://www.foo.__MSG_url_domain__/instant?q={searchTerms}",
- "image_url": "http://www.foo.__MSG_url_domain__/image?q={searchTerms}",
- "search_url_post_params": "search_lang=__MSG_url_domain__",
- "suggest_url_post_params": "suggest_lang=__MSG_url_domain__",
- "instant_url_post_params": "instant_lang=__MSG_url_domain__",
- "image_url_post_params": "image_lang=__MSG_url_domain__",
- "alternate_urls": [
- "http://www.moo.__MSG_url_domain__/s?q={searchTerms}",
- "http://www.noo.__MSG_url_domain__/s?q={searchTerms}"
- ],
- "encoding": "UTF-8",
- "is_default": true
- },
- "startup_pages": ["http://www.startup.com"]
- },
- "default_locale": "de",
- ...
-}
diff --git "a/\"manifest_version\": 2, \"name\": \"My Extension\", \"version\": \"versionString\"," "b/\"manifest_version\": 2, \"name\": \"My Extension\", \"version\": \"versionString\","
deleted file mode 100644
index 8dee193..0000000
--- "a/\"manifest_version\": 2, \"name\": \"My Extension\", \"version\": \"versionString\","
+++ /dev/null
@@ -1,3 +0,0 @@
- "manifest_version": 2,
- "name": "My Extension",
- "version": "versionString",
diff --git a/1 b/1
deleted file mode 100644
index 848d960..0000000
--- a/1
+++ /dev/null
@@ -1,9 +0,0 @@
- '{'.//// background.js
-
-chrome.runtime.onInstalled.addListener((reason) => {
- if (reason === chrome.runtime.OnInstalledReason.INSTALL) {
- chrome.tabs.create({
- '{'. url: 'onboarding.html'
- });
- }
-});
diff --git a/2 b/2
deleted file mode 100644
index 3858f34..0000000
--- a/2
+++ /dev/null
@@ -1,9 +0,0 @@
-//// background.js
-
-function toggleMuteState(tabId) {
- chrome.tabs.get(tabId, async (tab) => {
- let muted = !tab.mutedInfo.muted;
- await chrome.tabs.update(tabId, { muted });
- console.log(`Tab ${tab.id} is ${ muted ? 'muted' : 'unmuted' }`);
- });
-}
diff --git a/4 b/4
deleted file mode 100644
index 7c96fda..0000000
--- a/4
+++ /dev/null
@@ -1,17 +0,0 @@
-chrome.runtime.onMessage.addListener(
- function(request, sender, sendResponse) {
- console.log(sender.tab ?
- "from a content script:" + sender.tab.url :
- "from the extension");
- if (request.greeting == "hello")
- sendResponse({farewell: "goodbye"});
- }
-);
-var port = chrome.runtime.connect({name: "knockknock"});
-port.postMessage({joke: "Knock knock"});
-port.onMessage.addListener(function(msg) {
- if (msg.question == "Who's there?")
- port.postMessage({answer: "Madame"});
- else if (msg.question == "Madame who?")
- port.postMessage({answer: "Madame... Bovary"});
-});
diff --git a/5 b/5
deleted file mode 100644
index 62476bb..0000000
--- a/5
+++ /dev/null
@@ -1,12 +0,0 @@
-// For simple requests:
-chrome.runtime.onMessageExternal.addListener(
- function(request, sender, sendResponse) {
- if (sender.id == blocklistedExtension)
- return; // don't allow this extension access
- else if (request.getTargetData)
- sendResponse({targetData: targetData});
- else if (request.activateLasers) {
- var success = activateLasers();
- sendResponse({activateLasers: success});
- }
- });
diff --git a/555 b/555
deleted file mode 100644
index 2dd5d89..0000000
--- a/555
+++ /dev/null
@@ -1,9 +0,0 @@
----
-title: manifest_version
-slug: Mozilla/Add-ons/WebExtensions/manifest.json/manifest_version
-tags:
- - Add-ons
- - Extensions
- - WebExtensions
----
-
{{AddonSidebar}}
diff --git a/7 b/7
deleted file mode 100644
index b0f3ac3..0000000
--- a/7
+++ /dev/null
@@ -1,9 +0,0 @@
-var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
-
-// Make a simple request:
-chrome.runtime.sendMessage(laserExtensionId, {getTargetData: true},
- function(response) {
- if (targetInRange(response.targetData))
- chrome.runtime.sendMessage(laserExtensionId, {activateLasers: true});
- }
-);
diff --git a/89 b/89
deleted file mode 100644
index 0dcd69d..0000000
--- a/89
+++ /dev/null
@@ -1,2 +0,0 @@
-(port: Port) => {...}
-(details: object) => {...}
diff --git a/9 b/9
deleted file mode 100644
index bd8a42b..0000000
--- a/9
+++ /dev/null
@@ -1,32 +0,0 @@
-"externally_connectable": {
- "matches": ["*://*.example.com/*"]
-}"*", "*.com",
-var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
-chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
- function(response) {
- if (!response.success)
- handleError(url);
- });
- chrome.runtime.onMessageExternal.addListener(
- function(request, sender, sendResponse) {
- if (sender.url == blocklistedWebsite)
- return; // don't allow this web page access
- if (request.openUrlInEditor)
- openUrl(request.openUrlInEditor);
- });
- chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
- // WARNING! Might be evaluating an evil script!
- var resp = eval("(" + response.farewell + ")");
-});
-chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
- // WARNING! Might be injecting a malicious script!
- document.getElementById("resp").innerHTML = response.farewell;
-});
-chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
- // JSON.parse does not evaluate the attacker's scripts.
- var resp = JSON.parse(response.farewell);
-});
-chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
- // innerText does not let the attacker inject HTML elements.
- document.getElementById("resp").innerText = response.farewell;
-});
diff --git a/99 b/99
deleted file mode 100644
index 3386635..0000000
--- a/99
+++ /dev/null
@@ -1 +0,0 @@
-https://github.com/marketplace/profanity-filtered-muted/upgrade/1/CUSTOMER_ACCOUNT_ID
diff --git a/Conscript 1 b/Conscript 1
deleted file mode 100644
index d0357d7..0000000
--- a/Conscript 1
+++ /dev/null
@@ -1,7 +0,0 @@
-// Code for displaying /images/myimage.png:
-var imgURL = chrome.runtime.getURL("images/myimage.png");
-document.getElementById("someImage").src = imgURL;
-runtime.getURL(path: string): string
-() => {...}
-runtime.reload()
-(status: RequestUpdateCheckStatus, details: object) => {...}
diff --git a/Hulu App b/Hulu App
deleted file mode 100644
index 7c2abba..0000000
--- a/Hulu App
+++ /dev/null
@@ -1 +0,0 @@
-Mute Jesus in the Hulu App
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 261eeb9..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/Mani b/Mani
deleted file mode 100644
index 5113bb7..0000000
--- a/Mani
+++ /dev/null
@@ -1,2 +0,0 @@
-# ProfanityFilteredMuted
-(backgroundPage?: Window) => {...}
diff --git a/Manifisy b/Manifisy
deleted file mode 100644
index 685a098..0000000
--- a/Manifisy
+++ /dev/null
@@ -1,8 +0,0 @@
-const json = '{"result":true, "count":42}';
-const obj = JSON.parse(json);
-
-console.log(obj.count);
-// expected output: 42
-
-console.log(obj.result);
-// expected output: true
diff --git a/Po b/Po
deleted file mode 100644
index 751a211..0000000
--- a/Po
+++ /dev/null
@@ -1,12 +0,0 @@
-Traceback (most recent call last):
-File "D:/Work/Tests-Tutorials/german/TEIST.py", line 1, in
-from profanity_check import predict, predict_prob
-File "C:\Users\fasol\AppData\Local\Programs\Python\Python38\lib\site-packages\profanity_check_init_.py", line 1, in
-from .profanity_check import predict, predict_prob
-File "C:\Users\fasol\AppData\Local\Programs\Python\Python38\lib\site-packages\profanity_check\profanity_check.py", line 3, in
-from sklearn.externals import joblib
-ImportError: cannot import name 'joblib' from 'sklearn.externals' (C:\Users\fasol\AppData\Local\Programs\Python\Python38\lib\site-packages\sklearn\externals_init_.py)
-[0.08686173]
-
-predict_prob(['go to hell, you scum'])
-predict_prob('slut'
diff --git a/Port b/Port
deleted file mode 100644
index 5113bb7..0000000
--- a/Port
+++ /dev/null
@@ -1,2 +0,0 @@
-# ProfanityFilteredMuted
-(backgroundPage?: Window) => {...}
diff --git a/Profanity loving b/Profanity loving
deleted file mode 100644
index 988d78a..0000000
--- a/Profanity loving
+++ /dev/null
@@ -1,2 +0,0 @@
-[0.7618861]
-Mute Hell
diff --git a/Scriptable b/Scriptable
deleted file mode 100644
index 00b3280..0000000
--- a/Scriptable
+++ /dev/null
@@ -1,103 +0,0 @@
-// Variables used by Scriptable.
-// These must be at the very top of the file. Do not edit.
-// icon-color: deep-blue; icon-glyph: book;
-// This script shows a random Scriptable API in a widget. The script is meant to be used with a widget configured on the Home Screen.
-// You can run the script in the app to preview the widget or you can go to the Home Screen, add a new Scriptable widget and configure the widget to run this script.
-// You can also try creating a shortcut that runs this script. Running the shortcut will show widget.
-let api = await randomAPI()
-let widget = await createWidget(api)
-if (config.runsInWidget) {
- // The script runs inside a widget, so we pass our instance of ListWidget to be shown inside the widget on the Home Screen.
- Script.setWidget(widget)
-} else {
- // The script runs inside the app, so we preview the widget.
- widget.presentMedium()
-}
-// Calling Script.complete() signals to Scriptable that the script have finished running.
-// This can speed up the execution, in particular when running the script from Shortcuts or using Siri.
-Script.complete()
-
-async function createWidget(api) {
- let appIcon = await loadAppIcon()
- let title = "Random Scriptable API"
- let widget = new ListWidget()
- // Add background gradient
- let gradient = new LinearGradient()
- gradient.locations = [0, 1]
- gradient.colors = [
- new Color("141414"),
- new Color("13233F")
- ]
- widget.backgroundGradient = gradient
- // Show app icon and title
- let titleStack = widget.addStack()
- let appIconElement = titleStack.addImage(appIcon)
- appIconElement.imageSize = new Size(15, 15)
- appIconElement.cornerRadius = 4
- titleStack.addSpacer(4)
- let titleElement = titleStack.addText(title)
- titleElement.textColor = Color.white()
- titleElement.textOpacity = 0.7
- titleElement.font = Font.mediumSystemFont(13)
- widget.addSpacer(12)
- // Show API
- let nameElement = widget.addText(api.name)
- nameElement.textColor = Color.white()
- nameElement.font = Font.boldSystemFont(18)
- widget.addSpacer(2)
- let descriptionElement = widget.addText(api.description)
- descriptionElement.minimumScaleFactor = 0.5
- descriptionElement.textColor = Color.white()
- descriptionElement.font = Font.systemFont(18)
- // UI presented in Siri ans Shortcuta is non-interactive, so we only show the footer when not running the script from Siri.
- if (!config.runsWithSiri) {
- widget.addSpacer(8)
- // Add button to open documentation
- let linkSymbol = SFSymbol.named("arrow.up.forward")
- let footerStack = widget.addStack()
- let linkStack = footerStack.addStack()
- linkStack.centerAlignContent()
- linkStack.url = api.url
- let linkElement = linkStack.addText("Read more")
- linkElement.font = Font.mediumSystemFont(13)
- linkElement.textColor = Color.blue()
- linkStack.addSpacer(3)
- let linkSymbolElement = linkStack.addImage(linkSymbol.image)
- linkSymbolElement.imageSize = new Size(11, 11)
- linkSymbolElement.tintColor = Color.blue()
- footerStack.addSpacer()
- // Add link to documentation
- let docsSymbol = SFSymbol.named("book")
- let docsElement = footerStack.addImage(docsSymbol.image)
- docsElement.imageSize = new Size(20, 20)
- docsElement.tintColor = Color.white()
- docsElement.imageOpacity = 0.5
- docsElement.url = "https://docs.scriptable.app"
- }
- return widget
-}
-
-async function randomAPI() {
- let docs = await loadDocs()
- let apiNames = Object.keys(docs)
- let num = Math.round(Math.random() * apiNames.length)
- let apiName = apiNames[num]
- let api = docs[apiName]
- return {
- name: apiName,
- description: api["!doc"],
- url: api["!url"]
- }
-}
-
-async function loadDocs() {
- let url = "https://docs.scriptable.app/scriptable.json"
- let req = new Request(url)
- return await req.loadJSON()
-}
-
-async function loadAppIcon() {
- let url = "https://is5-ssl.mzstatic.com/image/thumb/Purple124/v4/21/1e/13/211e13de-2e74-4221-f7db-d6d2c53b4323/AppIcon-1x_U007emarketing-0-7-0-85-220.png/540x540sr.jpg"
- let req = new Request(url)
- return req.loadImage()
-}
diff --git a/Tr b/Tr
deleted file mode 100644
index 880788b..0000000
--- a/Tr
+++ /dev/null
@@ -1,299 +0,0 @@
-import Constants from './lib/constants';
-import Domain from './domain';
-import Filter from './lib/filter';
-import Page from './page';
-import WebAudio from './webAudio';
-import WebConfig from './webConfig';
-import Wordlist from './lib/wordlist';
-import './vendor/findAndReplaceDOMText';
-
-// NO-OP for chrome.* API
-const chrome = {} as any;
-chrome.runtime = {};
-chrome.runtime.sendMessage = (obj) => {};
-
-/* @preserve - Start User Config */
-const config = WebConfig._defaults as any;
-config.words = WebConfig._defaultWords;
-/* @preserve - End User Config */
-
-export default class BookmarkletFilter extends Filter {
- audio: WebAudio;
- audioOnly: boolean;
- audioWordlistId: number;
- cfg: WebConfig;
- domain: Domain;
- extension: boolean;
- hostname: string;
- iframe: Location;
- location: Location | URL;
- mutePage: boolean;
- observer: MutationObserver;
- processMutationTarget: boolean;
- processNode: (node: HTMLElement | Document | ShadowRoot, wordlistId: number, stats?: boolean) => void;
- shadowObserver: MutationObserver;
- Mute tab: mute just one profanity word (Webfilter: Audio Bleep)
- _____ edit English subtitles with this _____
-
- constructor() {
- super();
- this.extension = false;
- this.audioWordlistId = 0;
- this.mutePage = false;
- this.processMutationTarget = false;
- }
-
- advancedReplaceText(node, wordlistId: number, stats = true) {
- if (node.parentNode || node === document) {
- this.wordlists[wordlistId].regExps.forEach((regExp) => {
- // @ts-ignore: External library function
- findAndReplaceDOMText(node, { preset: 'prose', find: regExp, replace: (portion, match) => {
- if (portion.index === 0) {
- return this.replaceText(match[0], wordlistId, stats);
- } else {
- return '';
- }
- } });
- });
- } else {
- this.cleanText(node, wordlistId, stats);
- }
- }
-
- checkMutationForProfanity(mutation) {
- mutation.addedNodes.forEach((node) => {
- if (!Page.isForbiddenNode(node)) {
- if (this.mutePage) {
- this.cleanAudio(node);
- } else if (!this.audioOnly) {
- this.processNode(node, this.wordlistId);
- }
- }
- });
-
- if (this.mutePage && this.audio.muted) {
- mutation.removedNodes.forEach((node) => {
- const supported = this.audio.supportedNode(node);
- const rule = supported !== false ? this.audio.rules[supported] : this.audio.rules[0];
- if (
- supported !== false
- || node == this.audio.lastFilteredNode
- || node.contains(this.audio.lastFilteredNode)
- || (
- rule.simpleUnmute
- && this.audio.lastFilteredText
- && this.audio.lastFilteredText.includes(node.textContent)
- )
- ) {
- this.audio.unmute(rule);
- }
- });
- }
-
- if (mutation.target) {
- if (mutation.target.nodeName === '#text') {
- this.checkMutationTargetTextForProfanity(mutation);
- } else if (this.processMutationTarget) {
- this.processNode(mutation.target, this.wordlistId);
- }
- }
- }
-
- checkMutationTargetTextForProfanity(mutation) {
- if (!Page.isForbiddenNode(mutation.target)) {
- if (this.mutePage) {
- const supported = this.audio.supportedNode(mutation.target);
- const rule = supported !== false ? this.audio.rules[supported] : this.audio.rules[0];
- if (supported !== false && rule.simpleUnmute) {
- // Supported node. Check if a previously filtered node is being removed
- if (
- this.audio.muted
- && mutation.oldValue
- && this.audio.lastFilteredText
- && this.audio.lastFilteredText.includes(mutation.oldValue)
- ) {
- this.audio.unmute(rule);
- }
- this.audio.clean(mutation.target, supported);
- } else if (rule.simpleUnmute && this.audio.muted && !mutation.target.parentElement) {
- // Check for *** a filtered subtitle (no parent)
- if (this.audio.lastFilteredText && this.audio.lastFilteredText.includes(mutation.target.textContent)) {
- this.audio.unmute(rule);
- }
- } else if (!this.audioOnly) { // Filter regular text
- const result = this.replaceTextResult(mutation.target.data, this.wordlistId);
- if (result.modified) { mutation.target.data = result.filtered; }
- }
- } else if (!this.audioOnly) { // Filter regular text
- const result = this.replaceTextResult(mutation.target.data, this.wordlistId);
- if (result.modified) { mutation.target.data = result.filtered; }
- }
- }
- }
-
- cleanAudio(node) {
- if (this.audio.youTube && this.audio.youTubeAutoSubsPresent()) {
- if (this.audio.youTubeAutoSubsSupportedNode(node)) {
- if (this.audio.youTubeAutoSubsCurrentRow(node)) {
- this.audio.cleanYouTubeAutoSubs(node);
- } else if (!this.audioOnly) {
- this.processNode(node, this.wordlistId);
- }
- } else if (!this.audioOnly && !this.audio.youTubeAutoSubsNodeIsSubtitleText(node)) {
- this.processNode(node, this.wordlistId);
- }
- } else {
- const supported = this.audio.supportedNode(node);
- if (supported !== false) {
- this.audio.clean(node, supported);
- } else if (!this.audioOnly) {
- this.processNode(node, this.wordlistId);
- }
- }
- }
-
- cleanChildNode(node, wordlistId: number, stats: boolean = true) {
- if (node.nodeName) {
- if (node.textContent && node.textContent.trim() != '') {
- const result = this.replaceTextResult(node.textContent, wordlistId, stats);
- if (result.modified) {
- node.textContent = result.filtered;
- }
- } else if (node.nodeName == 'IMG') {
- if (node.alt != '') { node.alt = this.replaceText(node.alt, wordlistId, stats); }
- if (node.title != '') { node.title = this.replaceText(node.title, wordlistId, stats); }
- } else if (node.shadowRoot) {
- this.filterShadowRoot(node.shadowRoot, wordlistId, stats);
- }
- }
- }
-
- cleanNode(node, wordlistId: number, stats: boolean = true) {
- if (Page.isForbiddenNode(node)) { return false; }
- if (node.shadowRoot) { this.filterShadowRoot(node.shadowRoot, wordlistId, stats); }
- if (node.childNodes.length > 0) {
- for (let i = 0; i < node.childNodes.length ; i++) {
- this.cleanNode(node.childNodes[i], wordlistId, stats);
- }
- } else {
- this.cleanChildNode(node, this.wordlistId, stats);
- }
- }
-
- cleanPage() {
- this.cfg = new WebConfig(config);
- this.domain = Domain.byHostname(this.hostname, this.cfg.domains);
- this.cfg.muteMethod = Constants.MuteMethods.Video; // Bookmarklet: Force video volume bleeped/muted method
-
- // Use domain-specific settings
- const message: Message = { disabled: (this.cfg.enabledDomainsOnly && !this.domain.enabled) || this.domain.disabled };
- if (message.disabled) {
- chrome.runtime.sendMessage(message);
- return false;
- }
- if (this.domain.wordlistId !== undefined) { this.wordlistId = this.domain.wordlistId; }
- if (this.domain.audioWordlistId !== undefined) { this.audioWordlistId = this.domain.audioWordlistId; }
-
- // Detect if we should mute/bleeped audio for the current page
- if (this.cfg.muteAudio) {
- this.audio = new WebAudio(this);
- this.mutePage = this.audio.supportedPage;
- if (this.mutePage) {
- if (this.cfg.wordlistsEnabled && this.wordlistId != this.audio.wordlistId) {
- this.wordlists[this.audio.wordlistId] = new Wordlist(this.cfg, this.audio.wordlistId);
- }
- }
- }
-
- // Remove profanity from the main document and watch for new nodes
- this.init();
- if (!this.audioOnly) { this.processNode(document, this.wordlistId); }
- this.startObserving(document);
- }
-
- cleanText(node, wordlistId: number, stats: boolean = true) {
- if (Page.isForbiddenNode(node)) { return false; }
- if (node.shadowRoot) { this.filterShadowRoot(node.shadowRoot, wordlistId, stats); }
- if (node.childElementCount > 0) {
- const treeWalker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT);
- while(treeWalker.nextNode()) {
- if (treeWalker.currentNode.childNodes.length > 0) {
- treeWalker.currentNode.childNodes.forEach((childNode) => {
- this.cleanText(childNode, wordlistId, stats);
- });
- } else {
- if (!Page.isForbiddenNode(treeWalker.currentNode)) {
- this.cleanChildNode(treeWalker.currentNode, wordlistId, stats);
- }
- }
- }
- } else {
- this.cleanChildNode(node, wordlistId, stats);
- }
- }
-
- filterShadowRoot(shadowRoot: ShadowRoot, wordlistId: number, stats: boolean = true) {
- this.shadowObserver.observe(shadowRoot, ObserverConfig);
- this.processNode(shadowRoot, wordlistId, stats);
- }
-
- init(wordlistId: number | false = false) {
- super.init(wordlistId);
-
- if (this.domain.advanced) {
- this.processNode = this.advancedReplaceText;
- } else if (this.domain.deep) {
- this.processMutationTarget = true;
- this.processNode = this.cleanNode;
- } else {
- this.processNode = this.cleanText;
- }
- }
-
- processMutations(mutations) {
- mutations.forEach((mutation) => {
- filter.checkMutationForProfanity(mutation);
- });
- }
-
- startObserving(target: Node = document, observer: MutationObserver = this.observer) {
- observer.observe(target, ObserverConfig);
- }
-
- stopObserving(observer: MutationObserver = this.observer) {
- const mutations = observer.takeRecords();
- observer.disconnect();
- if (mutations) { this.processMutations(mutations); }
- }
-
- updateCounterBadge() {} // NO-OP
-}
-
-const filter = new BookmarkletFilter;
-const ObserverConfig: MutationObserverInit = {
- characterData: true,
- characterDataOldValue: true,
- childList: true,
- subtree: true,
-};
-
-if (typeof window !== 'undefined') {
- filter.observer = new MutationObserver(filter.processMutations);
- filter.shadowObserver = new MutationObserver(filter.processMutations);
-
- if (window != window.top) {
- filter.iframe = document.location;
- try {
- filter.hostname = window.parent.location.hostname;
- } catch(e) {
- if (document.referrer) {
- filter.hostname = new URL(document.referrer).hostname;
- } else {
- filter.hostname = document.location.hostname;
- }
- }
- } else {
- filter.hostname = document.location.hostname;
- }
-
- filter.cleanPager();
diff --git a/Travis Libby b/Travis Libby
deleted file mode 100644
index 61eef3e..0000000
--- a/Travis Libby
+++ /dev/null
@@ -1,7 +0,0 @@
-import Constants from './lib/constants';
-import WebFilter from './webFilter';
-import BookmarkletFilter from './bookmarkletFilter';
-import WebAudioSites from './webAudioSites';
-import { getGlobalVariable, hmsToSeconds, makeRequest, secondsToHMS } from './lib/helper';
-import Logger from './lib/logger';
-const logger = new Logger();
diff --git a/TravisLibby1 b/TravisLibby1
deleted file mode 100644
index 3bfbd2f..0000000
--- a/TravisLibby1
+++ /dev/null
@@ -1,12 +0,0 @@
-text eol=lf
-
-*.jpg binary
-*.mp3 binary
-*.png binary
-
-# https://github.com/github/linguist#overrides
-/src/static/w3.css linguist-vendored
-/src/static/w3-color-flat.css linguist-vendored
-/store/* linguist-vendored
-/test/* linguist-documentation
-MP3 binary audio censor bleep
diff --git a/blank.yml b/blank.yml
deleted file mode 100644
index c7c0969..0000000
--- a/blank.yml
+++ /dev/null
@@ -1 +0,0 @@
-https://github.com/travislibby0000/AdvancedProfanityFilter/blob/master/src/audio/Censored_Beep-Mastercard-569981218.mp3
diff --git a/blank.yml5 b/blank.yml5
deleted file mode 100644
index 3d0cdfa..0000000
--- a/blank.yml5
+++ /dev/null
@@ -1 +0,0 @@
-String replacedStr = jsonStr.replaceAll("\\[", "").replaceAll("\\]", "")
diff --git a/blank.ymld b/blank.ymld
deleted file mode 100644
index 7ce7ae7..0000000
--- a/blank.ymld
+++ /dev/null
@@ -1,195 +0,0 @@
-{
- "name": "Profanity Filtering Muted",
- "version": "2.18.0",
- "description": "A browser extension to filter profanity from webpages.",
- "main": "filter.js",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/richardfrost/AdvancedProfanityFilter.git"
- },
- "keywords": [
- "Profanity",
- "Filter"
- ],
- "author": "Travis Libby",
- "license": "SEE LICENSE IN LICENSE",
- "bugs": {
- "url": "https://github.com/TravisLibby/Profanity Filtering Muted /issues"
- },
- "homepage": "https://github.com/TravisLibby/ProfanityFilteringMuted#readme",
- "scripts": {
- "build:libs": "tsc -p ./src/script/lib/tsconfig.json",
- "build:static": "node bin/copy-static.js",
- "build:test-sm": "babel src/script --out-dir built --extensions \".ts,.tsx\" --source-maps inline",
- "build:test": "babel src/script --out-dir ./test/built --extensions \".ts,.tsx,.js\"",
- "build": "npm run build:static && npm run package:webpack",
- "clean": "node bin/clean.js",
- "package:bookmarklet": "webpack --config bin/bookmarklet.webpack.config.js",
- "package:extension": "node bin/package-extension.js",
- "package:webpack": "webpack --config bin/webpack.config.js",
- "package": "npm run build && npm run package:bookmarklet && npm run package:extension",
- "test:addon": "npx addons-linter ./extension-firefox.zip",
- "test:all": "npm run test && npm run test:lint:tests && npm run test:addon",
- "test:cov": "npm run build:test && nyc --reporter=lcov --reporter=text node_modules/mocha/bin/_mocha",
- "test:debug": "node --inspect-brk node_modules/mocha/bin/_mocha --reporter tap",
- "test:lint": "eslint \"src/**/*.ts\"",
- "test:lint:tests": "eslint \"test/**/*.spec.js\"",
- "test:nocov": "node_modules/mocha/bin/_mocha",
- "test:types": "tsc --noEmit",
- "test": "npm run test:lint && npm run test:types && npm run test:cov",
- "type-check:watch": "npm run type-check -- --watch",
- "update:help": "node bin/update-help.js",
- "watch": "node bin/watch.js"
- },
- "devDependencies": {
- "@babel/cli": "^7.12.10",
- "@babel/core": "^7.12.10",
- "@babel/plugin-proposal-class-properties": "^7.12.1",
- "@babel/plugin-proposal-object-rest-spread": "^7.12.1",
- "@babel/polyfill": "^7.12.1",
- "@babel/preset-env": "^7.12.11",
- "@babel/preset-typescript": "^7.12.7",
- "@babel/register": "^7.12.10",
- "@types/chrome": "^0.0.128",
- "@typescript-eslint/eslint-plugin": "^4.14.0",
- "@typescript-eslint/parser": "^4.14.0",
- "addons-linter": "^1.26.0",
- "adm-zip": "git+https://github.com/cthackers/adm-zip.git",
- "babel-loader": "^8.2.2",
- "chai": "^4.2.0",
- "chokidar": "^3.5.1",
- "download": "^7.1.0",
- "eslint": "^7.18.0",
- "fs-extra": "^8.1.0",
- "marked": "^0.7.0",
- "mocha": "^7.2.0",
- "nyc": "^14.1.1",
- "typescript": ">=4.1.3",
- "webpack": "^5.20.2",
- "webpack-cli": "^3.3.12"
- },
- "babel": {
- "presets": [
- "@babel/typescript",
- [
- "@babel/preset-env",
- {
- "modules": "commonjs",
- "targets": {
- "node": "current"
- }
- }
- ]
- ],
- "plugins": [
- "@babel/proposal-class-properties",
- "@babel/proposal-object-rest-spread"
- ]
- },
- "eslintConfig": {
- "extends": [
- "eslint:recommended",
- "plugin:@typescript-eslint/recommended"
- ],
- "parser": "@typescript-eslint/parser",
- "parserOptions": {
- "ecmaVersion": 6,
- "sourceType": "module",
- "ecmaFeatures": {}
- },
- "plugins": [
- "@typescript-eslint"
- ],
- "rules": {
- "array-bracket-spacing": [
- "warn",
- "never"
- ],
- "arrow-parens": [
- "warn",
- "always"
- ],
- "comma-spacing": "warn",
- "indent": [
- "warn",
- 2,
- {
- "SwitchCase": 1
- }
- ],
- "no-console": "warn",
- "no-control-regex": [
- "off"
- ],
- "no-prototype-builtins": "off",
- "no-shadow": "warn",
- "no-undef": [
- "off"
- ],
- "no-unused-vars": [
- "off"
- ],
- "no-useless-escape": [
- "off"
- ],
- "object-curly-spacing": [
- "warn",
- "always"
- ],
- "prefer-const": [
- "error",
- {
- "destructuring": "all"
- }
- ],
- "quotes": [
- "error",
- "single",
- "avoid-escape"
- ],
- "semi": [
- "error",
- "always"
- ],
- "@typescript-eslint/ban-ts-comment": [
- "warn",
- {
- "ts-ignore": "allow-with-description"
- }
- ],
- "@typescript-eslint/explicit-function-return-type": "off",
- "@typescript-eslint/explicit-member-accessibility": "off",
- "@typescript-eslint/explicit-module-boundary-types": "off",
- "@typescript-eslint/naming-convention": "off",
- "@typescript-eslint/no-empty-function": "off",
- "@typescript-eslint/no-explicit-any": "off",
- "@typescript-eslint/no-inferrable-types": "off",
- "@typescript-eslint/no-unused-vars": [
- "error",
- {
- "vars": "all",
- "args": "none"
- }
- ],
- "@typescript-eslint/no-use-before-define": "off",
- "@typescript-eslint/type-annotation-spacing": "error"
- }
- },
- "mocha": {
- "reporter": "dot",
- "require": [
- "@babel/register"
- ],
- "spec": [
- "test/**/*.spec.js"
- ]
- },
- "nyc": {
- "cwd": "test/",
- "exclude": [
- "**/*.spec.js",
- "built/vendor/**/*"
- ]
- }
-}
-© 2021 GitHub, Inc.
diff --git a/button.css b/button.css
deleted file mode 100644
index 66b2a79..0000000
--- a/button.css
+++ /dev/null
@@ -1,13 +0,0 @@
-button {
- height: 30px;
- width: 30px;
- outline: none;
- margin: 10px;
- border: none;
- border-radius: 2px;
-}
-
-button.current {
- box-shadow: 0 0 0 2px white,
- 0 0 0 4px black;
-}
\ No newline at end of file
diff --git a/censor-beep-sound-effect.html b/censor-beep-sound-effect.html
deleted file mode 100644
index cef5aa2..0000000
--- a/censor-beep-sound-effect.html
+++ /dev/null
@@ -1,502 +0,0 @@
-
-
-
-
-
-
-
-
-Censor Beep Sound Effects - Wav Mp3 Download
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Censor Beep Sounds
-
-
-
-
-
-
-
-
-
-You are allowed to use the sounds on our website free of charge and royalty free in your projects but you are NOT allowed to post the sounds on any web site for others to download, link directly to individual audio files, or sell the sounds to anyone else. Remember to read
Terms of Use before downloading and using the sound effects or music tracks.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (0.25s)
- Keywords: bleep out, bleeping, censored, censorship
-
-
-
-
-
- 0.25s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (0.50s)
- Keywords: television, tv, radio, video, swear, word, swearing, curse, cursing, censored, censoring, profanity
-
-
-
-
-
- 0.50s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (0.75s)
- Keywords:
-
-
-
-
-
- 0.75s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (1.00s)
- Keywords:
-
-
-
-
-
- 1.00s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (1.25s)
- Keywords:
-
-
-
-
-
- 1.25s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (1.50s)
- Keywords:
-
-
-
-
-
- 1.50s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (2.00s)
- Keywords:
-
-
-
-
-
- 2.00s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (3.00s)
- Keywords:
-
-
-
-
-
- 3.00s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (5.00s)
- Keywords:
-
-
-
-
-
- 5.00s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
- Bleep censor sound (10.00s)
- Keywords:
-
-
-
-
-
- 10.00s
- 44.1 kHz
- 16 bit
- Mono
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/chrome.txt b/chrome.txt
deleted file mode 100644
index 6ff0b8b..0000000
--- a/chrome.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-• Filter modes
- • Censor - Hide offending words
- • Substitute - Replace offensive words
- • Remove - Remove offensive words
-• Customizable word and substitution lists
-• Works everywhere, including popular pages such as:
- • Facebook
- • Pinterest
- • Reddit
- • Twitter
-• Audio muting for videos on supported sites:
- • Amazon Video
- • Hulu
- • Netflix
- • Plex
- • Vudu
- • YouTube
- • And more! You can even add your own! (advanced)
-
-For a detailed overview of the features and settings, please see the Getting Started page here:
-
-https://github.com/richardfrost/AdvancedProfanityFilter/wiki
\ No newline at end of file
diff --git a/content.js b/content.js
deleted file mode 100644
index f33da13..0000000
--- a/content.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// content.js
-var firstHref = $("a[href^='http']").eq(0).attr("href");
-
-console.log(firstHref);
diff --git a/content.js: b/content.js:
deleted file mode 100644
index 0223d05..0000000
--- a/content.js:
+++ /dev/null
@@ -1,2 +0,0 @@
-// content.js
-alert("Hello from your Chrome extension!")
diff --git a/extensions.json b/extensions.json
deleted file mode 100644
index 1871335..0000000
--- a/extensions.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "recommendations": [
- "coenraads.bracket-pair-colorizer-2",
- "kamikillerto.vscode-colorize",
- "dbaeumer.vscode-eslint",
- "shardulm94.trailing-spaces"
- ]
-}
\ No newline at end of file
diff --git a/filename1 b/filename1
deleted file mode 100644
index e9575a5..0000000
--- a/filename1
+++ /dev/null
@@ -1 +0,0 @@
-https://www.soundjay.com/censor-beep-sound-effect.html#google_vignette
diff --git a/filename4 b/filename4
deleted file mode 100644
index 7472425..0000000
--- a/filename4
+++ /dev/null
@@ -1,2 +0,0 @@
-boolean
-Whether the tab is muted (prevented from playing sound). The tab may be muted even if it has not played or is not currently playing sound. Equivalent to whether the 'muted' audio indicator is showing.
diff --git a/filenameq b/filenameq
deleted file mode 100644
index 7839944..0000000
--- a/filenameq
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "name": "My extension", ProfanityFiltered
- ...
- "permissions": [yes
- "tabs"
- ],
- ...
-}
diff --git a/iframe b/iframe
deleted file mode 100644
index 755b073..0000000
--- a/iframe
+++ /dev/null
@@ -1,8 +0,0 @@
-chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
- console.log(response.farewell);
-});
-chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
- chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
- console.log(response.farewell);
- });
-
diff --git a/manifest.json b/manifest.json
deleted file mode 100644
index 9466e79..0000000
--- a/manifest.json
+++ /dev/null
@@ -1,9 +0,0 @@
-manifest.json
-"content_scripts": [
- {
- "matches": [
- ""
- ],
- "js": ["content.js"]
- }
-]
diff --git a/manifest.json, b/manifest.json,
deleted file mode 100644
index 550afa7..0000000
--- a/manifest.json,
+++ /dev/null
@@ -1,7 +0,0 @@
-{ required
-"manifest version": 3,
-"name": "ProfanityFiltering2",
-"version", "versionString",
-
-
-
diff --git a/manifest.json00 b/manifest.json00
deleted file mode 100644
index d80c40d..0000000
--- a/manifest.json00
+++ /dev/null
@@ -1,4 +0,0 @@
- JSONObject resJb = JSONObject.fromObject(param);
- if (! resJb.containsKey ( "tcontent")) {// field format does not exist
- return productResult("400", errorDatas);
- }
diff --git a/manifest.json1 b/manifest.json1
deleted file mode 100644
index cfbe473..0000000
--- a/manifest.json1
+++ /dev/null
@@ -1,23 +0,0 @@
-manifest.json
-"background": {
- "scripts": ["background.js"]
-}// background.js
-
-// Called when the user clicks on the browser action.
-chrome.browserAction.onClicked.addListener(function(tab) {
- // Send a message to the active tab
- chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
- var activeTab = tabs[0];
- chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
- });
-});
-// content.js
-chrome.runtime.onMessage.addListener(
- function(request, sender, sendResponse) {
- if( request.message === "clicked_browser_action" ) {
- var firstHref = $("a[href^='http']").eq(0).attr("href");
-
- console.log(firstHref);
- }
- }
-);
diff --git a/manifest.json5 b/manifest.json5
deleted file mode 100644
index 0aff166..0000000
--- a/manifest.json5
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "manifest_version": 2,
- "name": "extension",
- "version": "1.0",
- "description": "My first Chrome extension.",
- "browser_action": {
- "default_icon": "icon.jpg",
- "popup": "popup.html"
- }
-}
diff --git a/manifest.json9 b/manifest.json9
deleted file mode 100644
index 4c272b6..0000000
--- a/manifest.json9
+++ /dev/null
@@ -1,49 +0,0 @@
-[
- {
- 'repeat(5, 10)': {
- _id: '{{objectId()}}',
- index: '{{index()}}',
- guid: '{{guid()}}',
- isActive: '{{bool()}}',
- balance: '{{floating(1000, 4000, 2, "$0,0.00")}}',
- picture: 'http://placehold.it/32x32',
- age: '{{integer(20, 40)}}',
- eyeColor: '{{random("blue", "brown", "green")}}',
- name: {
- first: '{{firstName()}}',
- last: '{{surname()}}'
- },
- company: '{{company().toUpperCase()}}',
- email(tags) {
- return `${this.name.first}.${this.name.last}@${this.company}${tags.domainZone()}`.toLowerCase();
- },
- phone: '+1 {{phone()}}',
- address: '{{integer(100, 999)}} {{street()}}, {{city()}}, {{state()}}, {{integer(100, 10000)}}',
- about: '{{lorem(1, "paragraphs")}}',
- registered: '{{moment(this.date(new Date(2014, 0, 1), new Date())).format("LLLL")}}',
- latitude: '{{floating(-90.000001, 90)}}',
- longitude: '{{floating(-180.000001, 180)}}',
- tags: [
- {
- 'repeat(5)': '{{lorem(1, "words")}}'
- }
- ],
- range: range(10),
- friends: [
- {
- 'repeat(3)': {
- id: '{{index()}}',
- name: '{{firstName()}} {{surname()}}'
- }
- }
- ],
- greeting(tags) {
- return `Hello, ${this.name.first}! You have ${tags.integer(5, 10)} unread messages.`;
- },
- favoriteFruit(tags) {
- const fruits = ['apple', 'banana', 'strawberry'];
- return fruits[tags.integer(0, fruits.length - 1)];
- }
- }
- }
-]
diff --git a/manifest.json9999 b/manifest.json9999
deleted file mode 100644
index c9b9457..0000000
--- a/manifest.json9999
+++ /dev/null
@@ -1 +0,0 @@
-a "{", "}".
diff --git a/manifest.json:1:1 b/manifest.json:1:1
deleted file mode 100644
index ed2e9d6..0000000
--- a/manifest.json:1:1
+++ /dev/null
@@ -1 +0,0 @@
-manifest.json:1:1
diff --git a/manifest.json:1:1: b/manifest.json:1:1:
deleted file mode 100644
index 59fe69b..0000000
--- a/manifest.json:1:1:
+++ /dev/null
@@ -1 +0,0 @@
-manifest.json:1:1:
diff --git a/script b/script
deleted file mode 100644
index 76fd620..0000000
--- a/script
+++ /dev/null
@@ -1,14 +0,0 @@
-
-{
- "manifest_version": 2,
- "name": "My Cool Extension",
- "version": "0.1",
- "content_scripts": [
- {
- "matches": [
- ""
- ],
- "js": ["jquery-2.1.3.min.js", "content.js"]
- }
- ]
-}
diff --git a/streamCleanWorker.ts b/streamCleanWorker.ts
deleted file mode 100644
index 4519d70..0000000
--- a/streamCleanWorker.ts
+++ /dev/null
@@ -1,374 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var filter_1 = require("./filter");
-var profanityfiltering_1 = require("./profanityfiltering");
-var Profanityfilteringworker = /** @class */ (function () {
- function profanityfilteringworker(dirtyWords, hideCaptions, hideCaptionsWhenFiltered, showCaptionsWhenFiltered, pollInterval, muteDelay) {
- var _this = this;
- this.isMuted = false;
- this.mutedCounter = 0;
- this.dirtyWords = StreamCleanWorker.NormalizeDirtyWords(dirtyWords || filter_1.Filter.DefaultFilterWords);
-
-
- this.pollInterval = pollInterval;
- this.showCaptionsWhenFiltered = showCaptionsWhenFiltered;
- this.filter = new filter_1.Filter(this.dirtyWords);
- this.selectors = {
- Amazon: { selector: ".f1iwgj00" },
- AmazonCA: { selector: ".persistentPanel" },
- AmazonCoUk: { selector: ".persistentPanel" },
- AmazonPrimeVideo: { selector: ".fg8afi5" },
- Hbo: { selector: ",fg8afi5" },
- FrndlyTV: { selector: ".jw-captions" },
- Hulu: { selector: ".CaptionBox" },
- ID: { selector: ".vjs-text-track-display" },
-
-
-
- ID: { selector: ".vjs-text-track-display" },
- IMDB: { selector: ".captions" },
- NBC: { selector: "anv-caption-608-frame-line-char" },
- NetFlix: { selector: ".player-timedtext" },
- NineNow: { selector: ".vjs-text-track-display" },
- OWN: { selector: "anv-caption-608-frame-line-char" },
- ParamountPlus: { selector: ".skin-tt-container-tt-div" },
- Peacock: { selector: ".video-player__subtitles" },
- Plex: { selector: ".libjass-subs" },
- ReelzNow: { selector: ".vjs-text-track-display" },
- Roku: { selector: ".vjs-text-track-display" },
- Showmax: { selector: ".contentWrapper" },
- Sling: { selector: ".bmpui-ui-subtitle-label" },
- Stan: { selector: ".clpp-subtitles" },
- TLC: { selector: ".vjs-text-track-display" },
- TubiTV: { selector: "#captionsComponent" },
- Viki: { selector: ".vjs-text-track-display" },
- Vudu: { selector: ".subtitles", IframeId: "contentPlayerFrame" },
- YouTube: { selector: ".captions-text" }
- };
- this.hideSelectorElement = document.createElement("style");
- this.hideSelectorString = "";
- this.hideSelectors = [];
- for (var prop in this.selectors) {
- if (!this.selectors.hasOwnProperty(prop)) {
- continue;
- }
- this.hideSelectors.push(this.selectors[prop].selector);
- }
- this.hideSelectors.push("video::cue");
- this.hideSelectorString = this.hideSelectors.join(",") + "{ display: none; opacity: 0 !important; }";
- var getCaptionSelector = function () {
- if (streamClean_1.StreamClean.IsAmazon)
- return _this.selectors.Amazon;
- if (streamClean_1.StreamClean.IsAmazonCA)
- return _this.selectors.AmazonCA;
- if (streamClean_1.StreamClean.IsAmazonCoUk)
- return _this.selectors.AmazonCoUk;
- if (streamClean_1.StreamClean.IsAmazonPrimeVideo)
- return _this.selectors.AmazonPrimeVideo;
- if (streamClean_1.StreamClean.IsAppleTv)
- return _this.selectors.AppleTv;
- if (streamClean_1.StreamClean.IsCharterSpectrum)
- return _this.selectors.CharterSpectrum;
- if (streamClean_1.StreamClean.IsCrackle)
- return _this.selectors.Crackle;
- if (streamClean_1.StreamClean.IsDiscoveryLife)
- return _this.selectors.DiscoveryLife;
- if (streamClean_1.StreamClean.IsDishAnywhere)
- return _this.selectors.DishAnywhere;
- if (streamClean_1.StreamClean.IsEpix)
- return _this.selectors.Epix;
- if (streamClean_1.StreamClean.IsFrndlyTV)
- return _this.selectors.FrndlyTV;
- if (streamClean_1.StreamClean.IsFuboTV)
- return _this.selectors.FuboTV;
- if (streamClean_1.StreamClean.IsHallmarkMoviesNow)
- return _this.selectors.HallmarkMoviesNow;
- if (streamClean_1.StreamClean.IsHulu)
- return _this.selectors.Hulu;
- if (streamClean_1.StreamClean.IsID)
- return _this.selectors.ID;
- if (streamClean_1.StreamClean.IsIMDB)
- return _this.selectors.IMDB;
- if (streamClean_1.StreamClean.IsNBC)
- return _this.selectors.NBC;
- if (streamClean_1.StreamClean.IsNetFlix)
- return _this.selectors.NetFlix;
- if (streamClean_1.StreamClean.IsNineNow)
- return _this.selectors.NineNow;
- if (streamClean_1.StreamClean.IsOWN)
- return _this.selectors.OWN;
- if (streamClean_1.StreamClean.IsParamountPlus)
- return _this.selectors.ParamountPlus;
- if (streamClean_1.StreamClean.IsPeacock)
- return _this.selectors.Peacock;
- if (streamClean_1.StreamClean.IsPlex)
- return _this.selectors.Plex;
- if (streamClean_1.StreamClean.IsReelzNow)
- return _this.selectors.ReelzNow;
- if (streamClean_1.StreamClean.IsRoku)
- return _this.selectors.Roku;
- if (streamClean_1.StreamClean.IsShowmax)
- return _this.selectors.Showmax;
- if (streamClean_1.StreamClean.IsSling)
- return _this.selectors.Sling;
- if (streamClean_1.StreamClean.IsStan)
- return _this.selectors.Stan;
- if (streamClean_1.StreamClean.IsTLC)
- return _this.selectors.TLC;
- if (streamClean_1.StreamClean.IsTubiTV)
- return _this.selectors.TubiTV;
- if (streamClean_1.StreamClean.IsViki)
- return _this.selectors.Viki;
- if (streamClean_1.StreamClean.IsVudu)
- return _this.selectors.Vudu;
- if (streamClean_1.StreamClean.IsYouTube)
- return _this.selectors.YouTube;
- return "";
- };
- this.captionsSelector = getCaptionSelector();
- this.muteTab = function () {
- // Hide captions when a filtered word is found
- if (_this.hideCaptionsWhenFiltered && !_this.showCaptionsWhenFiltered) {
- _this.hideSelectorElement.innerHTML = _this.hideSelectorString;
- }
- // Show captions when a filtered word is found
- if (_this.showCaptionsWhenFiltered) {
- _this.hideSelectorElement.innerHTML = "";
- }
- if (!_this.isMuted) {
- _this.mutedCounter++;
- StreamCleanWorker.Log(_this.mutedCounter.toString());
- chrome.runtime.sendMessage({ counter: _this.mutedCounter });
- }
- _this.isMuted = true;
- chrome.runtime.sendMessage({ muteUpdate: true, muted: true });
- };
- this.unMuteTab = function () {
- // Only hide captions when a filtered word is found
- if (_this.hideCaptionsWhenFiltered) {
- _this.hideSelectorElement.innerHTML = "";
- }
- // Always hide captions
- if (_this.hideCaptions) {
- _this.hideSelectorElement.innerHTML = _this.hideSelectorString;
- }
- _this.isMuted = false;
- var unMute = function () {
- if (!_this.isMuted) {
- chrome.runtime.sendMessage({ muteUpdate: true, muted: false });
- }
- };
- if (muteDelay > 0) {
- setTimeout(unMute, muteDelay);
- }
- else {
- unMute();
- }
- };
- }
- StreamCleanWorker.prototype.StartFiltering = function () {
- var _this = this;
- StreamCleanWorker.IsFiltering = true;
- StreamCleanWorker.Log("Stream Clean is Filtering...");
- if (streamClean_1.StreamClean.IsHboMax) {
- this.FilterHboMax();
- return;
- }
- var filterByCues = streamClean_1.StreamClean.IsAttTv ||
- streamClean_1.StreamClean.IsDisneyPlus ||
- streamClean_1.StreamClean.IsFreeForm ||
- streamClean_1.StreamClean.IsHallmark ||
- streamClean_1.StreamClean.IsPhilo ||
- streamClean_1.StreamClean.IsPlaystationVue ||
- streamClean_1.StreamClean.IsPlutoTv ||
- streamClean_1.StreamClean.IsScienceChannel ||
- streamClean_1.StreamClean.IsWeatherChannel;
- // Append the style node so it's ready to use if captions are being hidden
- document.body.appendChild(this.hideSelectorElement);
- if (this.hideCaptions) {
- this.hideSelectorElement.innerHTML = this.hideSelectorString;
- }
- var filterAction = streamClean_1.StreamClean.IsOWN || streamClean_1.StreamClean.IsNBC
- ? this.FilterAnvato
- : filterByCues
- ? this.FilterByCues
- : this.FilterByNode;
- this.filterInterval = setInterval(function () { return filterAction.call(_this); }, this.pollInterval);
- };
- StreamCleanWorker.prototype.StopFiltering = function () {
- clearInterval(this.filterInterval);
- };
- StreamCleanWorker.prototype.FilterHboMax = function () {
- var _this = this;
- StreamCleanWorker.Log("Filtering for HBO Max...");
- var filteredNodes = [];
- var isFiltering = false;
- var observer = new MutationObserver(function (mutations) {
- mutations.forEach(function (mutation) {
- Array.from(mutation.addedNodes).forEach(function (node) {
- if (node.tagName !== "SPAN") {
- return;
- }
- var cleanCaption = _this.filter.Clean(node.textContent || "");
- if (cleanCaption.indexOf(filter_1.Filter.Mask) > -1) {
- node.textContent = cleanCaption;
- filteredNodes.push(node);
- _this.muteTab();
- }
- });
- // Removing any previously filtered nodes
- Array.from(mutation.removedNodes).forEach(function (node) {
- var itemIndex = filteredNodes.indexOf(node);
- if (itemIndex > -1) {
- filteredNodes.splice(itemIndex, 1);
- }
- });
- // Check all filtered nodes and mute or unmute
- if (filteredNodes.map(function (i) { return i.textContent; }).some(function (c) { return c.indexOf(filter_1.Filter.Mask) > -1; })) {
- _this.muteTab();
- }
- else {
- _this.unMuteTab();
- }
- });
- });
- var tryToFilter = function () {
- if (isFiltering) {
- return;
- }
- //const elements = document.querySelectorAll(this.captionsSelector.selector);
- var elements = [document];
- if (!elements.length) {
- setTimeout(tryToFilter, 2000);
- return;
- }
- isFiltering = true;
- Array.from(elements).forEach(function (ele) {
- observer.observe(ele, { characterData: true, characterDataOldValue: true, childList: true, subtree: true });
- });
- };
- tryToFilter();
- };
- StreamCleanWorker.prototype.FilterByNode = function () {
- if (!this.captionsSelector) {
- StreamCleanWorker.Log("Missing caption selector...");
- return;
- }
- var iframe = this.captionsSelector.IframeId ? document.getElementById(this.captionsSelector.IframeId) : null;
- if (this.captionsSelector.IframeId && !iframe) {
- return;
- }
- var doc = this.captionsSelector.domSelector
- ? this.captionsSelector.domSelector()
- : this.captionsSelector.IframeId
- ? iframe.contentDocument
- : document;
- var ele = doc.querySelector(this.captionsSelector.selector);
- if (!ele) {
- this.unMuteTab();
- return;
- }
- var filterResults = [];
- var walker = document.createTreeWalker(ele, NodeFilter.SHOW_TEXT, null, false);
- while (walker.nextNode()) {
- var caption = walker.currentNode.nodeValue;
- var result = this.filter.Clean(caption);
- filterResults.push(result);
- walker.currentNode.nodeValue = result;
- }
- if (filterResults.some(function (result) { return result.indexOf(filter_1.Filter.Mask) > -1; })) {
- this.muteTab();
- }
- else {
- this.unMuteTab();
- }
- };
- StreamCleanWorker.prototype.FilterByCues = function () {
- var filterResults = [];
- var video = document.querySelector("video");
- var textTracks = video ? video.textTracks : null;
- if (!textTracks || !textTracks.length) {
- this.unMuteTab();
- return;
- }
- var tracks = textTracks.length > 1 && textTracks[1].kind === "captions"
- ? textTracks[1]
- : textTracks[0];
- var cues = tracks.activeCues;
- if (!cues || !cues.length) {
- this.unMuteTab();
- return;
- }
- for (var key in cues) {
- var text = cues[key].text;
- if (!text) {
- return;
- }
- var result = this.filter.Clean(text);
- filterResults.push(result);
- if (filterResults.some(function (result) { return result.indexOf(filter_1.Filter.Mask) > -1; })) {
- this.muteTab();
- text = result;
- cues[key].text = result;
- tracks.addCue(cues[key]);
- }
- else {
- this.unMuteTab();
- }
- }
- };
- StreamCleanWorker.prototype.FilterAnvato = function () {
- var iframe = document.getElementById("anvatoplayer0") || // OWN
- document.getElementById("nbctveappplayer"); // NBC
- if (!iframe) {
- return;
- }
- var doc = iframe.contentDocument;
- if (!document) {
- return;
- }
- // OWN breaks up the captions by characters, so they must be built up each time
- var elements = doc.getElementsByClassName(this.captionsSelector);
- var result = [];
- var i;
- for (i = 0; i < elements.length; i++) {
- result.push((elements[i].innerHTML || "").replace(" ", " "));
- if (this.hideCaptions) {
- elements[i].style.display = "none";
- }
- }
- var caption = result.join("").replace(/\s+/g, " ").trim();
- var filteredCaption = this.filter.Clean(caption);
- if ([filteredCaption].some(function (result) { return result.indexOf(filter_1.Filter.Mask) > -1; })) {
- this.muteTab();
- // For OWN, the captions will always be hidden
- for (i = 0; i < elements.length; i++) {
- elements[i].style.display = "none !important";
- }
- }
- else {
- this.unMuteTab();
- if (!this.hideCaptions) {
- for (i = 0; i < elements.length; i++) {
- elements[i].style.display = "inline !important";
- }
- }
- }
- };
- StreamCleanWorker.Log = function (message) {
- console.log("%c " + message, 'background: #222; color: #bada55');
- };
- StreamCleanWorker.NormalizeDirtyWords = function (dirtyWords) {
- // Sort the list descending by character length so phrases get filtered first
- dirtyWords.sort(function (a, b) { return b.length - a.length; });
- var results = [];
- for (var i = 0; i < dirtyWords.length; i++) {
- results.push(filter_1.Filter.NormalizeWord(dirtyWords[i]));
- }
- return results;
- };
- StreamCleanWorker.IsFiltering = false;
- StreamCleanWorker.LastFilterWordsSettings = "";
- return StreamCleanWorker;
-}());
-exports.StreamCleanWorker = StreamCleanWorker;
diff --git a/tr b/tr
deleted file mode 100644
index f3d80c6..0000000
--- a/tr
+++ /dev/null
@@ -1 +0,0 @@
- '{'.
diff --git a/type b/type
deleted file mode 100644
index ff3cb06..0000000
--- a/type
+++ /dev/null
@@ -1,3 +0,0 @@
-"browser_action": {
- "default_icon": "icon.png"
-}
diff --git a/webAudio.ts b/webAudio.ts
deleted file mode 100644
index b6c0680..0000000
--- a/webAudio.ts
+++ /dev/null
@@ -1,918 +0,0 @@
-import Constants from './lib/constants';
-import WebFilter from './webFilter';
-import BookmarkletFilter from './bookmarkletFilter';
-import WebAudioSites from './webAudioSites';
-import { getGlobalVariable, hmsToSeconds, makeRequest, secondsToHMS } from './lib/helper';
-import Logger from './lib/logger';
-const logger = new Logger();
-
-export default class WebAudio {
- cueRuleIds: number[];
- enabledRuleIds: number[];
- fetching: boolean;
- fillerAudio: HTMLAudioElement;
- filter: WebFilter | BookmarkletFilter;
- lastFilteredNode: HTMLElement | ChildNode;
- lastFilteredText: string;
- lastProcessedText: string;
- muted: boolean;
- rules: AudioRule[];
- sites: { [site: string]: AudioRule[] };
- supportedPage: boolean;
- unmuteTimeout: number;
- volume: number;
- watcherRuleIds: number[];
- wordlistId: number;
- youTube: boolean;
- youTubeAutoSubsMax: number;
- youTubeAutoSubsMin: number;
- youTubeAutoSubsTimeout: number;
- youTubeAutoSubsUnmuteDelay: number;
-
- static readonly brTagRegExp = new RegExp(' ', 'i');
- static readonly DefaultVideoSelector = 'video';
- static readonly FillerConfig = {
- beep: {
- fileName: 'audio/beep.mp3',
- volume: 0.2,
- },
- crickets: {
- fileName: 'audio/crickets.mp3',
- volume: 0.4,
- },
- static: {
- fileName: 'audio/static.mp3',
- volume: 0.3,
- },
- };
- static readonly TextTrackRuleMappings = {
- externalSubTrackLabel: 'label',
- videoCueKind: 'kind',
- videoCueLabel: 'label',
- videoCueLanguage: 'language',
- };
-
- constructor(filter: WebFilter | BookmarkletFilter) {
- this.filter = filter;
- this.cueRuleIds = [];
- this.enabledRuleIds = [];
- this.watcherRuleIds = [];
- if (this.filter.extension) { this.fillerAudio = this.initFillerAudio(this.filter.cfg.fillerAudio); }
- this.lastFilteredNode = null;
- this.lastFilteredText = '';
- this.lastProcessedText = '';
- this.muted = false;
- if (
- !filter.cfg.customAudioSites
- || typeof filter.cfg.customAudioSites !== 'object'
- ) {
- filter.cfg.customAudioSites = {};
- }
- this.sites = WebAudioSites.combineSites(filter.cfg.customAudioSites);
- this.volume = 1;
- this.wordlistId = filter.audioWordlistId;
- this.youTubeAutoSubsMax = filter.cfg.youTubeAutoSubsMax * 1000;
- this.youTubeAutoSubsMin = filter.cfg.youTubeAutoSubsMin;
- this.youTubeAutoSubsUnmuteDelay = 0;
-
- // Setup rules for current site
- this.rules = this.sites[filter.hostname];
- if (this.rules) {
- if (!Array.isArray(this.rules)) { this.rules = [this.rules]; }
- this.initRules();
- if (this.enabledRuleIds.length > 0) {
- this.supportedPage = true;
- if(['m.youtube.com', 'tv.youtube.com', 'www.youtube.com'].includes(filter.hostname)) {
- this.youTube = true;
- // Issue 251: YouTube is now filtering words out of auto-generated captions/subtitles
- const youTubeAutoCensor = '[ __ ]';
- const lists = this.wordlistId == 0 ? [] : [this.wordlistId];
- const youTubeAutoCensorOptions: WordOptions = { lists: lists, matchMethod: Constants.MatchMethods.Partial, repeat: false, separators: false, sub: '' };
- this.filter.cfg.addWord(youTubeAutoCensor, youTubeAutoCensorOptions);
- }
-
- if (this.watcherRuleIds.length > 0) {
- this.watcherRuleIds.forEach((ruleId) => {
- setInterval(this.watcher, this.rules[ruleId].checkInterval, this, ruleId);
- });
- }
-
- if (this.cueRuleIds.length > 0) { setInterval(this.watchForVideo, 250, this); }
- }
- }
- }
-
- clean(subtitleContainer, ruleIndex = 0): void {
- const rule = this.rules[ruleIndex];
- if (rule.mode === 'watcher') { return; } // If this is for a watcher rule, leave the text alone
- let filtered = false;
-
- if (subtitleContainer.nodeName && subtitleContainer.nodeName === '#text' && subtitleContainer.parentElement) {
- subtitleContainer = subtitleContainer.parentElement;
- }
- const subtitles = rule.subtitleSelector && subtitleContainer.querySelectorAll ? subtitleContainer.querySelectorAll(rule.subtitleSelector) : [subtitleContainer];
- if (subtitles.length === 0) { return; }
-
- // Process subtitles
- subtitles.forEach((subtitle) => {
- // innerText handles line feeds/spacing better, but is not available to #text nodes
- const textMethod = subtitle.nodeName === '#text' ? 'textContent' : 'innerText';
- if (
- rule.convertBreaks === true
- && subtitle.nodeName !== '#text'
- && !WebAudio.brTagRegExp.test(subtitle[textMethod])
- && WebAudio.brTagRegExp.test(subtitle.innerHTML)
- ) {
- if (subtitle.style.whiteSpace !== 'pre') { subtitle.style.whiteSpace = 'pre'; }
- subtitle.textContent = subtitle.innerHTML.replace(WebAudio.brTagRegExp, '\n');
- }
- const result = this.replaceTextResult(subtitle[textMethod]);
- if (result.modified) {
- filtered = true;
- this.mute(rule); // Mute the audio if we haven't already
-
- if (rule.filterSubtitles) {
- if (rule.preserveWhiteSpace && subtitle.style.whiteSpace !== 'pre') { subtitle.style.whiteSpace = 'pre'; }
- if (rule.ignoreMutations) { this.filter.stopObserving(); }
- subtitle[textMethod] = result.filtered;
- if (rule.ignoreMutations) { this.filter.startObserving(); }
- }
-
- this.lastFilteredNode = subtitle;
- this.lastFilteredText = subtitle[textMethod];
- }
- });
-
- switch (rule.showSubtitles) {
- case Constants.ShowSubtitles.Filtered: if (filtered) { this.showSubtitles(rule, subtitles); } else { this.hideSubtitles(rule, subtitles); } break;
- case Constants.ShowSubtitles.Unfiltered: if (filtered) { this.hideSubtitles(rule, subtitles); } else { this.showSubtitles(rule, subtitles); } break;
- case Constants.ShowSubtitles.None: this.hideSubtitles(rule, subtitles); break;
- }
- }
-
- cleanYouTubeAutoSubs(node): void {
- // Found a new word, clear the max timeout
- if (this.youTubeAutoSubsTimeout != null) {
- clearTimeout(this.youTubeAutoSubsTimeout);
- this.youTubeAutoSubsTimeout = null;
- }
-
- const result = this.replaceTextResult(node.textContent);
- if (result.modified) {
- node.textContent = result.filtered;
- this.mute();
- this.youTubeAutoSubsUnmuteDelay = null;
- this.filter.updateCounterBadge();
-
- // Set a timer to unmute if a max time was specified
- if (this.youTubeAutoSubsMax) {
- this.youTubeAutoSubsTimeout = window.setTimeout(this.youTubeAutoSubsMuteTimeout, this.youTubeAutoSubsMax, this);
- }
- } else {
- if (this.muted) {
- if (this.youTubeAutoSubsMin > 0) {
- const currentTime = document.getElementsByTagName(WebAudio.DefaultVideoSelector)[0].currentTime;
- if (this.youTubeAutoSubsUnmuteDelay == null) { // Start tracking youTubeAutoSubsUnmuteDelay when next unfiltered word is found
- this.youTubeAutoSubsUnmuteDelay = currentTime;
- } else {
- if (currentTime < this.youTubeAutoSubsUnmuteDelay) { this.youTubeAutoSubsUnmuteDelay = 0; } // Reset youTubeAutoSubsUnmuteDelay if video reversed
- if (currentTime > (this.youTubeAutoSubsUnmuteDelay + this.youTubeAutoSubsMin)) { // Unmute if its been long enough
- this.unmute();
- }
- }
- } else { // Unmute immediately if youTubeAutoSubsMin = 0
- this.unmute();
- }
- }
- }
-
- // Hide YouTube auto text unless show all subtitles is set
- if (this.filter.cfg.showSubtitles !== Constants.ShowSubtitles.All) {
- const container = document.querySelector('div.ytp-caption-window-rollup span.captions-text') as HTMLElement;
- if (container.style.display == 'block') {
- container.style.display = 'none';
- }
- }
- }
-
- clearUnmuteTimeout(rule: AudioRule) {
- if (rule.unmuteDelay && this.unmuteTimeout != null) {
- clearTimeout(this.unmuteTimeout);
- this.unmuteTimeout = null;
- }
- }
-
- delayedUnmute(instance: WebAudio, rule: AudioRule) {
- const delayed = true;
- instance.unmute(rule, null, delayed);
- this.unmuteTimeout = null;
- }
-
- // Priority (requires cues): [overrideKey], label, language, kind (prefer caption/subtitle), order
- getVideoTextTrack(textTracks, rule, overrideKey?: string): TextTrack {
- let bestIndex = 0;
- let bestScore = 0;
- let foundCues = false; // Return the first match with cues if no other matches are found
- let perfectScore = 0;
- if (overrideKey && rule[overrideKey]) { perfectScore += 1000; }
- if (rule.videoCueLabel) { perfectScore += 100; }
- if (rule.videoCueLanguage) { perfectScore += 10; }
- if (rule.videoCueKind) { perfectScore += 1; } // Add one, because we will default to 'captions'/'subtitles'
-
- for (let i = 0; i < textTracks.length; i++) {
- const textTrack = textTracks[i];
- if (textTrack.cues.length === 0) { continue; }
- if (rule.videoCueRequireShowing && textTrack.mode !== 'showing') { continue; }
-
- let currentScore = 0;
- if (overrideKey && rule[overrideKey] && this.textTrackKeyTest(textTrack, WebAudio.TextTrackRuleMappings[overrideKey], rule[overrideKey])) { currentScore += 1000; }
- if (rule.videoCueLabel && this.textTrackKeyTest(textTrack, WebAudio.TextTrackRuleMappings.videoCueLabel, rule.videoCueLabel)) { currentScore += 100; }
- if (rule.videoCueLanguage && this.textTrackKeyTest(textTrack, WebAudio.TextTrackRuleMappings.videoCueLanguage, rule.videoCueLanguage)) { currentScore += 10; }
- if (rule.videoCueKind) {
- if (this.textTrackKeyTest(textTrack, WebAudio.TextTrackRuleMappings.videoCueKind, rule.videoCueKind)) { currentScore += 1; }
- } else {
- if (
- this.textTrackKeyTest(textTrack, WebAudio.TextTrackRuleMappings.videoCueKind, 'captions')
- || this.textTrackKeyTest(textTrack, WebAudio.TextTrackRuleMappings.videoCueKind, 'subtitles')
- ) { currentScore += 1; }
- }
-
- if (currentScore === perfectScore) { return textTrack; }
- if (currentScore > bestScore || !foundCues) {
- bestScore = currentScore;
- bestIndex = i;
- foundCues = true;
- }
- }
-
- if (foundCues) { return textTracks[bestIndex]; }
- }
-
- // Some sites ignore textTrack.mode = 'hidden' and will still show captions
- // This is a fallback (not preferred) method that can be used for hiding the cues
- hideCue(rule: AudioRule, cue: FilteredVTTCue) {
- if (
- (rule.showSubtitles === Constants.ShowSubtitles.Filtered && !cue.filtered)
- || (rule.showSubtitles === Constants.ShowSubtitles.Unfiltered && cue.filtered)
- || rule.showSubtitles === Constants.ShowSubtitles.None
- ) {
- cue.text = '';
- cue.position = 100;
- cue.size = 0;
- }
- }
-
- hideSubtitles(rule: AudioRule, subtitles?) {
- if (rule.displaySelector) {
- const root = rule.rootNode && subtitles && subtitles[0] ? subtitles[0].getRootNode() : document;
- if (root) {
- const container = root.querySelector(rule.displaySelector) as HTMLElement;
- if (container) {
- // Save the original display style if none was included in the rule
- if (
- rule.displayShow === ''
- && container.style.display !== ''
- && container.style.display !== rule.displayHide
- ) {
- rule.displayShow = container.style.display;
- }
-
- container.style.setProperty('display', rule.displayHide); // , 'important');
- }
- }
- } else if (subtitles) {
- subtitles.forEach((subtitle) => {
- subtitle.innerText = '';
- if (rule.removeSubtitleSpacing && subtitle.style) {
- if (subtitle.style.padding) { subtitle.style.padding = 0; }
- if (subtitle.style.margin) { subtitle.style.margin = 0; }
- }
- });
- }
- }
-
- initCueRule(rule: AudioRule) {
- if (rule.videoSelector === undefined) { rule.videoSelector = WebAudio.DefaultVideoSelector; }
- if (rule.videoCueRequireShowing === undefined) { rule.videoCueRequireShowing = this.filter.cfg.muteCueRequireShowing; }
- if (rule.externalSub) {
- if (rule.externalSubURLKey === undefined) { rule.externalSubURLKey = 'url'; }
- if (rule.externalSubFormatKey === undefined) { rule.externalSubFormatKey = 'format'; }
- if (rule.externalSubTrackLabel === undefined) { rule.externalSubTrackLabel = 'APF'; }
- }
- this.initDisplaySelector(rule);
- }
-
- initDisplaySelector(rule: AudioRule) {
- if (rule.displaySelector !== undefined) {
- if (rule.displayHide === undefined) { rule.displayHide = 'none'; }
- if (rule.displayShow === undefined) { rule.displayShow = ''; }
- }
- }
-
- initElementChildRule(rule: AudioRule) {
- if (!rule.parentSelector && !rule.parentSelectorAll) { rule.disabled = true; }
- this.initDisplaySelector(rule);
- }
-
- initElementRule(rule: AudioRule) {
- this.initDisplaySelector(rule);
- }
-
- initFillerAudio(name: string = ''): HTMLAudioElement {
- const fillerConfig = WebAudio.FillerConfig[name];
- if (fillerConfig) {
- const url = chrome.runtime.getURL(fillerConfig.fileName);
- const audioFiller = new Audio();
- audioFiller.src = url;
- audioFiller.loop = true;
- if (fillerConfig.volume) { audioFiller.volume = fillerConfig.volume; }
- if (fillerConfig.loopAfter) {
- audioFiller.ontimeupdate = () => {
- if (audioFiller.currentTime > fillerConfig.loopAfter) {
- audioFiller.currentTime = 0;
- }
- };
- }
- return audioFiller;
- }
- }
-
- initRules() {
- this.rules.forEach((rule, index) => {
- if (
- rule.mode === undefined
- || ((rule.mode == 'element' || rule.mode == 'elementChild') && !rule.tagName)
- // Skip this rule if it doesn't apply to the current page
- || (rule.iframe === true && this.filter.iframe == null)
- || (rule.iframe === false && this.filter.iframe != null)
- ) {
- rule.disabled = true;
- }
-
- if (!rule.disabled) {
- // Setup rule defaults
- if (rule.filterSubtitles == null) { rule.filterSubtitles = true; }
-
- // Allow rules to override global settings
- if (rule.muteMethod == null) { rule.muteMethod = this.filter.cfg.muteMethod; }
- if (rule.showSubtitles == null) { rule.showSubtitles = this.filter.cfg.showSubtitles; }
-
- // Ensure proper rule values
- if (rule.tagName != null && rule.tagName != '#text') { rule.tagName = rule.tagName.toUpperCase(); }
-
- switch(rule.mode) {
- case 'cue':
- this.initCueRule(rule);
- if (!rule.disabled) { this.cueRuleIds.push(index); }
- break;
- case 'elementChild':
- this.initElementChildRule(rule);
- break;
- case 'element':
- this.initElementRule(rule);
- break;
- case 'text':
- this.initTextRule(rule);
- break;
- case 'watcher':
- this.initWatcherRule(rule);
- if (!rule.disabled) { this.watcherRuleIds.push(index); }
- break;
- }
- if (!rule.disabled) { this.enabledRuleIds.push(index); }
- }
- });
- }
-
- initTextRule(rule: AudioRule) {
- rule.tagName = '#text';
- if (rule.simpleUnmute === undefined) { rule.simpleUnmute = true; }
- }
-
- initWatcherRule(rule: AudioRule) {
- if (rule.checkInterval === undefined) { rule.checkInterval = 20; }
- if (rule.ignoreMutations === undefined) { rule.ignoreMutations = true; }
- if (rule.simpleUnmute === undefined) { rule.simpleUnmute = true; }
- if (rule.videoSelector === undefined) { rule.videoSelector = WebAudio.DefaultVideoSelector; }
- this.initDisplaySelector(rule);
- }
-
- mute(rule?: AudioRule, video?: HTMLVideoElement): void {
- if (!this.muted) {
- this.muted = true;
- const muteMethod = rule && rule.muteMethod >= 0 ? rule.muteMethod : this.filter.cfg.muteMethod;
-
- switch(muteMethod) {
- case Constants.MuteMethods.Tab:
- chrome.runtime.sendMessage({ mute: true });
- break;
- case Constants.MuteMethods.Video:
- if (!video) { video = document.querySelector(rule && rule.videoSelector ? rule.videoSelector : WebAudio.DefaultVideoSelector); }
- if (video && video.volume != null) {
- this.volume = video.volume; // Save original volume
- video.volume = 0;
- }
- if (this.fillerAudio) { this.playFillerAudio(); }
- break;
- }
- }
-
- // If we called mute and there is a delayedUnmute planned, clear it
- if (rule && rule.unmuteDelay && this.unmuteTimeout) { this.clearUnmuteTimeout(rule); }
- }
-
- newCue(start, end, text, options: ParsedSubOptions = {}): VTTCue {
- try {
- const cue = new VTTCue(hmsToSeconds(start), hmsToSeconds(end), text);
- if (options.align) { cue.align = options.align; }
- if (options.line) { cue.line = this.parseLineAndPositionSetting(options.line); }
- if (options.position) { cue.position = this.parseLineAndPositionSetting(options.position); }
- return cue;
- } catch (e) {
- logger.error(`[Audio] Failed to add cue: ( start: ${start}, end: ${end}, text: ${text} )`, e);
- }
- }
-
- newTextTrack(rule: AudioRule, video: HTMLVideoElement, cues: VTTCue[]): TextTrack {
- if (video.textTracks) {
- const track = video.addTextTrack('captions', rule.externalSubTrackLabel, rule.videoCueLanguage) as TextTrack;
- track.mode = 'showing';
- for (let i = 0; i < cues.length; i++) {
- track.addCue(cues[i]);
- }
- return track;
- }
- }
-
- parseLineAndPositionSetting(setting: string): LineAndPositionSetting {
- if (typeof setting == 'string' && setting != '') {
- if (setting == 'auto') {
- return 'auto';
- } else {
- return parseInt(setting);
- }
- }
- }
-
- parseSRT(srt): VTTCue[] {
- const lines = srt.trim().replace('\r\n', '\n').split(/[\r\n]/).map((line) => line.trim());
- const cues: VTTCue[] = [];
- let start = null;
- let end = null;
- let text = null;
- for (let i = 0; i < lines.length; i++) {
- if (lines[i].indexOf('-->') >= 0) {
- const splitted = lines[i].split(/[ \t]+-->[ \t]+/);
- if (splitted.length != 2) {
- throw 'Error when splitting "-->": ' + lines[i];
- }
- start = splitted[0];
- end = splitted[1];
- } else if (lines[i] == '') {
- if (start && end) {
- const cue = this.newCue(start, end, text);
- cues.push(cue);
- start = null;
- end = null;
- text = null;
- }
- } else if(start && end) {
- if (text == null) {
- text = lines[i];
- } else {
- text += '\n' + lines[i];
- }
- }
- }
- if (start && end) {
- const cue = this.newCue(start, end, text);
- cues.push(cue);
- }
- return cues;
- }
-
- parseSSA(ssa: string): VTTCue[] {
- const cues: VTTCue[] = [];
- let endIndex, startIndex, textIndex;
- let foundEvents = false;
-
- const lines = ssa.split('\n');
- for (let i = 0; i < lines.length; i++) {
- if (!foundEvents) {
- if (lines[i].match(/^\[Events\]/i)) { foundEvents = true; }
- continue;
- }
-
- if (lines[i].match(/^format:/i)) {
- const format = lines[i].trim().split(',');
- endIndex = format.indexOf('End');
- startIndex = format.indexOf('Start');
- textIndex = format.indexOf('Text');
- } else if (lines[i].match(/^dialogue:/i)) {
- const line = lines[i].trim().split(',');
- const start = line[startIndex];
- const end = line[endIndex];
- const cleanText = line.slice(textIndex).join(',').replace(/\{\\\w.+?\}/g, '').split('\\N').reverse(); // Cleanup formatting and convert newlines
- for (let j = 0; j < cleanText.length; j++) {
- cues.push(this.newCue(start, end, cleanText[j]));
- }
- }
- }
- return cues;
- }
-
- parseVTT(input: string): VTTCue[] {
- const cues: VTTCue[] = [];
- const lines = input.split('\n');
- const separator = new RegExp('\\s-->\\s');
-
- for (let i = 0; i < lines.length; i++) {
- const line = lines[i].trim();
- if (line.match(separator)) { // Timestamp [& option] line
- const parts = line.replace(separator, ' ').split(' ');
- let [start, end, ...extraOptions] = parts;
- start = start.replace(',', '.');
- end = end.replace(',', '.');
- const options: ParsedSubOptions = extraOptions.map((o) => o.split(':')).reduce((acc, cur) => {acc[cur[0]] = cur[1]; return acc;}, {});
-
- // Get text
- const prevLine = lines[i-1].trim();
- const nextLine = lines[i+1].trim();
- const textStartRegex = new RegExp(`^<[cs]\\.${prevLine}>`);
- const textEndRegex = new RegExp('<\/[cs]>$');
- let text;
- if (nextLine.match(textStartRegex)) {
- text = nextLine.replace(textStartRegex, '').replace(textEndRegex, '');
- } else {
- text = nextLine;
- }
-
- // Handle the case when there are multiple cues that should be shown concurrently
- // The first line of the entry could look like "Caption-C8_1", and the subsequent entry would be "Caption-C8_2"
- if (prevLine && !prevLine.match(/_1$/)) {
- const previousCue = cues[cues.length-1];
- // If they share an endTime with the previous cue, but startTimes are different, make them match
- if (previousCue.startTime != hmsToSeconds(start) && previousCue.endTime == hmsToSeconds(end)) {
- start = secondsToHMS(previousCue.startTime);
- }
- }
-
- const cue = this.newCue(start, end, text, options);
-
- // Concurrent cues seem to be displayed backwards, so we'll reverse them: [a,b,c] -> [c,b,a]
- if (prevLine && !prevLine.match(/_1$/)) {
- const concurrentNumber = parseInt(prevLine.match(/_([2-9])$/)[1]);
- const firstConcurrentCueIndex = (cues.length - concurrentNumber) + 1; // Find the first concurrent index
- cues.splice(firstConcurrentCueIndex, 0, cue);
- } else {
- cues.push(cue);
- }
-
- i++; // Skip the next line because we already processed the text
- }
- }
- return cues;
- }
-
- playFillerAudio() {
- this.fillerAudio.play();
- }
-
- playing(video: HTMLVideoElement): boolean {
- return !!(video && video.currentTime > 0 && !video.paused && !video.ended && video.readyState > 2);
- }
-
- processCues(cues: FilteredVTTCue[], rule: AudioRule) {
- for (let i = 0; i < cues.length; i++) {
- const cue = cues[i];
- if (cue.hasOwnProperty('filtered')) { continue; }
-
- if (rule.videoCueSync) {
- cue.startTime += rule.videoCueSync;
- cue.endTime += rule.videoCueSync;
- }
-
- const result = this.replaceTextResult(cue.text);
- if (result.modified) {
- cue.filtered = true;
- cue.originalText = cue.text;
- cue.text = result.filtered;
- } else {
- cue.filtered = false;
- }
-
- if (rule.videoCueHideCues) { this.hideCue(rule, cue); }
- }
- }
-
- async processExternalSub(video: HTMLVideoElement, rule) {
- const textTrack = this.getVideoTextTrack(video.textTracks, rule, 'externalSubTrackLabel');
- if (!this.fetching && !textTrack) {
- try {
- const subsData = getGlobalVariable(rule.externalSubVar);
- if (Array.isArray(subsData)) {
- const found = subsData.find((subtitle) => subtitle.language === rule.videoCueLanguage);
- if (!found) { throw(`Failed to find subtitle for language: ${rule.videoCueLanguage}.`); }
- this.fetching = true;
- const subs = await makeRequest('GET', found[rule.externalSubURLKey]) as string;
- if (typeof subs == 'string' && subs) {
- let parsedCues;
- switch(found[rule.externalSubFormatKey]) {
- case 'ass': parsedCues = this.parseSSA(subs); break;
- case 'srt': parsedCues = this.parseSRT(subs); break;
- case 'vtt': parsedCues = this.parseVTT(subs); break;
- default:
- throw(`Unsupported subtitle type: ${found[rule.externalSubFormatKey]}`);
- }
- if (parsedCues) {
- const track = this.newTextTrack(rule, video, parsedCues);
- const cues = track.cues as any as FilteredVTTCue[];
- this.processCues(cues, rule);
- this.fetching = false;
-
- // Hide old captions/subtitles
- if (rule.displaySelector) {
- const oldSubtitlesContainer = document.querySelector(rule.displaySelector) as HTMLElement;
- if (oldSubtitlesContainer) { oldSubtitlesContainer.style.display = 'none'; }
- }
- }
- } else {
- throw(`Failed to download external subtitles from '${found[rule.externalSubURLKey]}'.`);
- }
- } else {
- throw(`Failed to find subtitle variable: ${rule.externalSubVar}`);
- }
- } catch(e) {
- logger.error(`[Audio] Error using external subtitles for ${this.filter.hostname}.`, e);
- }
- }
- }
-
- processWatcherCaptions(rule, captions, data) {
- const initialCall = data.initialCall; // Check if this is the first call
- if (initialCall) {
- // Don't process the same filter again
- if (this.lastProcessedText && this.lastProcessedText === captions.textContent) {
- data.skipped = true;
- return false;
- } else { // These are new captions, unmute if muted
- this.unmute(rule);
- this.lastProcessedText = '';
- }
-
- data.initialCall = false;
- data.filtered = false;
- }
-
- if (captions.hasChildNodes()) {
- captions.childNodes.forEach((child) => {
- this.processWatcherCaptions(rule, child, data);
- });
- } else { // Process child
- // innerText handles line feeds/spacing better, but is not available to #text nodes
- const textMethod = (captions && captions.nodeName) === '#text' ? 'textContent' : 'innerText';
-
- // Don't process empty/whitespace nodes
- if (captions[textMethod] && captions[textMethod].trim()) {
- const result = this.replaceTextResult(captions[textMethod]);
- if (result.modified) {
- this.mute(rule);
- data.filtered = true;
- if (rule.filterSubtitles) { captions[textMethod] = result.filtered; }
- }
- }
- }
-
- if (initialCall) { this.lastProcessedText = captions.textContent; }
- }
-
- replaceTextResult(string: string, stats: boolean = true) {
- return this.filter.replaceTextResult(string, this.wordlistId, stats);
- }
-
- showSubtitles(rule, subtitles?) {
- if (rule.displaySelector) {
- const root = rule.rootNode && subtitles && subtitles[0] ? subtitles[0].getRootNode() : document;
- if (root) {
- const container = root.querySelector(rule.displaySelector);
- if (container) { container.style.setProperty('display', rule.displayShow); }
- }
- }
- }
-
- stopFillerAudio() {
- this.fillerAudio.pause();
- this.fillerAudio.currentTime = 0;
- }
-
- // Checks if a node is a supported audio node.
- // Returns rule id upon first match, otherwise returns false
- supportedNode(node) {
- for (let i = 0; i < this.enabledRuleIds.length; i++) {
- const ruleId = this.enabledRuleIds[i];
- const rule = this.rules[ruleId];
-
- switch(rule.mode) {
- case 'element':
- if (node.nodeName == rule.tagName) {
- let failed = false;
- if (!failed && rule.className && (!node.className || !node.classList.contains(rule.className))) { failed = true; }
- if (!failed && rule.dataPropPresent && (!node.dataset || !node.dataset.hasOwnProperty(rule.dataPropPresent))) { failed = true; }
- if (!failed && rule.hasChildrenElements && (typeof node.childElementCount !== 'number' || node.childElementCount == 0)) { failed = true; }
- if (!failed && rule.subtitleSelector && (typeof node.querySelector !== 'function' || !node.querySelector(rule.subtitleSelector))) { failed = true; }
- if (!failed && rule.containsSelector && (typeof node.querySelector !== 'function' || !node.querySelector(rule.containsSelector))) { failed = true; }
- if (!failed) { return ruleId; }
- }
- break;
- case 'elementChild':
- if (node.nodeName === rule.tagName) {
- const root = rule.rootNode ? node.getRootNode() : document;
- if (root) {
- if (rule.parentSelector) {
- const parent = root.querySelector(rule.parentSelector);
- if (parent && parent.contains(node)) { return ruleId; }
- } else {
- const parents = root.querySelectorAll(rule.parentSelectorAll);
- for (let j = 0; j < parents.length; j++) {
- if (parents[j].contains(node)) { return ruleId; }
- }
- }
- }
- }
- break;
- case 'text':
- if (node.nodeName === rule.tagName) {
- const parent = document.querySelector(rule.parentSelector);
- if (parent && parent.contains(node)) { return ruleId; }
- }
- break;
- case 'watcher':
- if (node.parentElement && node.parentElement == document.querySelector(rule.subtitleSelector)) { return ruleId; }
- if (rule.parentSelector != null) {
- const parent = document.querySelector(rule.parentSelector);
- if (parent && parent.contains(node)) { return ruleId; }
- }
- break;
- }
- }
-
- // No matching rule was found
- return false;
- }
-
- textTrackKeyTest(textTrack: TextTrack, key: string, value: string) {
- return (textTrack[key] && value && textTrack[key] === value);
- }
-
- unmute(rule?: AudioRule, video?: HTMLVideoElement, delayed: boolean = false): void {
- if (this.muted) {
- // If we haven't already delayed unmute and we should (rule.unmuteDelay), set the timeout
- if (!delayed && rule && rule.unmuteDelay >= 0) {
- // If unmute is called after an unmute has been scheduled, remove the older one and schedule a new unmute
- if (this.unmuteTimeout == null) { this.clearUnmuteTimeout(rule); }
- this.unmuteTimeout = window.setTimeout(this.delayedUnmute, rule.unmuteDelay, this, rule);
- return;
- }
-
- this.muted = false;
- const muteMethod = rule && rule.muteMethod >= 0 ? rule.muteMethod : this.filter.cfg.muteMethod;
-
- switch(muteMethod) {
- case Constants.MuteMethods.Tab:
- chrome.runtime.sendMessage({ mute: false });
- break;
- case Constants.MuteMethods.Video:
- if (this.fillerAudio) { this.stopFillerAudio(); }
- if (!video) { video = document.querySelector(rule && rule.videoSelector ? rule.videoSelector : WebAudio.DefaultVideoSelector); }
- if (video && video.volume != null) {
- video.volume = this.volume;
- }
- break;
- }
- }
- }
-
- watcher(instance: WebAudio, ruleId = 0) {
- const rule = instance.rules[ruleId];
- const video = document.querySelector(rule.videoSelector) as HTMLVideoElement;
-
- if (video && instance.playing(video)) {
- if (rule.ignoreMutations) { instance.filter.stopObserving(); } // Stop observing when video is playing
-
- const captions = document.querySelector(rule.subtitleSelector) as HTMLElement;
- if (captions && captions.textContent && captions.textContent.trim()) {
- const data: WatcherData = { initialCall: true };
- instance.processWatcherCaptions(rule, captions, data);
- if (data.skipped) { return false; }
-
- // Hide/show captions/subtitles
- switch (rule.showSubtitles) {
- case Constants.ShowSubtitles.Filtered: if (data.filtered) { instance.showSubtitles(rule); } else { instance.hideSubtitles(rule); } break;
- case Constants.ShowSubtitles.Unfiltered: if (data.filtered) { instance.hideSubtitles(rule); } else { instance.showSubtitles(rule); } break;
- case Constants.ShowSubtitles.None: instance.hideSubtitles(rule); break;
- }
-
- if (data.filtered) { instance.filter.updateCounterBadge(); }
- } else if (rule.simpleUnmute) { // If there are no captions/subtitles: unmute and hide
- instance.unmute(rule, video);
- if (rule.showSubtitles > 0) { instance.hideSubtitles(rule); }
- }
- } else {
- if (rule.ignoreMutations) { instance.filter.startObserving(); } // Start observing when video is not playing
- }
- }
-
- watchForVideo(instance: WebAudio) {
- for (let x = 0; x < instance.cueRuleIds.length; x++) {
- const rule = instance.rules[x] as AudioRule;
- const video = document.querySelector(rule.videoSelector) as HTMLVideoElement;
- if (video && video.textTracks && instance.playing(video)) {
- if (rule.externalSub) { instance.processExternalSub(video, rule); }
- const textTrack = instance.getVideoTextTrack(video.textTracks, rule);
-
- if (textTrack && !textTrack.oncuechange) {
- if (!rule.videoCueHideCues && rule.showSubtitles === Constants.ShowSubtitles.None) { textTrack.mode = 'hidden'; }
-
- textTrack.oncuechange = () => {
- if (textTrack.activeCues && textTrack.activeCues.length > 0) {
- let filtered = false;
-
- for (let i = 0; i < textTrack.activeCues.length; i++) {
- const activeCue = textTrack.activeCues[i] as FilteredVTTCue;
- if (!activeCue.hasOwnProperty('filtered')) {
- const cues = textTrack.cues as any as FilteredVTTCue[];
- instance.processCues(cues, rule);
- }
-
- if (activeCue.filtered) {
- filtered = true;
- instance.mute(rule, video);
- }
- }
-
- if (!filtered) { instance.unmute(rule, video); }
-
- if (!rule.videoCueHideCues) {
- if (filtered) {
- switch (rule.showSubtitles) {
- case Constants.ShowSubtitles.Filtered: textTrack.mode = 'showing'; break;
- case Constants.ShowSubtitles.Unfiltered: textTrack.mode = 'hidden'; break;
- }
- } else {
- switch (rule.showSubtitles) {
- case Constants.ShowSubtitles.Filtered: textTrack.mode = 'hidden'; break;
- case Constants.ShowSubtitles.Unfiltered: textTrack.mode = 'showing'; break;
- }
- }
- }
-
- if (rule.displaySelector) {
- if (filtered) {
- switch (rule.showSubtitles) {
- case Constants.ShowSubtitles.Filtered: instance.showSubtitles(rule); break;
- case Constants.ShowSubtitles.Unfiltered: instance.hideSubtitles(rule); break;
- }
- } else {
- switch (rule.showSubtitles) {
- case Constants.ShowSubtitles.Filtered: instance.hideSubtitles(rule); break;
- case Constants.ShowSubtitles.Unfiltered: instance.showSubtitles(rule); break;
- }
- }
- }
- } else { // No active cues
- instance.unmute(rule, video);
- }
- };
- }
- }
- }
- }
-
- youTubeAutoSubsCurrentRow(node): boolean {
- return !!(node.parentElement.parentElement == node.parentElement.parentElement.parentElement.lastChild);
- }
-
- youTubeAutoSubsMuteTimeout(instance) {
- const video = window.document.querySelector(WebAudio.DefaultVideoSelector);
- if (video && instance.playing(video)) {
- instance.unmute();
- }
- instance.youTubeAutoSubsTimeout = null;
- }
-
- youTubeAutoSubsNodeIsSubtitleText(node): boolean {
- const captionWindow = document.querySelector('div.caption-window'); // YouTube Auto-gen subs
- return !!(captionWindow && captionWindow.contains(node));
- }
-
- youTubeAutoSubsPresent(): boolean {
- return !!(document.querySelector('div.ytp-caption-window-rollup'));
- }
-
- youTubeAutoSubsSupportedNode(node: any): boolean {
- if (node.nodeName == '#text' && node.textContent != '') {
- return !!(this.youTubeAutoSubsNodeIsSubtitleText(node));
- }
- return false;
- }
-}
\ No newline at end of file
diff --git a/wordfilter b/wordfilter
deleted file mode 100644
index 03b65a8..0000000
--- a/wordfilter
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "compilerOptions": {
- "outDir": "./dist",
- "allowJs": true,
- "target": "esnext",
- "noEmit": true,
- "lib": ["es2017", "dom", "dom.iterable"]
- },
- "include": [
- "./src/script/**/*.ts"
- ]
-}
diff --git "a/{ ..., \"manifest_version\": 2, ... }" "b/{ ..., \"manifest_version\": 2, ... }"
deleted file mode 100644
index 9a8c18f..0000000
--- "a/{ ..., \"manifest_version\": 2, ... }"
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- ...,
- "manifest_version": 2,
- ...
-}