Add icon comment generation with categories and tags to PR validation workflow (#1444)
* Add 'generate-icons-comment' script to package.json and update PR validation workflow to include icon generation and commenting steps. * Refactor icon comment generation to include inline SVGs in markdown tables and update workflow to handle output correctly. * Refactor icon comment generation to use base64 data URIs for SVGs in markdown tables, improving compatibility and visual representation. * Refactor icon comment generation to use GitHub raw file URLs instead of base64 data URIs, enhancing compatibility with GitHub comments. * Update icon size in markdown table for improved visibility in GitHub comments. * Enhance icon comment generation by adding category and tags to markdown table, improving organization and metadata visibility. * Implement category validation for new icons and consolidate helper imports in icon generation scripts. * Add workflow step to remove comment with added icons if no icons are present * Remove unused SVG icon file 'a-b-2 copy 2.svg' to clean up the icon directory. * Update PR validation workflow to change icon comment mode from 'recreate' to 'upsert', allowing for more efficient comment updates. * Update icon name in markdown table to include file extension for clarity in generated comments. * Remove unused SVG icon file 'a-b-2 copy.svg' to streamline the icon directory.
This commit is contained in:
parent
e7f40a1500
commit
6d5f43d993
|
|
@ -0,0 +1,104 @@
|
|||
import { execSync } from 'child_process'
|
||||
import { basename, join } from 'path'
|
||||
import { ICONS_SRC_DIR, parseMatter } from './helpers.mjs'
|
||||
|
||||
// Check icon files added relative to main branch (for PR)
|
||||
function getAddedIconsFromMain() {
|
||||
try {
|
||||
const output = execSync('git diff origin/main...HEAD --name-status', { encoding: 'utf-8' })
|
||||
const addedIcons = []
|
||||
|
||||
output.split('\n').forEach(line => {
|
||||
if (line.startsWith('A\t')) {
|
||||
const filePath = line.substring(2)
|
||||
// Filter only SVG files from icons/outline/ or icons/filled/ directories
|
||||
if (filePath.match(/^icons\/(outline|filled)\/.+\.svg$/)) {
|
||||
const iconPath = filePath.replace(/^icons\//, '')
|
||||
addedIcons.push(iconPath)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return addedIcons
|
||||
} catch (error) {
|
||||
// Fallback: check relative to HEAD if origin/main doesn't exist
|
||||
try {
|
||||
const output = execSync('git diff --diff-filter=A --name-only', { encoding: 'utf-8' })
|
||||
const addedIcons = []
|
||||
|
||||
output.split('\n').forEach(filePath => {
|
||||
if (filePath && filePath.match(/^icons\/(outline|filled)\/.+\.svg$/)) {
|
||||
const iconPath = filePath.replace(/^icons\//, '')
|
||||
addedIcons.push(iconPath)
|
||||
}
|
||||
})
|
||||
|
||||
return addedIcons
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get GitHub raw file URL for icon
|
||||
function getIconRawUrl(iconPath) {
|
||||
const repo = process.env.GITHUB_REPOSITORY || 'tabler/tabler-icons'
|
||||
const ref = process.env.GITHUB_HEAD_REF || process.env.GITHUB_SHA || 'main'
|
||||
return `https://raw.githubusercontent.com/${repo}/${ref}/icons/${iconPath}`
|
||||
}
|
||||
|
||||
// Generate markdown table for icons
|
||||
function generateIconsTable(icons, type) {
|
||||
if (icons.length === 0) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const typeName = type === 'outline' ? 'Outline' : 'Filled'
|
||||
let markdown = `### ${typeName} Icons (${icons.length})\n\n`
|
||||
markdown += `| Icon | Name | Category | Tags |\n`
|
||||
markdown += `|------|------|------|------|\n`
|
||||
|
||||
icons.forEach(iconPath => {
|
||||
const iconName = basename(iconPath, '.svg')
|
||||
const rawUrl = getIconRawUrl(iconPath)
|
||||
|
||||
const { data } = parseMatter(join(ICONS_SRC_DIR, iconPath))
|
||||
const category = data.category || ''
|
||||
const tags = data.tags || []
|
||||
|
||||
// Use GitHub raw file URL - GitHub Comments support external image URLs
|
||||
markdown += `| <img src="${rawUrl}" width="240" height="240" alt="${iconName}" /> | \`${iconName}.svg\` | ${category || '❌ No category'} | ${tags.join(', ') || '❌ No tags' } |\n`
|
||||
})
|
||||
markdown += `\n`
|
||||
|
||||
return markdown
|
||||
}
|
||||
|
||||
// Generate markdown comment with table of added icons
|
||||
function generateIconsComment(icons) {
|
||||
if (icons.length === 0) {
|
||||
return ''
|
||||
}
|
||||
|
||||
// Group icons by type (outline/filled) with full paths
|
||||
const outlineIcons = icons.filter(icon => icon.startsWith('outline/'))
|
||||
const filledIcons = icons.filter(icon => icon.startsWith('filled/'))
|
||||
|
||||
let markdown = `## 📦 Added Icons\n\n`
|
||||
markdown += `This PR adds **${icons.length}** new icon${icons.length > 1 ? 's' : ''}.\n\n`
|
||||
|
||||
markdown += generateIconsTable(outlineIcons, 'outline')
|
||||
markdown += generateIconsTable(filledIcons, 'filled')
|
||||
|
||||
return markdown
|
||||
}
|
||||
|
||||
const addedIcons = getAddedIconsFromMain()
|
||||
|
||||
if (addedIcons.length > 0) {
|
||||
const comment = generateIconsComment(addedIcons)
|
||||
console.log(comment)
|
||||
} else {
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
|
|
@ -20,6 +20,50 @@ export const strokes = {
|
|||
400: 2,
|
||||
}
|
||||
|
||||
export const categories = [
|
||||
'Animals',
|
||||
'Arrows',
|
||||
'Badges',
|
||||
'Brand',
|
||||
'Buildings',
|
||||
'Charts',
|
||||
'Communication',
|
||||
'Computers',
|
||||
'Currencies',
|
||||
'Database',
|
||||
'Design',
|
||||
'Development',
|
||||
'Devices',
|
||||
'Document',
|
||||
'E-commerce',
|
||||
'Electrical',
|
||||
'Extensions',
|
||||
'Food',
|
||||
'Games',
|
||||
'Gender',
|
||||
'Gestures',
|
||||
'Health',
|
||||
'Laundry',
|
||||
'Letters',
|
||||
'Logic',
|
||||
'Map',
|
||||
'Math',
|
||||
'Media',
|
||||
'Mood',
|
||||
'Nature',
|
||||
'Numbers',
|
||||
'Photography',
|
||||
'Shapes',
|
||||
'Sport',
|
||||
'Symbols',
|
||||
'System',
|
||||
'Text',
|
||||
'Vehicles',
|
||||
'Version control',
|
||||
'Weather',
|
||||
'Zodiac'
|
||||
]
|
||||
|
||||
export const iconTemplate = (type) =>
|
||||
type === 'outline'
|
||||
? `<svg
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { globSync } from 'glob'
|
||||
import fs from 'fs'
|
||||
import { basename } from 'path'
|
||||
import { HOME_DIR, ICONS_SRC_DIR, iconTemplate, parseMatter, types, getArgvs } from './helpers.mjs'
|
||||
import { HOME_DIR, ICONS_SRC_DIR, iconTemplate, parseMatter, types, getArgvs, categories } from './helpers.mjs'
|
||||
import { join } from 'path'
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
|
|
@ -216,6 +216,17 @@ for (const icon of addedIcons) {
|
|||
error = true
|
||||
}
|
||||
|
||||
// check if outline icon has category
|
||||
if (icon.match(/^outline\//) && !data.category) {
|
||||
console.log(`⛔️ New icon \`${icon}\` has no category`)
|
||||
error = true
|
||||
} else {
|
||||
if (!categories.includes(data.category)) {
|
||||
console.log(`⛔️ New icon \`${icon}\` has invalid category \`${data.category}\`. Valid categories are: ${categories.join(', ')}`)
|
||||
error = true
|
||||
}
|
||||
}
|
||||
|
||||
// check if filled icon hasnt category
|
||||
if (icon.match(/^filled\//) && data.category) {
|
||||
console.log(`⛔️ New icon \`${icon}\` has category, but should not have it`)
|
||||
|
|
|
|||
|
|
@ -61,4 +61,33 @@ jobs:
|
|||
with:
|
||||
file-path: ./comment-markup.md
|
||||
comment-tag: validate
|
||||
mode: recreate
|
||||
mode: recreate
|
||||
|
||||
- name: Generate icons comment
|
||||
id: generate-icons-comment
|
||||
run: pnpm run --silent generate-icons-comment > ./comment-icons.md || true
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check if icons were added
|
||||
id: check-icons
|
||||
run: |
|
||||
if [ -s ./comment-icons.md ]; then
|
||||
echo "has_icons=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "has_icons=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Comment PR with added icons
|
||||
if: steps.check-icons.outputs.has_icons == 'true'
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
file-path: ./comment-icons.md
|
||||
comment-tag: added-icons
|
||||
mode: upsert
|
||||
|
||||
- name: Remove comment with added icons
|
||||
if: steps.check-icons.outputs.has_icons == 'false'
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
comment-tag: added-icons
|
||||
mode: delete
|
||||
|
|
@ -49,7 +49,8 @@
|
|||
"build:webfont": "pnpm --filter @tabler/icons-webfont build",
|
||||
"update-readme": "node ./.build/update-readme.mjs",
|
||||
"zip": "node ./.build/zip-files.mjs",
|
||||
"validate-pr": "node ./.build/validate-pr.mjs"
|
||||
"validate-pr": "node ./.build/validate-pr.mjs",
|
||||
"generate-icons-comment": "node ./.build/generate-icons-comment.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@11ty/eleventy": "^2.0.1",
|
||||
|
|
|
|||
Loading…
Reference in New Issue