ai-pp3
Version:
CLI tool combining multimodal AI analysis with RawTherapee's engine to generate optimized PP3 profiles for RAW photography
156 lines • 4.57 kB
JavaScript
/**
* PP3 file format parser with search/replace block handling and direct section/attribute changes
*/
function createInitialState() {
return {
isInSearch: false,
isInReplace: false,
currentBlock: { search: [], replace: [] },
};
}
function createDirectChangeState() {
return {
isInCodeBlock: false,
currentSection: "",
sections: [],
};
}
function handleSearchStart(state) {
state.isInSearch = true;
state.isInReplace = false;
state.currentBlock = { search: [], replace: [] };
}
function handleSeparator(state) {
state.isInSearch = false;
state.isInReplace = true;
}
function handleReplaceEnd(state, blocks) {
state.isInSearch = false;
state.isInReplace = false;
if (state.currentBlock.search.length > 0 &&
state.currentBlock.replace.length > 0) {
blocks.push({
search: state.currentBlock.search.join("\n"),
replace: state.currentBlock.replace.join("\n"),
});
}
}
function handleContentLine(line, state) {
if (state.isInSearch)
state.currentBlock.search.push(line);
if (state.isInReplace)
state.currentBlock.replace.push(line);
}
export function parseSearchReplaceBlocks(text) {
const blocks = [];
const state = createInitialState();
for (const line of text.split("\n")) {
if (line.startsWith("<<<<<<< SEARCH")) {
handleSearchStart(state);
}
else if (line.startsWith("=======")) {
handleSeparator(state);
}
else if (line.startsWith(">>>>>>> REPLACE")) {
handleReplaceEnd(state, blocks);
}
else {
handleContentLine(line, state);
}
}
return blocks;
}
/**
* Parses direct section/attribute changes from AI response
* @param text - The AI response text
* @returns Array of section changes
*/
export function parseDirectSectionChanges(text) {
const state = createDirectChangeState();
// Extract content to process (from code blocks or full text)
const contentToProcess = extractContentToProcess(text);
// Process the content line by line
processContentLines(contentToProcess, state);
return state.sections;
}
/**
* Extracts content to process from text, prioritizing code blocks
*/
function extractContentToProcess(text) {
const codeBlocks = extractCodeBlocks(text);
// If no code blocks found, use the entire text
return codeBlocks.length > 0 ? codeBlocks.join("\n") : text;
}
/**
* Extracts code blocks from text
*/
function extractCodeBlocks(text) {
const codeBlockRegex = /```([\s\S]*?)```/g;
const codeBlocks = [];
let match;
while ((match = codeBlockRegex.exec(text)) !== null) {
if (match[1]) {
codeBlocks.push(match[1].trim());
}
}
return codeBlocks;
}
/**
* Processes content lines and updates the state
*/
function processContentLines(content, state) {
let currentSectionChange = null;
for (const line of content.split("\n")) {
const trimmedLine = line.trim();
// Skip empty lines
if (!trimmedLine)
continue;
if (isSectionHeader(trimmedLine)) {
// Finalize previous section if exists
if (currentSectionChange) {
state.sections.push(currentSectionChange);
}
// Start a new section
const sectionName = trimmedLine.slice(1, -1);
currentSectionChange = createNewSectionChange(sectionName);
}
else if (isParameterLine(trimmedLine) && currentSectionChange) {
processParameterLine(trimmedLine, currentSectionChange);
}
}
// Add the last section if we were processing one
if (currentSectionChange) {
state.sections.push(currentSectionChange);
}
}
/**
* Checks if a line is a section header
*/
function isSectionHeader(line) {
return line.startsWith("[") && line.endsWith("]");
}
/**
* Checks if a line is a parameter line
*/
function isParameterLine(line) {
return line.includes("=");
}
/**
* Creates a new section change object
*/
function createNewSectionChange(sectionName) {
return {
sectionName,
parameters: new Map(),
};
}
/**
* Processes a parameter line and adds it to the section change
*/
function processParameterLine(line, sectionChange) {
const [parameterName] = line.split("=");
if (parameterName) {
sectionChange.parameters.set(parameterName, line);
}
}
//# sourceMappingURL=pp3-parser.js.map