Skip to content

Instantly share code, notes, and snippets.

@lepinkainen
Created August 19, 2025 08:33
Show Gist options
  • Save lepinkainen/828f495eee3ba3fce3b7726a179c861b to your computer and use it in GitHub Desktop.
Save lepinkainen/828f495eee3ba3fce3b7726a179c861b to your computer and use it in GitHub Desktop.
Create a colour based on note name
module.exports = async (params) => {
const { app } = params;
const file = app.workspace.getActiveFile();
if (!file) return;
// Only run for Markdown files
if (!file.name.endsWith(".md")) return;
// Read full note text
let content = await app.vault.read(file);
// Hash → deterministic muted hex color for backgrounds
function stringToColor(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
// Generate muted colors by constraining RGB values to a narrower, lighter range
let color = "#";
for (let i = 0; i < 3; i++) {
// Get base value from hash
const rawValue = (hash >> (i * 8)) & 0xff;
// Map to muted range: 160-220 (instead of 0-255) for softer colors
const mutedValue = 160 + (rawValue % 61);
color += ("00" + mutedValue.toString(16)).slice(-2);
}
return '"' + color + '"';
}
// Check if a cover value is an image link/URL
function isImageLink(coverValue) {
if (!coverValue) return false;
// Remove quotes and whitespace
const cleanValue = coverValue.replace(/['"]/g, "").trim();
// Check for common image extensions
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|svg|webp)$/i;
if (imageExtensions.test(cleanValue)) return true;
// Check for URLs (http/https)
if (/^https?:\/\//.test(cleanValue)) return true;
// Check for Obsidian internal links [[filename]]
if (/^\[\[.*\]\]$/.test(cleanValue)) return true;
// Check for markdown image syntax ![alt](url)
if (/^!\[.*\]\(.*\)$/.test(cleanValue)) return true;
return false;
}
const title = file.basename.trim();
const newColor = stringToColor(title);
// Ensure frontmatter exists
if (!/^---/.test(content)) {
content = `---\ncover: ${newColor}\n---\n\n${content}`;
} else if (/^cover: .*/m.test(content)) {
// Check if existing cover is an image link before replacing
const existingCoverMatch = content.match(/^cover: (.*)$/m);
if (existingCoverMatch && !isImageLink(existingCoverMatch[1])) {
// Only replace if it's not an image link
content = content.replace(/^cover: .*/m, `cover: ${newColor}`);
}
// If it is an image link, don't replace it
} else {
// Insert cover into frontmatter block
content = content.replace(
/^---([\s\S]*?)---/,
(match, inner) => `---${inner}\ncover: ${newColor}\n---`
);
}
await app.vault.modify(file, content);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment