Skip to content

Commit bf4d6f6

Browse files
committed
29.3.0 release
1 parent 6553caf commit bf4d6f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+9996
-9037
lines changed

.github/workflows/stale.yml

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,29 @@
44
# For more information, see:
55
# https://github.com/actions/stale
66
name: Mark stale issues and pull requests
7+
78
on:
89
schedule:
9-
- cron: '54 14 * * *'
10+
- cron: '42 11 * * *'
11+
1012
jobs:
1113
stale:
14+
1215
runs-on: ubuntu-latest
1316
permissions:
1417
issues: write
1518
pull-requests: write
19+
1620
steps:
17-
- uses: actions/stale@v9
21+
- uses: actions/stale@v5
1822
with:
23+
repo-token: ${{ secrets.GITHUB_TOKEN }}
1924
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. See [the FAQ](https://github.com/jgraph/drawio/wiki/Stale-bot-FAQ) for more information.'
20-
stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. See [the FAQ](https://github.com/jgraph/drawio/wiki/Stale-bot-FAQ) for more information.'
25+
stale-pr-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. See [the FAQ](https://github.com/jgraph/drawio/wiki/Stale-bot-FAQ) for more information.'
2126
stale-issue-label: 'wontfix'
2227
stale-pr-label: 'wontfix'
2328
close-issue-label: 'declined'
24-
days-before-stale: 200
25-
days-before-close: 20
29+
days-before-stale: 250
30+
days-before-close: 30
2631
exempt-issue-labels: notstale
27-
exempt-pr-labels: notstale
28-
operations-per-run: 300
29-
ascending: true
30-
delete-branch: true
32+
exempt-pr-labels: notstale

ChangeLog

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
08-JAN-2026: 29.3.0
2+
3+
- Fixes possible NPE
4+
- Merges built preprod back to dev as PR rather than commit
5+
- Adapts validate actions for PR merge instead of cherry picking
6+
- Fixes possible invalid default parent
7+
- Hides current menu when windows are moved or resized
8+
- Adds layer selection in layers dialog [jgraph/drawio#5408]
9+
- Fixes inconsistent menu order for current layer
10+
- Fixes possible NPE [jgraph/drawio-desktop#2307]
11+
- Adds legacy support for anchor points [jgraph/drawio-desktop#2306]
12+
- Fixes resources for selecting and selected objects in layers
13+
- Adds defaultTextStyle config switch
14+
- Adds autosize for shape picker text [jgraph/drawio#5409]
15+
- Disables legacy anchor points only on unconnected flipped shapes
16+
17+
06-JAN-2026: 29.2.10
18+
19+
- Fixes help link in chat dialog
20+
- Fixed a bug in vsdx importer [DID-17282]
21+
- Improves generate dialog for custom LLMs
22+
- Changes default for desktopAutoSync to true [jgraph/drawio-desktop#2227]
23+
- Uses fonts loader path for MathJax
24+
- Fixes multi-line issue
25+
- Sanitize HTML output in ChatWindow
26+
- Improves layers dialog [jgraph/drawio#5408]
27+
128
19-DEC-2025: 29.2.9
229

330
- Updates MathJax fonts to 4.1.0

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
29.2.9
1+
29.3.0

src/main/webapp/js/app.min.js

Lines changed: 2985 additions & 2978 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/webapp/js/diagramly/Devel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ if (!mxIsElectron)
4848
replace(/%connect-src%/g, 'https://*.dropboxapi.com https://api.trello.com').
4949
replace(/%frame-src%/g, '').
5050
replace(/%style-src%/g, '').
51-
replace(/ /g, ' ') + ' frame-ancestors \'self\' https://teams.microsoft.com https://*.cloud.microsoft;';
51+
replace(/ /g, ' ') + ' frame-ancestors \'self\' https://teams.microsoft.com https://*.cloud.microsoft https://*.sharepoint.com https://*.sharepoint.de;';
5252
console.log('app.diagrams.net:', app_diagrams_net);
5353

5454
var viewer_diagrams_net = hashes.replace(/%script-src%/g, 'https://www.dropbox.com https://api.trello.com https://app.diagrams.net') +

src/main/webapp/js/diagramly/Dialogs.js

Lines changed: 103 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,6 @@ var ParseDialog = function(editorUi, title, defaultType)
17361736

17371737
function insertPlantUmlImage(text, format, data, w, h)
17381738
{
1739-
insertPoint = (mxEvent.isAltDown(evt)) ? insertPoint : graph.getCenterInsertPoint(new mxRectangle(0, 0, w, h));
17401739
var cell = null;
17411740

17421741
graph.getModel().beginUpdate();
@@ -1910,8 +1909,6 @@ var ParseDialog = function(editorUi, title, defaultType)
19101909
if (cells.length > 0)
19111910
{
19121911
var graph = editorUi.editor.graph;
1913-
insertPoint = (mxEvent.isAltDown(evt)) ? insertPoint :
1914-
graph.getCenterInsertPoint(graph.getBoundingBoxFromGeometry(cells, true));
19151912
graph.setSelectionCells(graph.importCells(cells, insertPoint.x, insertPoint.y));
19161913
graph.scrollCellToVisible(graph.getSelectionCell());
19171914
}
@@ -1982,9 +1979,6 @@ var ParseDialog = function(editorUi, title, defaultType)
19821979

19831980
if (cells.length > 0)
19841981
{
1985-
insertPoint = (mxEvent.isAltDown(evt)) ? insertPoint :
1986-
graph.getCenterInsertPoint(graph.getBoundingBoxFromGeometry(cells, true));
1987-
19881982
graph.getModel().beginUpdate();
19891983
try
19901984
{
@@ -2010,7 +2004,8 @@ var ParseDialog = function(editorUi, title, defaultType)
20102004
}
20112005
}
20122006
else
2013-
{
2007+
{
2008+
var lines = text.split('\n');
20142009
var vertices = new Object();
20152010
var cells = [];
20162011

@@ -2119,8 +2114,6 @@ var ParseDialog = function(editorUi, title, defaultType)
21192114
try
21202115
{
21212116
cells = graph.getModel().getChildren(graph.getDefaultParent());
2122-
insertPoint = (mxEvent.isAltDown(evt)) ? insertPoint :
2123-
editorUi.editor.graph.getCenterInsertPoint(graph.getBoundingBoxFromGeometry(cells, true));
21242117
inserted = editorUi.editor.graph.importCells(cells, insertPoint.x, insertPoint.y)
21252118
editorUi.editor.graph.fireEvent(new mxEventObject('cellsInserted', 'cells', inserted));
21262119
}
@@ -8559,13 +8552,14 @@ var ChatWindow = function(editorUi, x, y, w, h)
85598552
typeSelect.style.padding = '5px';
85608553
typeSelect.style.minWidth = '0';
85618554

8555+
var createPublicOption = document.createElement('option');
8556+
85628557
if (typeof mxMermaidToDrawio !== 'undefined' && window.isMermaidEnabled &&
85638558
mxUtils.indexOf(Editor.aiActions, 'createPublic') >= 0)
85648559
{
8565-
var createPublicOption = document.createElement('option');
85668560
createPublicOption.setAttribute('value', 'createPublic');
85678561
mxUtils.write(createPublicOption, mxResources.get('create') +
8568-
' (' + mxResources.get('diagramIsPublic') + ')');
8562+
' (' + mxResources.get('draw.io') + ')');
85698563
typeSelect.appendChild(createPublicOption);
85708564
}
85718565

@@ -8574,6 +8568,14 @@ var ChatWindow = function(editorUi, x, y, w, h)
85748568
var createOption = document.createElement('option');
85758569
var helpOption = document.createElement('option');
85768570

8571+
if (typeof mxMermaidToDrawio !== 'undefined' && window.isMermaidEnabled &&
8572+
mxUtils.indexOf(Editor.aiActions, 'create') >= 0)
8573+
{
8574+
createOption.setAttribute('value', 'create');
8575+
mxUtils.write(createOption, mxResources.get('create'));
8576+
typeSelect.appendChild(createOption);
8577+
}
8578+
85778579
if (mxUtils.indexOf(Editor.aiActions, 'update') >= 0)
85788580
{
85798581
includeOption.setAttribute('value', 'includeCopyOfMyDiagram');
@@ -8585,23 +8587,13 @@ var ChatWindow = function(editorUi, x, y, w, h)
85858587
typeSelect.appendChild(selectionOption);
85868588
}
85878589

8588-
if (typeof mxMermaidToDrawio !== 'undefined' && window.isMermaidEnabled &&
8589-
mxUtils.indexOf(Editor.aiActions, 'create') >= 0)
8590-
{
8591-
createOption.setAttribute('value', 'create');
8592-
mxUtils.write(createOption, mxResources.get('create'));
8593-
typeSelect.appendChild(createOption);
8594-
}
8595-
85968590
if (mxUtils.indexOf(Editor.aiActions, 'assist') >= 0)
85978591
{
85988592
helpOption.setAttribute('value', 'assist');
85998593
mxUtils.write(helpOption, mxResources.get('help'));
86008594
typeSelect.appendChild(helpOption);
86018595
}
86028596

8603-
typeSelect.value = Editor.aiActions[0];
8604-
86058597
// Adds a drop down for selecting the model from Editor.aiModels
86068598
var modelSelect = typeSelect.cloneNode(false);
86078599

@@ -8651,6 +8643,11 @@ var ChatWindow = function(editorUi, x, y, w, h)
86518643

86528644
if (!publicChat)
86538645
{
8646+
if (urlParams['test'] != 1)
8647+
{
8648+
createPublicOption.parentNode.removeChild(createPublicOption);
8649+
}
8650+
86548651
options.appendChild(typeSelect);
86558652

86568653
if (modelSelect.children.length > 1)
@@ -8661,6 +8658,11 @@ var ChatWindow = function(editorUi, x, y, w, h)
86618658
user.appendChild(options);
86628659
}
86638660

8661+
if (typeSelect.children.length > 0)
8662+
{
8663+
typeSelect.value = typeSelect.children[0].value;
8664+
}
8665+
86648666
var ignoreChange = false;
86658667
var lastType = typeSelect.value;
86668668

@@ -8802,7 +8804,10 @@ var ChatWindow = function(editorUi, x, y, w, h)
88028804
editorUi.writeTextToClipboard(prompt, mxUtils.bind(this, function(e)
88038805
{
88048806
editorUi.handleError(e);
8805-
}));
8807+
}), function()
8808+
{
8809+
editorUi.alert(mxResources.get('copiedToClipboard'));
8810+
});
88068811
}));
88078812
buttons.appendChild(btn);
88088813

@@ -8832,19 +8837,59 @@ var ChatWindow = function(editorUi, x, y, w, h)
88328837
waiting.className = 'geSidebar';
88338838
waiting.style.marginTop = '2px';
88348839

8835-
function createError(message)
8840+
function createRetryButton(title)
88368841
{
8837-
var wrapper = document.createElement('div');
8838-
wrapper.style.display = 'flex';
8839-
wrapper.style.alignItems = 'center';
8840-
mxUtils.write(wrapper, mxResources.get('error') + ': ' + message);
8842+
var buttons = document.createElement('div');
8843+
buttons.style.display = 'flex';
88418844

88428845
var btn = document.createElement('img');
88438846
btn.className = 'geAdaptiveAsset geLibraryButton';
88448847
btn.setAttribute('src', Editor.refreshImage);
8845-
btn.setAttribute('title', mxResources.get('tryAgain'));
8848+
btn.setAttribute('title', (title != null) ? title : mxResources.get('tryAgain'));
8849+
buttons.appendChild(btn);
88468850
mxEvent.addListener(btn, 'click', processMessage);
8847-
wrapper.appendChild(btn);
8851+
8852+
return buttons;
8853+
};
8854+
8855+
function parseAIMarkup(text) {
8856+
return mxUtils.htmlEntities(text, false)
8857+
// Headings (consume surrounding newlines)
8858+
.replace(/\n*^##### (.+)$\n*/gm, '<h5>$1</h5>')
8859+
.replace(/\n*^#### (.+)$\n*/gm, '<h4>$1</h4>')
8860+
.replace(/\n*^### (.+)$\n*/gm, '<h3>$1</h3>')
8861+
.replace(/\n*^## (.+)$\n*/gm, '<h2>$1</h2>')
8862+
.replace(/\n*^# (.+)$\n*/gm, '<h1>$1</h1>')
8863+
// Bold
8864+
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
8865+
// Italic
8866+
.replace(/\*(.+?)\*/g, '<em>$1</em>')
8867+
// Inline code
8868+
.replace(/`([^`]+)`/g, '<code>$1</code>')
8869+
};
8870+
8871+
function createDivForText(text)
8872+
{
8873+
var wrapper = document.createElement('div');
8874+
wrapper.style.whiteSpace = 'pre-wrap';
8875+
wrapper.innerHTML = Graph.sanitizeHtml(parseAIMarkup(text));
8876+
8877+
return wrapper;
8878+
};
8879+
8880+
function createError(message)
8881+
{
8882+
var title = mxResources.get('error') + ': ';
8883+
var wrapper = document.createElement('div');
8884+
wrapper.style.whiteSpace = 'pre-wrap';
8885+
8886+
if (message.substring(0, title.length) != title)
8887+
{
8888+
message = title + message;
8889+
}
8890+
8891+
mxUtils.write(wrapper, message);
8892+
wrapper.appendChild(createRetryButton());
88488893

88498894
return wrapper;
88508895
};
@@ -9016,11 +9061,23 @@ var ChatWindow = function(editorUi, x, y, w, h)
90169061

90179062
var handleResponse = mxUtils.bind(this, function(data, prompt)
90189063
{
9064+
var dt = Date.now() - t0;
90199065
EditorUi.debug('EditorUi.ChatWindow.handleResponse',
9020-
'data', data, 'prompt', [prompt],
9021-
'time', Date.now() - t0);
9022-
var cells = (data != null) ? editorUi.stringToCells(data[1]) : null;
9066+
'data', data, 'prompt', [prompt], 'time', dt);
9067+
var cells = null;
90239068

9069+
if (data != null && data.length > 1 && data[1].length > 0)
9070+
{
9071+
try
9072+
{
9073+
cells = editorUi.stringToCells(data[1]);
9074+
}
9075+
catch (e)
9076+
{
9077+
throw new Error(e.toString() + '\n\n' + data[1]);
9078+
}
9079+
}
9080+
90249081
if (cells != null && cells.length > 0)
90259082
{
90269083
var bbox = graph.getBoundingBoxFromGeometry(cells);
@@ -9084,8 +9141,7 @@ var ChatWindow = function(editorUi, x, y, w, h)
90849141

90859142
if (data[0].length > 0)
90869143
{
9087-
mxUtils.write(bubble, data[0]);
9088-
mxUtils.br(bubble);
9144+
bubble.appendChild(createDivForText(data[0]));
90899145
}
90909146

90919147
if (data[1].length > 0)
@@ -9106,6 +9162,11 @@ var ChatWindow = function(editorUi, x, y, w, h)
91069162
bubble.appendChild(item);
91079163
editorUi.sidebar.createItem(cells, prompt, true, true, bbox.width, bbox.height,
91089164
true, true, clickFn, null, null, null, null, null, item);
9165+
9166+
if (!publicChat && type != 'createPublic' && urlParams['test'] == 1)
9167+
{
9168+
item.setAttribute('title', theModel + ' (' + dt + ' ms)');
9169+
}
91099170

91109171
var buttons = document.createElement('div');
91119172
buttons.style.display = 'flex';
@@ -9177,8 +9238,7 @@ var ChatWindow = function(editorUi, x, y, w, h)
91779238

91789239
if (data[2].length > 0)
91799240
{
9180-
mxUtils.br(bubble);
9181-
mxUtils.write(bubble, data[2]);
9241+
bubble.appendChild(createDivForText(data[2]));
91829242
}
91839243
}
91849244
else
@@ -9194,8 +9254,10 @@ var ChatWindow = function(editorUi, x, y, w, h)
91949254
}
91959255
else
91969256
{
9197-
mxUtils.write(bubble, data[0]);
9198-
mxUtils.write(bubble, data[2]);
9257+
bubble.style.whiteSpace = 'pre-wrap';
9258+
bubble.appendChild(createDivForText(data[0]));
9259+
bubble.appendChild(createDivForText(data[2]));
9260+
bubble.appendChild(createRetryButton(mxResources.get('refresh')));
91999261
}
92009262
}
92019263

@@ -9234,7 +9296,7 @@ var ChatWindow = function(editorUi, x, y, w, h)
92349296
}
92359297
});
92369298

9237-
EditorUi.debug('EditorUi.ChatWindow.addMessage', 'url', url,
9299+
EditorUi.debug('EditorUi.ChatWindow.addMessage send', 'url', url,
92389300
'params', params, 'aiModel', aiModel, 'config', config);
92399301

92409302
req.send(mxUtils.bind(this, function(req)
@@ -9249,7 +9311,7 @@ var ChatWindow = function(editorUi, x, y, w, h)
92499311
var result = Editor.executeSimpleJsonPath(response, config.responsePath);
92509312
var text = mxUtils.trim((result.length > 0) ? result[0] : req.getText());
92519313
var mermaid = editorUi.extractMermaidDeclaration(text);
9252-
EditorUi.debug('EditorUi.ChatWindow.addMessage',
9314+
EditorUi.debug('EditorUi.ChatWindow.addMessage response',
92539315
'params', params, 'response', response,
92549316
'text', [text], 'mermaid', [mermaid]);
92559317

@@ -9360,7 +9422,7 @@ var ChatWindow = function(editorUi, x, y, w, h)
93609422
// Adds help icon to title bar
93619423
if (!editorUi.isOffline())
93629424
{
9363-
var icon = editorUi.createHelpIcon('https://github.com/jgraph/drawio/discussions/5387');
9425+
var icon = editorUi.createHelpIcon('https://www.drawio.com/doc/faq/configure-ai-options');
93649426
icon.style.cursor = 'help';
93659427
icon.style.opacity = '0.5';
93669428
this.window.buttons.insertBefore(icon, this.window.buttons.firstChild);

0 commit comments

Comments
 (0)