Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/verify-pull-request.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Verify Pull Request

on:
workflow_dispatch:
pull_request:
branches:
- develop
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.2] - 2025-11-12

### Fixed

- CSS selectors for `Members Only` videos

### Added

- Github Actions CI and security scan workflow

## [1.1.1] - 2025-10-22

### Fixed
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,27 @@ A browser extension that filters out watched and members-only YouTube videos, ke
## Development

- git clone this repository.
- run `npm i`
- run `npm start` or `./ddstart` for docker-desktop on Linux
- Run `npm i`
- Run `npm start` or `./ddstart` for docker-desktop on Linux
- Load the extension in your browser:
- Firefox: Go to `about:debugging#/runtime/this-firefox` and select "Load Temporary Add-on."
- Create a `feature/`, `bugfix/`, etc. branch, where you'll commit your code

## Build and Package (for Mozilla code reviewers)

- to build and package into `artifacts/youtube_magic-<version>.zip`: run: `npm run build` or `./ddbuild` for docker-desktop on Linux

## Manual Build Pipeline (for extension developers)

- Create a pull request to merge your `feature` branch into `develop` branch
- Create a pull request to merge your `feature/`, `bugfix/`, etc. branch into the `develop` branch
- Create `release/v<version>` off `develop` branch
- Update `version` in `package.json`, `manifest.json`, `CHANGELOG.md`
- Run `npm install` to update the version in `package-lock.json`
- Commit the changes on the `release/v<version>` branch
- To build for production, and package into `artifacts/youtube_magic-<version>.zip`: run: `npm run build` or `./ddbuild` for docker-desktop on Linux
- Submit zip file from `artifacts/` to https://addons.mozilla.org
- Once the extension is live, merge `release/v<version>` into `develop` and `main`
- `git tag -a v<version> -m "Release <version>: <Summary of changes> - Published to Firefox Add-ons"`
- Tag the latest commit: `git tag -a v<version> -m "Release <version>: <Summary of changes> - Published to Firefox Add-ons"`

## Zip Source Code

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "youtube-magic",
"version": "1.1.1",
"version": "1.1.2",
"main": "index.ts",
"type": "module",
"scripts": {
Expand Down
18 changes: 1 addition & 17 deletions src/code/content/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default class Dom {
/**
* returns all HTML elements for a given selector (`selector` parameter), including the matching parent (`element` parameter) and its children
*/
public static findAll(element: HTMLElement, selector: string) {
public static _findAll(element: HTMLElement, selector: string) {
const elements: HTMLElement[] = [];

if (element.matches(selector)) {
Expand All @@ -59,22 +59,6 @@ export default class Dom {
return elements;
}

/**
* checks if any elements returned by the `findAll` method have text content
*/
public static anySelectedElementHasText(
element: HTMLElement,
selector: string,
) {
const elements = this.findAll(element, selector);

if (elements) {
return elements.some((element) => element.textContent);
} else {
return false;
}
}

/**
* returns the descendant's ancestor HTML element selected by `ancestorSelector`, if found, or null
*/
Expand Down
26 changes: 25 additions & 1 deletion src/code/content/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export default class Element {
return this.youTubePageType;
}

/**
* returns the outermost `contents` element that is visible on the page
*/
public get newContents() {
/* may include invisible elements */
const contentsElements = Array.from(
Expand Down Expand Up @@ -89,6 +92,10 @@ export default class Element {
return this.visibleVideos.length;
}

public isVideo(element: HTMLElement) {
return element.matches(selectors.video[this.pageType]);
}

public waitForAndGetAndSetContents(): Promise<HTMLElement> {
return new Promise((resolve) => {
this.contents = this.newContents;
Expand Down Expand Up @@ -136,7 +143,24 @@ export default class Element {
}

public hasMembersOnlyBadge(element: HTMLElement) {
return Dom.anySelectedElementHasText(element, selectors.membersOnlyBadge);
if (this.isVideo(element)) {
const membersOnlyElements = element.querySelectorAll(
selectors.membersOnlyBadge,
);

return [...membersOnlyElements].some((element) => element.textContent);
}

if (element.textContent) {
const membersOnlyElement = Dom.getAncestor(
selectors.membersOnlyBadge,
element,
);

return !!membersOnlyElement;
}

return false;
}

public hasChipBeenClicked(event: Event) {
Expand Down
2 changes: 1 addition & 1 deletion src/code/content/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export default class Filter {
}

/**
* @param element - can be a video element or an element inside a video. The element and its children are checked recursively for the presence of elements that indicate the video should get hidden, based on the enabled filters
* @param element - can be a video element, or an element inside a video if detected by Mutation Observer. The element and its children are checked recursively for the presence of elements that indicate the video should get hidden, based on the enabled filters
*/
private shouldHideVideo(element: HTMLElement) {
if (this.watchedFilterEnabled && this.element.hasProgressBar(element)) {
Expand Down
2 changes: 1 addition & 1 deletion src/code/content/observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class Observer {
public constructor(
private observedElement: HTMLElement,
private eventBus: EventTarget,
private exclusionSelectors?: string[],
private exclusionSelectors?: string[] /* identifies elements that should not be acted on */,
) {
this.mutationObserver = this.create();
}
Expand Down
2 changes: 1 addition & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "YouTube Magic",
"version": "1.1.1",
"version": "1.1.2",
"description": "Filters out YouTube videos using UI indicators.",
"permissions": ["management", "tabs", "activeTab", "storage"],
"background": {
Expand Down