feat: add custom CSS save system with dual-editor interface
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 16s
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 16s
Implement complete custom CSS management system: - Separate base CSS (readonly) and custom CSS (editable) - Save custom CSS to Kirby backend per narrative - Visual save button with state indicators (dirty/saving/success/error) - CSRF-protected API endpoint for CSS operations - Dual-editor StylesheetViewer (base + custom with edit mode toggle) - Auto-format custom CSS with Prettier on edit mode exit Backend changes: - Add web2print Kirby plugin with POST/GET routes - Add customCss field to narrative blueprint - Add CSRF token meta tag in header - Include customCss and modified timestamps in JSON template - Install code-editor plugin for Kirby panel Frontend changes: - Refactor stylesheet store with baseCss/customCss refs - Make content a computed property (baseCss + customCss) - Add helper methods: replaceBlock, replaceInCustomCss, setCustomCss - Update all components to use new store API - Create SaveButton component with FAB design - Redesign StylesheetViewer with collapsable sections - Initialize store from narrative data on app mount File changes: - Rename stylesheet.css → stylesheet.print.css - Update all references to new filename Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
4d1183d1af
commit
0f46618066
32 changed files with 1207 additions and 89 deletions
|
|
@ -354,10 +354,7 @@ const updateMargins = () => {
|
|||
`$1${marginValue}`
|
||||
);
|
||||
|
||||
stylesheetStore.content = stylesheetStore.content.replace(
|
||||
currentBlock,
|
||||
updatedBlock
|
||||
);
|
||||
stylesheetStore.replaceBlock(currentBlock, updatedBlock);
|
||||
};
|
||||
|
||||
// Watch margin values (number inputs) with debounce
|
||||
|
|
@ -398,19 +395,13 @@ const updateBackground = () => {
|
|||
/(background:\s*)[^;]+/,
|
||||
`$1${background.value.value}`
|
||||
);
|
||||
stylesheetStore.content = stylesheetStore.content.replace(
|
||||
currentBlock,
|
||||
updatedBlock
|
||||
);
|
||||
stylesheetStore.replaceBlock(currentBlock, updatedBlock);
|
||||
} else {
|
||||
const updatedBlock = currentBlock.replace(
|
||||
/(\s*})$/,
|
||||
` background: ${background.value.value};\n$1`
|
||||
);
|
||||
stylesheetStore.content = stylesheetStore.content.replace(
|
||||
currentBlock,
|
||||
updatedBlock
|
||||
);
|
||||
stylesheetStore.replaceBlock(currentBlock, updatedBlock);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -457,7 +448,7 @@ watch(runningTitle, (enabled) => {
|
|||
});
|
||||
|
||||
const updatePageFooters = () => {
|
||||
let currentCss = stylesheetStore.content;
|
||||
let currentCss = stylesheetStore.customCss;
|
||||
|
||||
// Remove existing @page:left and @page:right rules
|
||||
currentCss = currentCss.replace(/@page:left\s*\{[^}]*\}/g, '');
|
||||
|
|
@ -539,7 +530,7 @@ const updatePageFooters = () => {
|
|||
currentCss.slice(insertPosition);
|
||||
}
|
||||
|
||||
stylesheetStore.content = currentCss;
|
||||
stylesheetStore.setCustomCss(currentCss);
|
||||
};
|
||||
|
||||
const syncFromStore = () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue