Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fac44c8
Add flowchart editor, AI drafts, and Markdown step links
Twest2 Nov 8, 2026
e7355f7
Refine description modes and numbered Step toolbar links
Twest2 Nov 8, 2026
598dd19
Polish diagram toolbar, shape tools and canvas zoom
Twest2 Nov 8, 2026
085fcc0
Rebuild flowcharts as a simple feature; restore the image toolbar
Twest2 Nov 8, 2026
4f69f17
Flowcharts: 30 shapes, colors, pictures, resize and Ctrl+wheel zoom
Twest2 Nov 8, 2026
168a38d
Markdown descriptions, image in the Fill menu, grouped shapes, canvas…
Twest2 Nov 8, 2026
9837de8
Description: live links in rich text, resizable boxes, clickable prev…
Twest2 Nov 8, 2026
6d80c9a
Links without https://; keep Markdown sources across renderer changes
Twest2 Nov 8, 2026
dd0fd79
Flowcharts: Mermaid text panel, arrow styles in More shapes, more too…
Twest2 Nov 8, 2026
bfc89c6
Mermaid: a toolbar button and a cleaner side panel
Twest2 Nov 8, 2026
95725fb
Mermaid panel: drag to resize, Code theme syntax colors
Twest2 Nov 8, 2026
8ccc865
Mermaid panel follows side-panel edits; drop the In sync status line
Twest2 Nov 8, 2026
ffa58ca
Flowchart toolbar: zoom out, zoom level (click for 100%), zoom in
Twest2 Nov 8, 2026
7e52bec
Flowchart toolbar: drop the Select button; a second click on a tool t…
Twest2 Nov 8, 2026
46454a1
Flowchart canvas: room to pan and drag shapes left and up, not only r…
Twest2 Nov 8, 2026
100c7b3
Arrange: layered layout (fewer crossings, side inputs and notes place…
Twest2 Nov 8, 2026
87cdf45
package-lock: keep main's libc markers (glibc/musl) so Linux packages…
Twest2 Nov 8, 2026
330db1b
Exports: flowchart blocks on PowerPoint slides; Wiki.js/Confluence pu…
Twest2 Nov 8, 2026
79a40c3
Flowchart background color (white, any color, or transparent); light …
Twest2 Nov 8, 2026
9209256
Flowchart pictures: step saves no longer rejected as oversized ("Coul…
Twest2 Nov 8, 2026
0d3de1b
Flowchart block position: before/after title, description or image, l…
Twest2 Nov 8, 2026
837aa39
Make exported flowchart step links jump to their targets
Twest2 Nov 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion app/confluence.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const fs = require('node:fs');
const path = require('node:path');
const { atomicWriteFileSync, writeJsonSync, readJsonIfExists, escapeXml } = require('../core/util');
const { normalizeServer } = require('./webdav');
const { publishedImageName } = require('../exporters/common');

/*
* Publishing guides as Confluence pages, on Confluence Cloud or a Confluence
Expand Down Expand Up @@ -70,8 +71,9 @@ function pageFromExport(apiDir) {
let body = request.body.storage.value;
const attachmentDir = path.join(apiDir, 'attachments');
const files = fs.existsSync(attachmentDir) ? fs.readdirSync(attachmentDir).sort() : [];
const used = new Set();
const attachments = files.filter((file) => /^\d{3}-.*\.png$/.test(file)).map((file) => {
const name = `step-${file.slice(0, 3)}.png`;
const name = publishedImageName(file, used);
body = body.split(`ri:filename="${escapeXml(file)}"`).join(`ri:filename="${name}"`);
return { name, data: fs.readFileSync(path.join(attachmentDir, file)) };
});
Expand Down
18 changes: 15 additions & 3 deletions app/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const { GuideStore } = require('../core/store');
const { libraryLocationFor } = require('./data-dir');
const { Settings } = require('../core/settings');
const { saveGuideFromEditor, saveStepFromEditor } = require('../core/editor-save');
const flowchartModel = require('../core/flowchart');
const { descriptionToMarkdown, descriptionFromMarkdown } = require('../core/description-markdown');
const { GoogleDrive } = require('./google-drive');
const { OneDrive } = require('./onedrive');
Expand Down Expand Up @@ -828,6 +829,7 @@ function setupIpc() {
});

const IMAGE_BUDGET = 256 * 1024 * 1024; // channels that carry base64 PNGs
const STEP_BUDGET = 2 * (flowchartModel.MAX_CHART_IMAGE_CHARS + 2 * 1024 * 1024); // step:save
const h = (channel, fn, opts = {}) => {
const { maxChars = 2 * 1024 * 1024, validate = null } = opts;
ipcMain.handle(channel, async (event, args = {}) => {
Expand Down Expand Up @@ -939,6 +941,8 @@ function setupIpc() {
// Guide information edits the description as Markdown (core/description-markdown.js).
h('guide:descriptionToMarkdown', ({ html }) => descriptionToMarkdown(html),
{ validate: (a) => c.string(a.html, 2 * 1024 * 1024) });
// Description → Rich text / Markdown: the rich-text description as Markdown to edit.
h('step:descriptionToMarkdown', ({ html }) => descriptionToMarkdown(html), { validate: (a) => c.string(a.html, 2 * 1024 * 1024) });
h('guide:descriptionFromMarkdown', ({ markdown }) => descriptionFromMarkdown(markdown),
{ validate: (a) => c.string(a.markdown, 2 * 1024 * 1024) });
// A new screenshot in the form the store keeps: WebP when the setting asks
Expand Down Expand Up @@ -976,7 +980,11 @@ function setupIpc() {
const saved = saveStepFromEditor(store, guideId, step, baseStep);
reindex(guideId);
return saved;
}, { validate: (a) => c.id(a.guideId) && security.isPlainArgs(a.step) && a.step && c.id(a.step.stepId)
}, {
// The step and the version it was edited from; each may carry a
// flowchart's pictures (core/flowchart.js caps them at 12 MB a chart).
maxChars: STEP_BUDGET,
validate: (a) => c.id(a.guideId) && security.isPlainArgs(a.step) && a.step && c.id(a.step.stepId)
&& (a.baseStep == null || (security.isPlainArgs(a.baseStep) && a.baseStep.stepId === a.step.stepId)) });
h('step:delete', ({ guideId, stepId }) => {
store.deleteStep(guideId, stepId);
Expand Down Expand Up @@ -1047,9 +1055,9 @@ function setupIpc() {
return { ok: true, step };
}, { validate: (a) => c.id(a.guideId) && c.optionalNumber(a.position, 0, 100000) });
// Pick a draft with the import decoder; no step or library file is created.
h('step:pickImage', async () => {
h('step:pickImage', async ({ purpose } = {}) => {
const res = await dialog.showOpenDialog(mainWindow, {
title: t('Choose an image for the new step'),
title: purpose === 'shape' ? t('Choose an image for the shape') : t('Choose an image for the new step'),
filters: [{ name: t('Images'), extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp'] }],
properties: ['openFile'],
});
Expand Down Expand Up @@ -1515,6 +1523,10 @@ function setupIpc() {
h('ai:status', () => textIntel.aiStatus());
// Settings → Branding → Advanced CSS → Write with AI. Nothing is saved: the
// editor shows the CSS for the user to add or discard.
// AI ▾ → Create a flowchart. Nothing is saved: the editor applies it (undoable).
h('ai:flowchart', ({ guideId, request = '' }) => textIntel.generateFlowchart({ guideId, request }), {
validate: (a) => c.id(a.guideId) && (a.request === undefined || c.string(a.request, 1000)),
});
h('ai:brandCss', ({ request, css = '', profile = {} }) => textIntel.generateBrandCss({ request, css, profile }), {
validate: (a) => c.string(a.request, MAX_BRAND_CSS_REQUEST_CHARS) && a.request.trim() !== ''
&& (a.css === undefined || c.string(a.css, MAX_CSS_CHARS))
Expand Down
2 changes: 2 additions & 0 deletions app/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const api = {
importImage: invoke('step:importImage'),
pickImage: invoke('step:pickImage'),
chooseImage: invoke('step:chooseImage'),
descriptionToMarkdown: invoke('step:descriptionToMarkdown'),
retake: invoke('step:retake'),
setImages: invoke('step:setImages'),
},
Expand Down Expand Up @@ -175,6 +176,7 @@ const api = {
cancel: invoke('ai:cancel'),
status: invoke('ai:status'),
brandCss: invoke('ai:brandCss'),
flowchart: invoke('ai:flowchart'),
},
agents: {
setup: invoke('agents:setup'),
Expand Down
Loading
Loading