Skip to content
Open
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@

A lightweight command-line tool that converts markdown files to styled HTML and opens them in your default browser. Supports GitHub Flavored Markdown, Mermaid diagrams, embedded images, and automatic theme detection.

> **This fork adds corporate theming tools** (see [`contrib/`](contrib/README.md)):
> **Style Inspector**, a Chrome extension that extracts any website's design
> tokens (logo, colors, fonts, paddings) and exports them as a theme file, plus
> **mdview-themed**, an offline bash viewer that renders markdown in that
> style — your company's colors, fonts and logo on every document, mermaid
> diagrams re-colored to match. Themes are plain JSON files you can save,
> share and install with one command.

## Features

- **GitHub Flavored Markdown** - Full support for tables, task lists, strikethrough, and more
Expand Down
55 changes: 55 additions & 0 deletions contrib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# contrib: Style Inspector + themed viewer

Companion tools that let `mdview` users render markdown in the visual style of
any website — extract a site's design tokens with a Chrome extension, save them
as a theme file, and apply that theme to a markdown viewer.

## What's inside

| Path | What it is |
|------|------------|
| `chrome-extension/` | **Style Inspector** — a Chrome extension (Manifest V3) that extracts a site's logo, colors, fonts and paddings, and exports them as JSON |
| `mdview-themed` | A self-contained bash markdown viewer (marked + mermaid, fully offline) that renders `.md` files using an installable theme |
| `install-mdview-themed.sh` | Installer: copies the script to `~/.local/bin` and fetches marked/mermaid |
| `mdview-theme.example.json` | Example theme file |

## Workflow

1. Install the extension: `chrome://extensions` → Developer mode → *Load unpacked* → `contrib/chrome-extension`.
2. Open any website, click the extension icon, press **Inject into mdview** —
the extension derives a theme from the page (background, text color, the two
most saturated colors as accents, font stack, logo) and downloads
`mdview-theme.json`.
3. Apply it:

```sh
./contrib/install-mdview-themed.sh
mdview-themed --install-theme ~/Downloads/mdview-theme.json
mdview-themed README.md
```

Every markdown file now opens styled like the site: its colors, its fonts, its
logo in the header. Mermaid diagrams are re-colored to match.

`--reset-theme` restores the built-in dark theme, `--show-theme` prints the
active one.

## Theme file format

```json
{
"bg": "#FFFFFF", // page background
"text": "#1A1A1A", // main text color
"accent": "#7C88FC", // links, table headers, rules
"accent2": "#FF8562", // hover, blockquote border
"surface": "#F5F5F7", // code blocks, quotes, even table rows
"line": "#E6E6E6", // borders
"fonts": ["Manrope", "Roboto", "Arial"],
"logo": "https://…/logo.svg", // URL or data URI; downloaded on install
"site": "example.com" // logo links here
}
```

Only `bg` and `text` are required. The extension's **Export style** / **Import
style** buttons additionally let you save and share the full extracted token
set between machines and teammates.
91 changes: 91 additions & 0 deletions contrib/chrome-extension/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Style Inspector — Chrome Extension

A lightweight Chrome extension that instantly extracts the design system of any website: fonts, colors, paddings, and logo URL — all in one click.

## Demo

[![Style Inspector Demo](https://img.youtube.com/vi/NnzUSkLEZ3M/0.jpg)](https://www.youtube.com/watch?v=NnzUSkLEZ3M)

## What it does

Open any website, click the extension icon — and you'll see:

- **Logo** — image preview with a direct link (falls back to favicon if no logo found)
- **Background colors** — HEX chips, click any chip to copy the code
- **Text colors** — same
- **Fonts** — list with a live preview (`Aa Бб`) in the actual font
- **Paddings** — all unique padding values used on the page

At the bottom there's a **ready-to-copy text summary**, e.g.:

```
Site: business-pad.com
Logo: https://business-pad.com/assets/logo.svg
Background colors: #FFFFFF, #F5F7FA, #1A1A2E
Text colors: #333333, #666666, #0056D2
Fonts: Inter, Roboto
Paddings: 8px, 16px, 24px, 32px, 48px
```

Paste it into a brief, a design chat, or a Notion doc — done.

## Export / Import / mdview

Three buttons in the popup toolbar:

- **Export style** — saves everything the inspector collected as a JSON file
(`style-<domain>.json`). Share it with a teammate or archive it.
- **Import style** — loads a previously exported JSON file and renders it in the
popup, even on pages the extension can't access (e.g. `chrome://` pages).
- **Inject into mdview** — derives a ready-to-use theme (`mdview-theme.json`)
from the page's palette: background, text, the two most saturated colors as
accents, surface/border tones, and the font stack. Apply it to the
[mdview](https://github.com/neo37/mdview) markdown viewer:

```
mdview --install-theme ~/Downloads/mdview-theme.json
```

From then on every markdown file you open with `mdview` is rendered in the
site's corporate style, logo included. `mdview --reset-theme` restores the
default theme.

## Installation (Developer mode)

1. Download or clone this repository
2. Open Chrome → `chrome://extensions/`
3. Enable **Developer mode** (top right toggle)
4. Click **"Load unpacked"**
5. Select the `style-inspector` folder

No build step required — it's pure HTML + JS.

## How it works

When you click the popup, the extension injects `content.js` into the active tab using the Chrome Scripting API. The script scans computed styles of key elements (`header`, `nav`, `h1–h4`, `p`, `button`, `a`, etc.), deduplicates values by frequency, and returns the top results to the popup.

Logo detection checks:
- `<img>` with "logo" in `src`, `alt`, `class`, or `id`
- First `<img>` inside `header` or `nav`
- Inline SVG elements with a logo-related class
- `<link rel="icon">` as a fallback

## Files

| File | Purpose |
|------|---------|
| `manifest.json` | Extension config (Manifest V3) |
| `content.js` | Page analysis — extracts styles and logo |
| `popup.html` | Extension popup UI |
| `popup.js` | Renders results, handles copy |

## Permissions

- `activeTab` — access the current tab when the popup is opened
- `scripting` — inject the analysis script into the page

No data is sent anywhere. Everything runs locally.

## License

MIT
111 changes: 111 additions & 0 deletions contrib/chrome-extension/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
function rgbToHex(rgb) {
const m = rgb.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
if (!m) return null;
return '#' + [m[1], m[2], m[3]]
.map(n => parseInt(n).toString(16).padStart(2, '0'))
.join('').toUpperCase();
}

function getLuminance(hex) {
const r = parseInt(hex.slice(1, 3), 16) / 255;
const g = parseInt(hex.slice(3, 5), 16) / 255;
const b = parseInt(hex.slice(5, 7), 16) / 255;
return 0.299 * r + 0.587 * g + 0.114 * b;
}

function analyzeStyles() {
// --- Logo ---
let logo = null;

const logoImgSelectors = [
'a[href="/"] img', 'header img', 'nav img',
'img[src*="logo" i]', 'img[alt*="logo" i]',
'img[class*="logo" i]', 'img[id*="logo" i]',
'[class*="logo" i] img', '[id*="logo" i] img',
'.navbar-brand img', '.brand img',
];
for (const sel of logoImgSelectors) {
const el = document.querySelector(sel);
if (el && el.src && !el.src.startsWith('data:')) { logo = el.src; break; }
}

// SVG logo
if (!logo) {
const svgEl = document.querySelector(
'[class*="logo" i] svg, [id*="logo" i] svg, header svg, nav svg, .navbar-brand svg'
);
if (svgEl) logo = '__SVG_INLINE__';
}

// Favicon fallback
const favicon = document.querySelector('link[rel~="icon"]');
const faviconUrl = favicon ? favicon.href : null;

// og:image
const ogImage = document.querySelector('meta[property="og:image"]');
const ogUrl = ogImage ? ogImage.content : null;

// --- Colors & Fonts & Paddings ---
const bgColorMap = new Map(); // hex -> count
const textColorMap = new Map(); // hex -> count
const fontMap = new Map(); // family -> count
const paddingSet = new Set();

const els = document.querySelectorAll(
'body, header, nav, main, footer, section, article, aside, ' +
'h1, h2, h3, h4, p, a, button, span, div, li, input, label, ' +
'[class*="btn"], [class*="card"], [class*="hero"], [class*="banner"]'
);

els.forEach(el => {
const s = window.getComputedStyle(el);

// background-color
const bg = s.backgroundColor;
if (bg && bg !== 'rgba(0, 0, 0, 0)') {
const hex = rgbToHex(bg);
if (hex && hex !== '#000000' || bg.includes('0, 0, 0')) {
bgColorMap.set(hex, (bgColorMap.get(hex) || 0) + 1);
}
}

// color
const col = s.color;
if (col) {
const hex = rgbToHex(col);
if (hex) textColorMap.set(hex, (textColorMap.get(hex) || 0) + 1);
}

// font-family (first family only)
const rawFont = s.fontFamily;
if (rawFont) {
const family = rawFont.split(',')[0].trim().replace(/['"]/g, '');
if (family) fontMap.set(family, (fontMap.get(family) || 0) + 1);
}

// paddings
['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'].forEach(prop => {
const val = parseFloat(s[prop]);
if (val > 0 && val < 200) paddingSet.add(val);
});
});

// Sort by frequency, dedupe, limit
const sortByCount = (map) =>
[...map.entries()].sort((a, b) => b[1] - a[1]).map(([k]) => k);

const bgColors = sortByCount(bgColorMap).slice(0, 8);
const textColors = sortByCount(textColorMap).slice(0, 8);

// Unique sorted paddings
const paddings = [...paddingSet]
.sort((a, b) => a - b)
.map(v => v + 'px')
.slice(0, 12);

const fonts = sortByCount(fontMap).slice(0, 6);

return { logo, faviconUrl, ogUrl, bgColors, textColors, fonts, paddings };
}

analyzeStyles();
11 changes: 11 additions & 0 deletions contrib/chrome-extension/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"manifest_version": 3,
"name": "Style Inspector",
"version": "1.1",
"description": "Извлекает шрифты, цвета, отступы и логотип с любого сайта. Экспорт/импорт стиля и тема для mdview",
"permissions": ["activeTab", "scripting"],
"action": {
"default_popup": "popup.html",
"default_title": "Style Inspector"
}
}
Loading