diff --git a/.changeset/thick-buckets-agree.md b/.changeset/thick-buckets-agree.md
new file mode 100644
index 0000000..0c0ee4e
--- /dev/null
+++ b/.changeset/thick-buckets-agree.md
@@ -0,0 +1,8 @@
+---
+"ec-lang-logo": minor
+---
+
+Allows for automatic color change from `#fff` to `#000` when the code block is shown with a light theme.
+This is achieved by looking at the `html[data-theme]` value.
+
+Also adds another `color` option: `theme` takes the standard code foreground color and applies it to the language logo.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..80cf856
--- /dev/null
+++ b/README.md
@@ -0,0 +1,90 @@
+# Language Logo Plugin For Expressive Code
+
+A plugin for Expressive Code that adds language logos (coming from [Simple Icons](https://simpleicons.org)) to code blocks.
+
+## Examples
+
+
+
+
+
+For more examples, see [my blog post](http://blog.dertimonius.dev/posts/til-38).
+
+## Installation
+
+```bash
+npm install ec-lang-logo
+# pnpm install ec-lang-logo
+# bun install ec-lang-logo
+# yarn add ec-lang-logo
+```
+
+## Usage
+
+Add the plugin to your Expressive Code configuration:
+
+```js
+import { defineConfig } from 'astro/config';
+import { pluginLanguageLogo } from 'ec-lang-logo';
+
+export default defineConfig({
+ integrations: [
+ starlight({
+ expressiveCode: {
+ plugins: [pluginLanguageLogo()],
+ },
+ }),
+ ],
+});
+```
+
+## Configuration
+
+The plugin accepts an optional configuration object:
+
+```ts
+pluginLanguageLogo({
+ color: 'mono', // 'mono' | 'original' | 'theme' | '#hexcolor'
+ excludedLangs: [], // Array of language identifiers to exclude
+})
+```
+
+### Options
+
+- `color`: Controls the badge color
+ - `'mono'`: Adapts to theme (white for dark, black for light)
+ - `'original'`: Uses the official language brand color
+ - `'theme'`: Takes the code foreground color of the currently active theme
+ - `'#hexcolor'`: Custom hex color (e.g., `'#ff0000'`)
+- `excludedLangs`: Array of language identifiers where badges should not appear
+
+## Per-Block Customization
+
+You can override settings for individual code blocks using meta attributes:
+
+```md
+```js badge-color="#ff0000"
+// Custom red badge
+```
+
+```md
+```js badge-color="original"
+// Shows the official brand color
+```
+
+```md
+```ts hide-badge
+// No badge on this block
+```
+
+```
+
+### Available Meta Attributes
+
+- `badge-color="value"`: Override the badge color for this block (takes the same values as the overall options)
+- `hide-badge`: Hide the badge for this block
+
+## Theme Support
+
+The plugin automatically adapts mono-colored badges to your site's theme. Ensure your theme switcher uses `data-theme="light"` or `data-theme="dark"` on the `html` element.
+
diff --git a/assets/light.png b/assets/light.png
new file mode 100644
index 0000000..8003b23
Binary files /dev/null and b/assets/light.png differ
diff --git a/assets/original.png b/assets/original.png
new file mode 100644
index 0000000..cda13d1
Binary files /dev/null and b/assets/original.png differ
diff --git a/assets/plain.png b/assets/plain.png
new file mode 100644
index 0000000..1d51172
Binary files /dev/null and b/assets/plain.png differ
diff --git a/src/index.ts b/src/index.ts
index 9de43bd..2873092 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -27,6 +27,8 @@ const LANGUAGE_MAP = {
yml: { icon: icons.siYaml },
yaml: { icon: icons.siYaml },
json: { icon: icons.siJson },
+ graphql: { icon: icons.siGraphql },
+ gql: { icon: icons.siGraphql },
html: { icon: icons.siHtml5 },
css: { icon: icons.siCss },
@@ -47,8 +49,10 @@ const LANGUAGE_MAP = {
type Language = keyof typeof LANGUAGE_MAP;
+type Color = 'mono' | 'original' | 'theme' | (`#${string}` & {});
+
interface PluginOptions {
- color: 'mono' | 'original' | (`#${string}` & {});
+ color: Color;
excludedLangs: Language[];
}
@@ -63,6 +67,14 @@ export function pluginLanguageLogo(config?: PluginOptions) {
return definePlugin({
name: 'Language Logo',
baseStyles: `
+ html[data-theme=light] {
+ --ec-lang-logo: #000;
+ }
+
+ html[data-theme=dark] {
+ --ec-lang-logo: #eee;
+ }
+
.ec-lang-logo {
position: absolute;
width: 48px;
@@ -77,7 +89,7 @@ export function pluginLanguageLogo(config?: PluginOptions) {
pointer-events: none;
z-index: 10;
}
- [data-small=true] {
+ [data-ec-logo-small=true] {
width: 32px;
height: 32px;
bottom: 0.8rem;
@@ -106,16 +118,17 @@ export function pluginLanguageLogo(config?: PluginOptions) {
if (!foundLang) {
return;
}
-
const loc = codeBlock.getLines().length;
const icon = foundLang.icon;
- const color = colorMatch ? colorMatch[1] || colorMatch[2] : opts.color;
+ const color = colorMatch
+ ? ((colorMatch[1] || colorMatch[2]) as Color)
+ : opts.color;
const logoSvg = h(
'div',
{
class: 'ec-lang-logo',
- 'data-small': loc === 1 ? 'true' : undefined,
+ 'data-ec-logo-small': loc === 1 ? 'true' : undefined,
},
[
h(
@@ -125,12 +138,7 @@ export function pluginLanguageLogo(config?: PluginOptions) {
viewBox: '0 0 24 24',
width: loc === 1 ? '24px' : '32px',
height: loc === 1 ? '24px' : '32px',
- fill:
- color === 'mono'
- ? '#fff'
- : color === 'original'
- ? `#${icon.hex}`
- : color,
+ fill: getFillColor(color, icon.hex),
},
[
h('title', { innerHtml: icon.title }),
@@ -147,3 +155,16 @@ export function pluginLanguageLogo(config?: PluginOptions) {
},
});
}
+
+function getFillColor(color: Color, iconHex: string): string {
+ if (color === 'mono') {
+ return 'var(--ec-lang-logo)';
+ }
+ if (color === 'theme') {
+ return 'var(--ec-codeFg)';
+ }
+ if (color === 'original') {
+ return `#${iconHex}`;
+ }
+ return color;
+}