reload custom css
This commit is contained in:
parent
9c58edb425
commit
b544928a65
7 changed files with 115 additions and 39 deletions
|
|
@ -161,7 +161,7 @@
|
|||
|
||||
.element-selected {
|
||||
outline: 2px dashed #7136ff !important;
|
||||
background-color: #7136ff1a !important;
|
||||
/* background-color: #7136ff1a !important; */
|
||||
}
|
||||
|
||||
.element-hover-label {
|
||||
|
|
|
|||
|
|
@ -31,21 +31,30 @@ body {
|
|||
}
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
font-size: 22px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 38px;
|
||||
font-size: 28px;
|
||||
line-height: 38px;
|
||||
background: rgba(255, 255, 255, 0.521);
|
||||
background: rgba(60, 143, 66, 0.52);
|
||||
padding-top: 10px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 20px;
|
||||
margin-top: 60px;
|
||||
margin-bottom: 30px;
|
||||
font-family: "Montserrat";
|
||||
font-family: "EB Garamond";
|
||||
font-weight: normal;
|
||||
margin-right: 0mm;
|
||||
margin-left: 0mm;
|
||||
color: rgb(224, 9, 9);
|
||||
border-style: solid;
|
||||
border-color: #e01b1b;
|
||||
border-width: 3px;
|
||||
text-align: right;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
em {
|
||||
|
|
@ -68,6 +77,54 @@ a {
|
|||
color: #0000ee;
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
h5 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 20px;
|
||||
background: #dedede;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 20px;
|
||||
border-width: 2px;
|
||||
font-weight: bold;
|
||||
border-style: dotted;
|
||||
border-color: #000000;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 38px;
|
||||
border-width: 2px;
|
||||
font-weight: bold;
|
||||
border-style: solid;
|
||||
border-color: #000000;
|
||||
padding-top: 20px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 20px;
|
||||
padding-left: 20px;
|
||||
margin-top: 36px;
|
||||
}
|
||||
|
||||
p.author {
|
||||
font-size: 24px;
|
||||
background: rgba(255, 255, 255, 0.521);
|
||||
font-weight: bold;
|
||||
padding-top: 10px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 20px;
|
||||
margin-top: 20px;
|
||||
margin-right: 0px;
|
||||
margin-bottom: 0px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
----
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ import { useKeyboardShortcuts } from './composables/useKeyboardShortcuts';
|
|||
import { useIframeInteractions } from './composables/useIframeInteractions';
|
||||
import { usePreviewRenderer } from './composables/usePreviewRenderer';
|
||||
import { usePrintPreview } from './composables/usePrintPreview';
|
||||
import { useProjectFonts } from './composables/useProjectFonts';
|
||||
|
||||
const stylesheetStore = useStylesheetStore();
|
||||
const narrativeStore = useNarrativeStore();
|
||||
const { loadFontsFromCss } = useProjectFonts();
|
||||
|
||||
const previewFrame1 = ref(null);
|
||||
const previewFrame2 = ref(null);
|
||||
|
|
@ -86,6 +88,8 @@ onMounted(async () => {
|
|||
// Initialize stylesheet with custom CSS
|
||||
if (narrativeStore.data) {
|
||||
await stylesheetStore.initializeFromNarrative(narrativeStore.data);
|
||||
// Pre-load any fonts referenced in the saved CSS so @font-face rules are ready for the preview
|
||||
await loadFontsFromCss(stylesheetStore.customCss);
|
||||
}
|
||||
|
||||
// Render preview after data is loaded
|
||||
|
|
|
|||
|
|
@ -228,7 +228,9 @@ export function useElementSettings({ margin, padding, basePopup }) {
|
|||
removeProps(['color']);
|
||||
stylesheetStore.updateProperty('body', 'color', textDefaults.color);
|
||||
} else if (group === 'font') {
|
||||
removeProps(['font-family', 'font-style', 'font-weight']);
|
||||
removeProps(['font-family', 'font-style']);
|
||||
// Write font-weight: normal explicitly so applyDefaultsCss() won't re-apply bold defaults on reload
|
||||
stylesheetStore.updateProperty(selector.value, 'font-weight', 'normal');
|
||||
const fontVal = textDefaults.fontFamily === 'sans-serif' ? 'sans-serif' : `"${textDefaults.fontFamily}"`;
|
||||
stylesheetStore.updateProperty('body', 'font-family', fontVal);
|
||||
}
|
||||
|
|
@ -422,36 +424,14 @@ export function useElementSettings({ margin, padding, basePopup }) {
|
|||
|
||||
const specialGroupDiffersFromDefault = (group, parsed) => {
|
||||
switch (group) {
|
||||
case 'font': {
|
||||
if ('font-family' in parsed) {
|
||||
const val = parsed['font-family'].split(',')[0].trim().replace(/['"]/g, '');
|
||||
if (val !== textDefaults.fontFamily) return true;
|
||||
}
|
||||
if ('font-style' in parsed && parsed['font-style'].trim() === 'italic') return true;
|
||||
if ('font-weight' in parsed) {
|
||||
const v = parsed['font-weight'].trim();
|
||||
if (v === 'bold' || parseInt(v) >= 700) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case 'fontSize': {
|
||||
if ('font-size' in parsed) {
|
||||
const m = parsed['font-size'].match(/([\d.]+)(px|rem|em|mm|cm|in)?/);
|
||||
if (m) return parseFloat(m[1]) !== textDefaults.fontSize.value || (m[2] || 'px') !== textDefaults.fontSize.unit;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case 'lineHeight': {
|
||||
if ('line-height' in parsed) {
|
||||
const m = parsed['line-height'].match(/([\d.]+)(px|rem|em|mm|cm|in)?/);
|
||||
if (m) return parseFloat(m[1]) !== textDefaults.lineHeight.value || (m[2] || 'px') !== textDefaults.lineHeight.unit;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case 'color': {
|
||||
if ('color' in parsed) return parsed['color'].trim() !== textDefaults.color;
|
||||
return false;
|
||||
}
|
||||
case 'font':
|
||||
return 'font-family' in parsed || 'font-style' in parsed || 'font-weight' in parsed;
|
||||
case 'fontSize':
|
||||
return 'font-size' in parsed;
|
||||
case 'lineHeight':
|
||||
return 'line-height' in parsed;
|
||||
case 'color':
|
||||
return 'color' in parsed;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
|
@ -734,6 +714,13 @@ export function useElementSettings({ margin, padding, basePopup }) {
|
|||
|
||||
loadValuesFromStylesheet(true);
|
||||
|
||||
// If no session state, sync toggles from custom CSS block (handles page reload with saved CSS)
|
||||
// Uses extractCustomBlock (not extractBlock) to avoid activating toggles for base stylesheet rules
|
||||
if (!stored) {
|
||||
const cssBlock = stylesheetStore.extractCustomBlock(selector.value);
|
||||
if (cssBlock) syncRefsFromCss(cssBlock);
|
||||
}
|
||||
|
||||
if (stored && stored.values) {
|
||||
if (settingEnabled.font) {
|
||||
fontFamily.value = stored.values.fontFamily;
|
||||
|
|
|
|||
|
|
@ -134,6 +134,19 @@ async function loadFont(fontName) {
|
|||
stylesheetStore.setFontFaceCss(loadedFontsCss.value);
|
||||
}
|
||||
|
||||
async function loadFontsFromCss(css) {
|
||||
if (!css) return;
|
||||
const matches = css.matchAll(/font-family:\s*["']?([^"';,\n]+)["']?/gi);
|
||||
const names = new Set();
|
||||
for (const m of matches) {
|
||||
const name = m[1].trim().replace(/['"]/g, '');
|
||||
if (name && name !== 'sans-serif' && name !== 'serif' && name !== 'monospace') {
|
||||
names.add(name);
|
||||
}
|
||||
}
|
||||
await Promise.all([...names].map((name) => loadFont(name)));
|
||||
}
|
||||
|
||||
async function loadAllFontPreviews() {
|
||||
// Only loads fonts into document.fonts for select preview — does NOT update the stylesheet store
|
||||
const promises = fonts
|
||||
|
|
@ -148,6 +161,7 @@ export function useProjectFonts() {
|
|||
fonts,
|
||||
loadFont,
|
||||
loadAllFontPreviews,
|
||||
loadFontsFromCss,
|
||||
loadedFontsCss,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,6 +116,11 @@ export const useStylesheetStore = defineStore('stylesheet', () => {
|
|||
return cssParsingUtils.extractCssBlock(baseCss.value, selector);
|
||||
};
|
||||
|
||||
// Extract block only from custom CSS (used for toggle activation on load)
|
||||
const extractCustomBlock = (selector) => {
|
||||
return cssParsingUtils.extractCssBlock(customCss.value, selector);
|
||||
};
|
||||
|
||||
// Replace a CSS block in custom CSS (handles blocks from base CSS too)
|
||||
const replaceBlock = (oldBlock, newBlock) => {
|
||||
// Check if the old block exists in custom CSS
|
||||
|
|
@ -369,6 +374,7 @@ export const useStylesheetStore = defineStore('stylesheet', () => {
|
|||
updateProperty,
|
||||
extractValue,
|
||||
extractBlock,
|
||||
extractCustomBlock,
|
||||
replaceBlock,
|
||||
replaceInCustomCss,
|
||||
setCustomCss,
|
||||
|
|
|
|||
|
|
@ -6,12 +6,20 @@ const extractCssBlock = (css, selector) => {
|
|||
|
||||
const extractCssValue = (css, selector, property) => {
|
||||
const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const regex = new RegExp(
|
||||
// Try numeric with unit first
|
||||
const numericRegex = new RegExp(
|
||||
`${escaped}\\s*{[^}]*${property}:\\s*([\\d.]+)(px|rem|em|mm|cm|in)`,
|
||||
'i'
|
||||
);
|
||||
const match = css.match(regex);
|
||||
return match ? { value: parseFloat(match[1]), unit: match[2] } : null;
|
||||
const numericMatch = css.match(numericRegex);
|
||||
if (numericMatch) return { value: parseFloat(numericMatch[1]), unit: numericMatch[2] };
|
||||
// Fallback: any string value (colors, keywords, font names, etc.)
|
||||
const stringRegex = new RegExp(
|
||||
`${escaped}\\s*\\{[^}]*?${property}:\\s*([^;}\\n]+)`,
|
||||
'i'
|
||||
);
|
||||
const stringMatch = css.match(stringRegex);
|
||||
return stringMatch ? stringMatch[1].trim() : null;
|
||||
};
|
||||
|
||||
const updateCssValue = ({ css, selector, property, value, unit }) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue