mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
demo reupload plus translations and pdf editor cleanups, test amd64
This commit is contained in:
parent
e8d8aa8f46
commit
a5e21bc35c
2
.github/workflows/push-docker-demo.yml
vendored
2
.github/workflows/push-docker-demo.yml
vendored
@ -76,6 +76,6 @@ jobs:
|
|||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
|
build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
|
||||||
platforms: linux/amd64,linux/arm64/v8
|
platforms: linux/amd64
|
||||||
provenance: true
|
provenance: true
|
||||||
sbom: true
|
sbom: true
|
||||||
|
|||||||
@ -5285,5 +5285,111 @@
|
|||||||
"offline": "Backend Offline",
|
"offline": "Backend Offline",
|
||||||
"starting": "Backend starting up...",
|
"starting": "Backend starting up...",
|
||||||
"wait": "Please wait for the backend to finish launching and try again."
|
"wait": "Please wait for the backend to finish launching and try again."
|
||||||
|
},
|
||||||
|
"pdfTextEditor": {
|
||||||
|
"title": "PDF JSON Editor",
|
||||||
|
"imageLabel": "Placed image",
|
||||||
|
"pageSummary": "Page {{number}} of {{total}}",
|
||||||
|
"currentFile": "Current file: {{name}}",
|
||||||
|
"pagePreviewAlt": "Page preview",
|
||||||
|
"noTextOnPage": "No editable text was detected on this page.",
|
||||||
|
"empty": {
|
||||||
|
"title": "No document loaded",
|
||||||
|
"subtitle": "Load a PDF or JSON file to begin editing text content."
|
||||||
|
},
|
||||||
|
"pageType": {
|
||||||
|
"sparse": "Sparse text"
|
||||||
|
},
|
||||||
|
"badges": {
|
||||||
|
"unsaved": "Edited",
|
||||||
|
"modified": "Edited",
|
||||||
|
"earlyAccess": "Early Access"
|
||||||
|
},
|
||||||
|
"actions": {
|
||||||
|
"reset": "Reset Changes",
|
||||||
|
"downloadJson": "Download JSON",
|
||||||
|
"generatePdf": "Generate PDF"
|
||||||
|
},
|
||||||
|
"fontAnalysis": {
|
||||||
|
"details": "Font Details",
|
||||||
|
"embedded": "Embedded",
|
||||||
|
"type": "Type",
|
||||||
|
"webFormat": "Web Format",
|
||||||
|
"warnings": "Warnings",
|
||||||
|
"suggestions": "Notes",
|
||||||
|
"currentPageFonts": "Fonts on this page",
|
||||||
|
"allFonts": "All fonts",
|
||||||
|
"fallback": "fallback",
|
||||||
|
"missing": "missing",
|
||||||
|
"perfect": "perfect",
|
||||||
|
"subset": "subset",
|
||||||
|
"perfectMessage": "All fonts are perfectly matched",
|
||||||
|
"warningMessage": "Some fonts may render differently",
|
||||||
|
"infoMessage": "Font information"
|
||||||
|
},
|
||||||
|
"manual": {
|
||||||
|
"resizeHandle": "Adjust text width"
|
||||||
|
},
|
||||||
|
"modeChange": {
|
||||||
|
"title": "Confirm Mode Change",
|
||||||
|
"warning": "Changing the text grouping mode will reset all unsaved changes. Are you sure you want to continue?",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"confirm": "Reset and Change Mode"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"autoScaleText": {
|
||||||
|
"title": "Auto-scale text to fit boxes",
|
||||||
|
"description": "Automatically scales text horizontally to fit within its original bounding box when font rendering differs from PDF."
|
||||||
|
},
|
||||||
|
"groupingMode": {
|
||||||
|
"title": "Text Grouping Mode",
|
||||||
|
"autoDescription": "Automatically detects page type and groups text appropriately.",
|
||||||
|
"paragraphDescription": "Groups aligned lines into multi-line paragraph text boxes."
|
||||||
|
},
|
||||||
|
"manualGrouping": {
|
||||||
|
"descriptionInline": "Tip: Hold Ctrl (Cmd) or Shift to multi-select text boxes. A floating toolbar will appear above the selection so you can merge, ungroup, or adjust widths."
|
||||||
|
},
|
||||||
|
"forceSingleElement": {
|
||||||
|
"title": "Lock edited text to a single PDF element",
|
||||||
|
"description": "When enabled, the editor exports each edited text box as one PDF text element to avoid overlapping glyphs or mixed fonts."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"groupingMode": {
|
||||||
|
"auto": "Auto",
|
||||||
|
"paragraph": "Paragraph",
|
||||||
|
"singleLine": "Single Line"
|
||||||
|
},
|
||||||
|
"disclaimer": {
|
||||||
|
"heading": "Preview Limitations",
|
||||||
|
"textFocus": "This workspace focuses on editing text and repositioning embedded images. Complex page artwork, form widgets, and layered graphics are preserved for export but are not fully editable here.",
|
||||||
|
"previewVariance": "Some visuals (such as table borders, shapes, or annotation appearances) may not display exactly in the preview. The exported PDF keeps the original drawing commands whenever possible.",
|
||||||
|
"alpha": "This alpha viewer is still evolving—certain fonts, colours, transparency effects, and layout details may shift slightly. Please double-check the generated PDF before sharing."
|
||||||
|
},
|
||||||
|
"welcomeBanner": {
|
||||||
|
"title": "Welcome to PDF Text Editor (Early Access)",
|
||||||
|
"experimental": "This is an experimental feature in active development. Expect some instability and issues during use.",
|
||||||
|
"howItWorks": "This tool converts your PDF to an editable format where you can modify text content and reposition images. Changes are saved back as a new PDF.",
|
||||||
|
"bestFor": "Works Best With:",
|
||||||
|
"bestFor1": "Simple PDFs containing primarily text and images",
|
||||||
|
"bestFor2": "Documents with standard paragraph formatting",
|
||||||
|
"bestFor3": "Letters, essays, reports, and basic documents",
|
||||||
|
"notIdealFor": "Not Ideal For:",
|
||||||
|
"notIdealFor1": "PDFs with special formatting like bullet points, tables, or multi-column layouts",
|
||||||
|
"notIdealFor2": "Magazines, brochures, or heavily designed documents",
|
||||||
|
"notIdealFor3": "Instruction manuals with complex layouts",
|
||||||
|
"limitations": "Current Limitations:",
|
||||||
|
"limitation1": "Font rendering may differ slightly from the original PDF",
|
||||||
|
"limitation2": "Complex graphics, form fields, and annotations are preserved but not editable",
|
||||||
|
"limitation3": "Large files may take time to convert and process",
|
||||||
|
"knownIssues": "Known Issues (Being Fixed):",
|
||||||
|
"issue1": "Text colour is not currently preserved (will be added soon)",
|
||||||
|
"issue2": "Paragraph mode has more alignment and spacing issues - Single Line mode recommended",
|
||||||
|
"issue3": "The preview display differs from the exported PDF - exported PDFs are closer to the original",
|
||||||
|
"issue4": "Rotated text alignment may need manual adjustment",
|
||||||
|
"issue5": "Transparency and layering effects may vary from original",
|
||||||
|
"feedback": "This is an early access feature. Please report any issues you encounter to help us improve!",
|
||||||
|
"gotIt": "Got it",
|
||||||
|
"dontShowAgain": "Don't show again"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2084,7 +2084,8 @@ const selectionToolbarPosition = useMemo(() => {
|
|||||||
const isActive = activeGroupId === group.id || editingGroupId === group.id;
|
const isActive = activeGroupId === group.id || editingGroupId === group.id;
|
||||||
const isEditing = editingGroupId === group.id;
|
const isEditing = editingGroupId === group.id;
|
||||||
const baseFontSize = group.fontMatrixSize ?? group.fontSize ?? 12;
|
const baseFontSize = group.fontMatrixSize ?? group.fontSize ?? 12;
|
||||||
const fontSizePx = Math.max(baseFontSize * scale, 6);
|
// Reduce font size by ~2% to account for browser rendering differences and prevent wrapping
|
||||||
|
const fontSizePx = Math.max(baseFontSize * scale * 0.98, 6);
|
||||||
const effectiveFontId = resolveFontIdForIndex(pageGroupIndex) ?? group.fontId;
|
const effectiveFontId = resolveFontIdForIndex(pageGroupIndex) ?? group.fontId;
|
||||||
const fontFamily = getFontFamily(effectiveFontId, group.pageIndex);
|
const fontFamily = getFontFamily(effectiveFontId, group.pageIndex);
|
||||||
let lineHeightPx = getLineHeightPx(effectiveFontId, group.pageIndex, fontSizePx);
|
let lineHeightPx = getLineHeightPx(effectiveFontId, group.pageIndex, fontSizePx);
|
||||||
@ -2154,9 +2155,12 @@ const selectionToolbarPosition = useMemo(() => {
|
|||||||
const fontWeight = group.fontWeight || getFontWeight(effectiveFontId, group.pageIndex);
|
const fontWeight = group.fontWeight || getFontWeight(effectiveFontId, group.pageIndex);
|
||||||
|
|
||||||
// Determine text wrapping behavior based on whether text has been changed
|
// Determine text wrapping behavior based on whether text has been changed
|
||||||
|
// Only wrap if: it's a multi-line paragraph, width extended, or text changed
|
||||||
|
// Don't wrap single lines just because we're in paragraph mode
|
||||||
const hasChanges = changed;
|
const hasChanges = changed;
|
||||||
const widthExtended = resolvedWidth - baseWidth > 0.5;
|
const widthExtended = resolvedWidth - baseWidth > 0.5;
|
||||||
const enableWrap = isParagraphLayout || widthExtended || isEditing || hasChanges;
|
const isMultiLineParagraph = isParagraphLayout && lineCount > 1;
|
||||||
|
const enableWrap = isMultiLineParagraph || widthExtended || hasChanges;
|
||||||
const whiteSpace = enableWrap ? 'pre-wrap' : 'pre';
|
const whiteSpace = enableWrap ? 'pre-wrap' : 'pre';
|
||||||
const wordBreak = enableWrap ? 'break-word' : 'normal';
|
const wordBreak = enableWrap ? 'break-word' : 'normal';
|
||||||
const overflowWrap = enableWrap ? 'break-word' : 'normal';
|
const overflowWrap = enableWrap ? 'break-word' : 'normal';
|
||||||
@ -2169,7 +2173,7 @@ const selectionToolbarPosition = useMemo(() => {
|
|||||||
// We need to add this to the container width to compensate, so the inner content
|
// We need to add this to the container width to compensate, so the inner content
|
||||||
// has the full PDF-defined width available for text
|
// has the full PDF-defined width available for text
|
||||||
// Add extra padding to prevent text from being too tight and wrapping prematurely
|
// Add extra padding to prevent text from being too tight and wrapping prematurely
|
||||||
const WRAPPER_HORIZONTAL_PADDING = 10;
|
const WRAPPER_HORIZONTAL_PADDING = 15;
|
||||||
|
|
||||||
const containerStyle: React.CSSProperties = {
|
const containerStyle: React.CSSProperties = {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@ -2301,6 +2305,7 @@ const selectionToolbarPosition = useMemo(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const textScale = textScales.get(group.id) ?? 1;
|
const textScale = textScales.get(group.id) ?? 1;
|
||||||
|
// Apply scale when needed to prevent text overflow, even when editing
|
||||||
const shouldScale = autoScaleText && textScale < 0.98;
|
const shouldScale = autoScaleText && textScale < 0.98;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -2333,7 +2338,8 @@ const selectionToolbarPosition = useMemo(() => {
|
|||||||
data-text-content
|
data-text-content
|
||||||
style={{
|
style={{
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
display: enableWrap ? 'inline' : 'inline-block',
|
// Keep inline-block even when wrapping to maintain scaleX transform
|
||||||
|
display: 'inline-block',
|
||||||
transform: shouldScale ? `scaleX(${textScale})` : 'none',
|
transform: shouldScale ? `scaleX(${textScale})` : 'none',
|
||||||
transformOrigin: 'left center',
|
transformOrigin: 'left center',
|
||||||
whiteSpace,
|
whiteSpace,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user