awesome-copilot/yaml-parser.js
Jeremiah Snee afc0705b11
Collections Improvement with Tasks Collection POC (#270)
* add yaml block support

* Add usage Section to Collections

* new edge ai tasks collection with usage example from PR
https://github.com/github/awesome-copilot/pull/159

* Update collections/edge-ai-tasks.collection.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update collections/edge-ai-tasks.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update collections/edge-ai-tasks.collection.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update collections/edge-ai-tasks.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fixing some bugs in the update script

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Aaron Powell <me@aaron-powell.com>
2025-10-08 11:36:06 +11:00

169 lines
5.6 KiB
JavaScript

// Simple YAML parser for collection files
const fs = require("fs");
function safeFileOperation(operation, filePath, defaultValue = null) {
try {
return operation();
} catch (error) {
console.error(`Error processing file ${filePath}: ${error.message}`);
return defaultValue;
}
}
function parseCollectionYaml(filePath) {
return safeFileOperation(
() => {
const content = fs.readFileSync(filePath, "utf8");
const lines = content.split("\n");
const result = {};
let currentKey = null;
let currentArray = null;
let currentObject = null;
const readLiteralBlock = (startIndex, parentIndent) => {
const blockLines = [];
let blockIndent = null;
let index = startIndex;
for (; index < lines.length; index++) {
const rawLine = lines[index];
const trimmedLine = rawLine.trimEnd();
const contentOnly = trimmedLine.trim();
const lineIndent = rawLine.length - rawLine.trimLeft().length;
if (contentOnly === "" && blockIndent === null) {
// Preserve leading blank lines inside the literal block
blockLines.push("");
continue;
}
if (contentOnly !== "" && lineIndent <= parentIndent) {
break;
}
if (contentOnly === "") {
blockLines.push("");
continue;
}
if (blockIndent === null) {
blockIndent = lineIndent;
}
blockLines.push(rawLine.slice(blockIndent));
}
return {
content: blockLines.join("\n").replace(/\r/g, "").trimEnd(),
nextIndex: index - 1,
};
};
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#")) continue;
const leadingSpaces = line.length - line.trimLeft().length;
// Handle array items starting with -
if (trimmed.startsWith("- ")) {
if (currentKey === "items") {
if (!currentArray) {
currentArray = [];
result[currentKey] = currentArray;
}
// Parse item object
const item = {};
currentArray.push(item);
currentObject = item;
// Handle inline properties on same line as -
const restOfLine = trimmed.substring(2).trim();
if (restOfLine) {
const colonIndex = restOfLine.indexOf(":");
if (colonIndex > -1) {
const key = restOfLine.substring(0, colonIndex).trim();
const value = restOfLine.substring(colonIndex + 1).trim();
item[key] = value;
}
}
} else if (currentKey === "tags") {
if (!currentArray) {
currentArray = [];
result[currentKey] = currentArray;
}
const value = trimmed.substring(2).trim();
currentArray.push(value);
}
}
// Handle key-value pairs
else if (trimmed.includes(":")) {
const colonIndex = trimmed.indexOf(":");
const key = trimmed.substring(0, colonIndex).trim();
let value = trimmed.substring(colonIndex + 1).trim();
if (leadingSpaces === 0) {
// Top-level property
currentKey = key;
currentArray = null;
currentObject = null;
if (value) {
// Handle array format [item1, item2, item3]
if (value.startsWith("[") && value.endsWith("]")) {
const arrayContent = value.slice(1, -1);
if (arrayContent.trim()) {
result[key] = arrayContent.split(",").map(item => item.trim());
} else {
result[key] = [];
}
currentKey = null; // Reset since we handled the array
} else if (value === "|" || value === ">") {
const { content: blockContent, nextIndex } = readLiteralBlock(i + 1, leadingSpaces);
result[key] = blockContent;
i = nextIndex;
} else {
result[key] = value;
}
} else if (key === "items" || key === "tags") {
// Will be populated by array items
result[key] = [];
currentArray = result[key];
} else if (key === "display") {
result[key] = {};
currentObject = result[key];
}
} else if (currentObject && leadingSpaces > 0) {
// Property of current object (e.g., display properties)
if (value === "|" || value === ">") {
const { content: blockContent, nextIndex } = readLiteralBlock(i + 1, leadingSpaces);
currentObject[key] = blockContent;
i = nextIndex;
} else {
currentObject[key] = value === "true" ? true : value === "false" ? false : value;
}
} else if (currentArray && currentObject && leadingSpaces > 2) {
// Property of array item object
if (value === "|" || value === ">") {
const { content: blockContent, nextIndex } = readLiteralBlock(i + 1, leadingSpaces);
currentObject[key] = blockContent;
i = nextIndex;
} else {
currentObject[key] = value;
}
}
}
}
return result;
},
filePath,
null
);
}
module.exports = { parseCollectionYaml, safeFileOperation };