Skip to content

Commit cf167c6

Browse files
authored
Merge pull request #29 from jamesainslie/feature-site-blocking
feat(content): add site blocklist controls
2 parents 0bcd33d + 39f5804 commit cf167c6

File tree

15 files changed

+1006
-65
lines changed

15 files changed

+1006
-65
lines changed

CHANGELOG.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
## [0.3.1](https://github.com/jamesainslie/mdview/compare/mdview-v0.3.0...mdview-v0.3.1) (2025-12-02)
1+
## [0.3.2](https://github.com/jamesainslie/mdview/compare/mdview-v0.3.1...mdview-v0.3.2) (2025-12-02)
22

33

44
### Documentation
55

6-
* **changelog:** remove manual unreleased section ([eaf770f](https://github.com/jamesainslie/mdview/commit/eaf770f71be1d6696e040f34f288da47469a246f))
6+
* **changelog:** remove duplicate 0.2.0 section ([2e2cfd5](https://github.com/jamesainslie/mdview/commit/2e2cfd5b698b77d8c88244a3a0ed86ba6751de88))
77

8-
## [0.3.2](https://github.com/jamesainslie/mdview/compare/mdview-v0.3.1...mdview-v0.3.2) (2025-12-02)
8+
## [0.3.1](https://github.com/jamesainslie/mdview/compare/mdview-v0.3.0...mdview-v0.3.1) (2025-12-02)
99

1010

1111
### Documentation
1212

13-
* **changelog:** remove duplicate 0.2.0 section ([2e2cfd5](https://github.com/jamesainslie/mdview/commit/2e2cfd5b698b77d8c88244a3a0ed86ba6751de88))
13+
* **changelog:** remove manual unreleased section ([eaf770f](https://github.com/jamesainslie/mdview/commit/eaf770f71be1d6696e040f34f288da47469a246f))
1414

1515
## [0.3.0](https://github.com/jamesainslie/mdview/compare/mdview-v0.2.8...mdview-v0.3.0) (2025-12-02)
1616

public/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "MDView - Markdown Viewer",
4-
"version": "0.2.7",
4+
"version": "0.3.2",
55
"description": "Beautiful markdown file viewer with themes, syntax highlighting, and interactive Mermaid diagrams",
66
"permissions": [
77
"storage"

src/background/service-worker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const defaultState: AppState = {
2424
tocMaxDepth: 6,
2525
tocAutoCollapse: false,
2626
tocPosition: 'left',
27+
blockedSites: [], // Sites where MDView should not render
2728
},
2829
document: {
2930
path: '',

src/content/content-script.ts

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Injected into markdown files to handle rendering
44
*/
55

6+
// CSS is imported but only activated when we add .mdview-active to body
67
import './content.css';
78
import { FileScanner } from '../utils/file-scanner';
89
import type { AppState } from '../types';
@@ -51,9 +52,15 @@ class MDViewContentScript {
5152

5253
// Check if this is a markdown file (before logging, since we need state for debug mode)
5354
const isMarkdown = FileScanner.isMarkdownFile();
55+
console.log('[MDView] isMarkdownFile check:', {
56+
isMarkdown,
57+
contentType: document.contentType,
58+
pathname: window.location.pathname,
59+
href: window.location.href,
60+
});
5461
if (!isMarkdown) {
55-
// Can't debug.log here as debug mode isn't loaded yet
5662
console.log('[MDView] Not a markdown file, skipping initialization');
63+
this.logStyleDebug('non-markdown');
5764
return;
5865
}
5966

@@ -67,6 +74,22 @@ class MDViewContentScript {
6774
debug.debug('MDView', `Document ready state: ${document.readyState}`);
6875
debug.debug('MDView', `Debug mode enabled: ${this.state?.preferences.debug}`);
6976
debug.debug('MDView', `Auto-reload enabled: ${this.state?.preferences.autoReload}`);
77+
78+
// Check if this site is in the blocklist
79+
const blockedSites = this.state?.preferences.blockedSites || [];
80+
debug.info('MDView', `Blocklist check - patterns: ${JSON.stringify(blockedSites)}`);
81+
debug.info('MDView', `Blocklist check - current hostname: ${window.location.hostname}`);
82+
if (FileScanner.isSiteBlocked(blockedSites)) {
83+
debug.info('MDView', 'Site is in blocklist, skipping rendering');
84+
this.logStyleDebug('blocked');
85+
console.log('[MDView] Site blocked by user preference, skipping initialization');
86+
return;
87+
}
88+
debug.info('MDView', 'Site is NOT blocked, proceeding with render');
89+
90+
// Activate styles only after confirming this page should be rendered
91+
this.activateStyles();
92+
7093
debug.info('MDView', 'Content script initializing...');
7194
debug.info('MDView', 'Markdown file detected:', FileScanner.getFilePath());
7295

@@ -270,6 +293,93 @@ class MDViewContentScript {
270293
}
271294
}
272295

296+
/**
297+
* Activate MDView styles by adding a scoping class to the body element.
298+
* Global resets in content.css are scoped to body.mdview-active to avoid
299+
* impacting sites where MDView should not render (e.g. GitHub UI pages).
300+
*/
301+
private activateStyles(): void {
302+
document.body.classList.add('mdview-active');
303+
debug.info('MDView', 'Content styles activated (body.mdview-active)');
304+
}
305+
306+
/**
307+
* Emit debug information about styles in different contexts
308+
* (non-markdown page, blocked site, etc.). This helps verify
309+
* whether any MDView styles are affecting the page when they
310+
* should not.
311+
*/
312+
private logStyleDebug(context: string): void {
313+
try {
314+
debug.info('MDView', `=== STYLE DEBUG START (${context}) ===`);
315+
316+
// 1. Body class list and key computed styles
317+
const body = document.body;
318+
const classes = Array.from(body.classList.values());
319+
const computed = window.getComputedStyle(body);
320+
321+
debug.info('MDView', 'Body classList:', JSON.stringify(classes));
322+
debug.info('MDView', 'Body computed styles snapshot:', {
323+
backgroundColor: computed.backgroundColor,
324+
color: computed.color,
325+
fontFamily: computed.fontFamily,
326+
fontSize: computed.fontSize,
327+
lineHeight: computed.lineHeight,
328+
});
329+
330+
// 2. Stylesheets originating from this extension
331+
const styleSheets = Array.from(document.styleSheets);
332+
const extensionId = chrome.runtime.id;
333+
334+
const extensionSheets: Array<{
335+
index: number;
336+
href: string | null;
337+
ownerTag: string | null;
338+
rules: number | 'unknown';
339+
}> = [];
340+
341+
styleSheets.forEach((sheet, index) => {
342+
let href: string | null = null;
343+
let ownerTag: string | null = null;
344+
let rules: number | 'unknown' = 'unknown';
345+
346+
try {
347+
href = sheet.href || null;
348+
} catch {
349+
href = null;
350+
}
351+
352+
const owner = sheet.ownerNode as HTMLElement | null;
353+
if (owner) {
354+
ownerTag = owner.tagName.toLowerCase();
355+
}
356+
357+
const isFromExtension =
358+
(href && href.startsWith(`chrome-extension://${extensionId}/`)) ||
359+
(owner && owner.tagName.toLowerCase() === 'style');
360+
361+
if (!isFromExtension) {
362+
return;
363+
}
364+
365+
try {
366+
// Accessing cssRules may throw for cross-origin stylesheets
367+
const cssRules = sheet.cssRules;
368+
rules = cssRules ? cssRules.length : 0;
369+
} catch {
370+
rules = 'unknown';
371+
}
372+
373+
extensionSheets.push({ index, href, ownerTag, rules });
374+
});
375+
376+
debug.info('MDView', 'Extension stylesheets on page:', extensionSheets);
377+
debug.info('MDView', `=== STYLE DEBUG END (${context}) ===`);
378+
} catch (error) {
379+
debug.error('MDView', 'Failed to collect style debug:', error);
380+
}
381+
}
382+
273383
private async loadState(): Promise<void> {
274384
try {
275385
const response: unknown = await chrome.runtime.sendMessage({ type: 'GET_STATE' });

src/content/content.css

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,19 @@
3232
border-color 100ms ease !important;
3333
}
3434

35-
/* Reset and base styles */
36-
* {
35+
/* Reset and base styles - only apply when MDView is active */
36+
body.mdview-active,
37+
body.mdview-active * {
3738
margin: 0;
3839
padding: 0;
3940
box-sizing: border-box;
4041
}
4142

42-
::selection {
43+
body.mdview-active ::selection {
4344
background: var(--md-selection);
4445
}
4546

46-
body {
47+
body.mdview-active {
4748
background-color: var(--md-bg);
4849
color: var(--md-fg);
4950
font-family: var(--md-font-family);
@@ -241,39 +242,44 @@ body {
241242
}
242243

243244
/* Headings */
244-
h1, h2, h3, h4, h5, h6 {
245+
body.mdview-active h1,
246+
body.mdview-active h2,
247+
body.mdview-active h3,
248+
body.mdview-active h4,
249+
body.mdview-active h5,
250+
body.mdview-active h6 {
245251
color: var(--md-heading);
246252
font-weight: 600;
247253
margin-top: 24px;
248254
margin-bottom: 16px;
249255
line-height: 1.25;
250256
}
251257

252-
h1 {
258+
body.mdview-active h1 {
253259
font-size: 2em;
254260
padding-bottom: 0.3em;
255261
border-bottom: 1px solid var(--md-border);
256262
}
257263

258-
h2 {
264+
body.mdview-active h2 {
259265
font-size: 1.5em;
260266
padding-bottom: 0.3em;
261267
border-bottom: 1px solid var(--md-border);
262268
}
263269

264-
h3 {
270+
body.mdview-active h3 {
265271
font-size: 1.25em;
266272
}
267273

268-
h4 {
274+
body.mdview-active h4 {
269275
font-size: 1em;
270276
}
271277

272-
h5 {
278+
body.mdview-active h5 {
273279
font-size: 0.875em;
274280
}
275281

276-
h6 {
282+
body.mdview-active h6 {
277283
font-size: 0.85em;
278284
color: var(--md-fg);
279285
opacity: 0.7;
@@ -293,42 +299,43 @@ h6 {
293299
}
294300

295301
/* Paragraphs */
296-
p {
302+
body.mdview-active p {
297303
margin-top: 0;
298304
margin-bottom: 16px;
299305
}
300306

301307
/* Links */
302-
a {
308+
body.mdview-active a {
303309
color: var(--md-link);
304310
text-decoration: none;
305311
}
306312

307-
a:hover {
313+
body.mdview-active a:hover {
308314
color: var(--md-link-hover);
309315
text-decoration: underline;
310316
}
311317

312-
a:visited {
318+
body.mdview-active a:visited {
313319
color: var(--md-link-visited);
314320
}
315321

316322
/* Lists */
317-
ul, ol {
323+
body.mdview-active ul,
324+
body.mdview-active ol {
318325
margin-top: 0;
319326
margin-bottom: 16px;
320327
padding-left: 2em;
321328
}
322329

323-
li {
330+
body.mdview-active li {
324331
margin-top: 0.25em;
325332
}
326333

327-
li > p {
334+
body.mdview-active li > p {
328335
margin-bottom: 0;
329336
}
330337

331-
li + li {
338+
body.mdview-active li + li {
332339
margin-top: 0.25em;
333340
}
334341

@@ -344,7 +351,7 @@ li + li {
344351
}
345352

346353
/* Code */
347-
code {
354+
body.mdview-active code {
348355
background-color: var(--md-code-bg);
349356
color: var(--md-code-text);
350357
font-family: var(--md-font-family-code);
@@ -353,7 +360,7 @@ code {
353360
border-radius: 3px;
354361
}
355362

356-
pre {
363+
body.mdview-active pre {
357364
background-color: var(--md-code-bg);
358365
color: var(--md-code-text);
359366
font-family: var(--md-font-family-code);
@@ -364,7 +371,7 @@ pre {
364371
margin-bottom: 16px;
365372
}
366373

367-
pre code {
374+
body.mdview-active pre code {
368375
background: transparent;
369376
padding: 0;
370377
font-size: 100%;
@@ -558,33 +565,33 @@ hr {
558565
margin-bottom: 16px;
559566
}
560567

561-
table {
568+
body.mdview-active table {
562569
width: 100%;
563570
border-collapse: collapse;
564571
border-spacing: 0;
565572
}
566573

567-
table th {
574+
body.mdview-active table th {
568575
font-weight: 600;
569576
background-color: var(--md-code-bg);
570577
}
571578

572-
table th,
573-
table td {
579+
body.mdview-active table th,
580+
body.mdview-active table td {
574581
padding: 6px 13px;
575582
border: 1px solid var(--md-border);
576583
}
577584

578-
table tr {
585+
body.mdview-active table tr {
579586
background-color: var(--md-bg);
580587
}
581588

582-
table tr:nth-child(2n) {
589+
body.mdview-active table tr:nth-child(2n) {
583590
background-color: var(--md-code-bg);
584591
}
585592

586593
/* Images */
587-
img {
594+
body.mdview-active img {
588595
max-width: 100%;
589596
height: auto;
590597
display: block;

0 commit comments

Comments
 (0)