filteredTags() {
// Assumes each tag has a property 'family' with a 'name'
return this.tags.filter(tag => tag.family && tag.family.name === this.font);
+ },
+ lintErrors() {
+ return this.$root.gf.linter(this.$root.gf.lintRules, this.font, this.filteredTags);
}
},
methods: {
<button @click="removeTag(tag)">Remove</button>
</li>
</ul>
+
+ <ul>
+ <li v-for="error in lintErrors" :key="error.description" :class="{ 'tag-error': error.severity === 'ERROR', 'tag-warn': error.severity === 'WARN', 'tag-fail': error.severity === 'FAIL', 'tag-info': error.severity === 'INFO' }">
+ {{ error.description }}
+ </li>
+ </ul>
</div>
`
};
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
+ <link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app">
import Panel from "./Panel.js";
import TagView from "./TagView.js";
import AddTag from "./AddTag.js";
+ import { linter } from "./linter.js";
Vue.component('tags-by-font', TagsByFont);
Vue.component('tags-by-categories', TagsByCategories);
// Load the GF and Tags classes
this.gf = new GF();
await this.gf.getFamilyData();
+ await this.gf.getLintRules();
this.gf.loadFamilies();
+ this.gf.linter = linter;
this.tags = new Tags(this.gf);
this.tags.items = this.tags.items;
this.$root.$on("remove-tag", this.removeTag);
constructor() {
this.familyData = {};
this.families = [];
+ this.lintRules = [];
}
async getFamilyData() {
let data = await loadText('family_data.json');
this.familyData[family.family] = family;
});
}
+ async getLintRules() {
+ let data = await loadText('tag_rules.csv');
+ const lines = data.split('\n');
+ for (let line of lines) {
+ if (line.startsWith('#') || line.trim() === '') {
+ continue;
+ }
+ let [rule, severity, description] = line.split(',');
+ description = description.replace(/^"(.*)"$/, '$1');
+ if (!rule || !description || !severity) {
+ console.warn("Skipping line due to missing fields:", line);
+ continue;
+ }
+ this.lintRules.push({
+ rule: rule.trim(),
+ description: description.trim(),
+ severity: severity.trim()
+ });
+ }
+ }
loadFamilies() {
for (let familyName in this.familyData) {
const axes = []
--- /dev/null
+body {
+ font-family: sans-serif;
+ margin: 0;
+}
+
+.tag-error { background-color: #f88f7e; padding: 2px; }
+.tag-warn { color: #c0a007; }
+.tag-fail { color: #c02007; }
+.tag-info { color: #007ac0; }
\ No newline at end of file