feat: update Material Symbols font and add automation scripts

- Updated Material Symbols to latest version with complete icon set
- Added `update-font.mjs` script for automated future font updates
- Added `deploy.mjs` script with proper error handling
- Fixed potential null pointer in font update logic
- Bumped version and restored repository URL
This commit is contained in:
Cristoph Berane 2026-02-26 20:55:54 +01:00 committed by GitHub
parent 78f795c5ed
commit 75c6e4ea55
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 177 additions and 6 deletions

3
.gitignore vendored
View file

@ -21,3 +21,6 @@ data.json
# Exclude macOS Finder (System Explorer) View States
.DS_Store
/package-lock.json
# Deploy directory
deploy/

42
deploy.mjs Normal file
View file

@ -0,0 +1,42 @@
#!/usr/bin/env node
import { execSync } from 'child_process';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const deployDir = path.join(__dirname, 'deploy');
const files = ['manifest.json', 'main.js', 'styles.css'];
// 1. Ensure deploy/ exists (create or reuse)
fs.mkdirSync(deployDir, { recursive: true });
// 2. Install dependencies
console.log('Installing dependencies...');
execSync('npm install', { stdio: 'inherit', cwd: __dirname });
// 3. Update Material Symbols font
console.log('\nUpdating Material Symbols font...');
execSync('node update-font.mjs', { stdio: 'inherit', cwd: __dirname });
// 4. Run the production build
console.log('\nRunning npm run build...');
execSync('npm run build', { stdio: 'inherit', cwd: __dirname });
// 5. Copy deployment files
console.log('\nCopying files to deploy/...');
for (const file of files) {
const srcPath = path.join(__dirname, file);
const destPath = path.join(deployDir, file);
if (!fs.existsSync(srcPath)) {
console.error(`Error: Expected source file not found: ${srcPath}`);
console.error('Deployment aborted. Ensure the build has produced all required files.');
process.exit(1);
}
fs.copyFileSync(srcPath, destPath);
console.log(`Copied ${file} → deploy/${file}`);
}
console.log('\n✓ Full deployment complete. Files are in deploy/');

View file

@ -1,10 +1,10 @@
{
"id": "material-symbols",
"name": "Material Symbols",
"version": "0.1.0",
"version": "1.0.0",
"minAppVersion": "0.15.0",
"description": "This plugin adds the material symbols (outlined) to obsidian",
"author": "Cristoph Berane",
"authorUrl": "https://www.berane-it.de",
"authorUrl": "https://github.com/cberane/obsidian-material-symbols",
"isDesktopOnly": false
}
}

File diff suppressed because one or more lines are too long

125
update-font.mjs Executable file
View file

@ -0,0 +1,125 @@
#!/usr/bin/env node
import https from 'https';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Fetch URL with a modern User-Agent to get woff2 format
function fetchUrl(url, userAgent = null) {
return new Promise((resolve, reject) => {
const options = {
headers: userAgent ? { 'User-Agent': userAgent } : {},
};
https.get(url, options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(data);
} else {
reject(new Error(`HTTP ${res.statusCode}: ${url}`));
}
});
}).on('error', reject);
});
}
// Fetch binary data (for woff2 font file)
function fetchBinary(url) {
return new Promise((resolve, reject) => {
https.get(url, (res) => {
const chunks = [];
res.on('data', (chunk) => {
chunks.push(chunk);
});
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(Buffer.concat(chunks));
} else {
reject(new Error(`HTTP ${res.statusCode}: ${url}`));
}
});
}).on('error', reject);
});
}
// Extract woff2 URL from CSS
function extractWoff2Url(css) {
// Match url() declarations in @font-face blocks
const match = css.match(/url\((https:\/\/fonts\.gstatic\.com\/[^)]+\.woff2)\)/g);
if (!match || match.length === 0) {
throw new Error('No woff2 URL found in Google Fonts CSS');
}
// Take the last one (largest/most complete subset) or any - for variable icon font they're all the same
const lastMatch = match[match.length - 1];
const urlMatch = lastMatch.match(/url\((https:\/\/fonts\.gstatic\.com\/[^)]+\.woff2)\)/);
if (!urlMatch || urlMatch.length < 2) {
throw new Error('No woff2 URL found in Google Fonts CSS');
}
return urlMatch[1];
}
// Main update function
async function updateFont() {
try {
console.log('Fetching Google Fonts CSS for Material Symbols Outlined...');
// Step 1: Fetch the Google Fonts CSS with modern User-Agent
const css = await fetchUrl(
'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
);
// Step 2: Parse the woff2 URL
const woff2Url = extractWoff2Url(css);
console.log(`Found woff2 URL: ${woff2Url}`);
// Step 3: Download the woff2 font binary
console.log('Downloading woff2 font...');
const fontBinary = await fetchBinary(woff2Url);
console.log(`Downloaded ${fontBinary.length} bytes`);
// Step 4: Base64-encode the binary
const base64 = fontBinary.toString('base64');
console.log(`Base64 encoded: ${base64.length} characters`);
// Step 5: Replace the src in styles.css
const stylesPath = path.join(__dirname, 'styles.css');
console.log(`Reading ${stylesPath}...`);
let stylesContent = fs.readFileSync(stylesPath, 'utf-8');
// Replace the src declaration inside @font-face
// Target: src: url(data:application/octet-stream;base64,...) or variations with format()
const srcRegex = /src:\s*url\(data:(?:font\/woff2;base64|application\/octet-stream;base64),[^)]+\)(?:\s*format\([^)]*\))?[^;]*;/;
if (!srcRegex.test(stylesContent)) {
throw new Error('Could not find src declaration in styles.css');
}
const newSrc = `src: url(data:application/octet-stream;base64,${base64}) format('woff2');`;
stylesContent = stylesContent.replace(srcRegex, newSrc);
console.log('Writing updated styles.css...');
fs.writeFileSync(stylesPath, stylesContent, 'utf-8');
console.log('✓ Font update completed successfully!');
console.log(`✓ Updated base64 size: ${base64.length} characters (original ~3MB woff2 file)`);
} catch (error) {
console.error('✗ Error updating font:', error.message);
process.exit(1);
}
}
updateFont();

View file

@ -1,3 +1,4 @@
{
"0.1.0": "0.15.0"
}
"0.1.0": "0.15.0",
"1.0.0": "0.15.0"
}