Skip to content

Commit 5d9571b

Browse files
committed
29.2.6 release
1 parent 0f3317f commit 5d9571b

28 files changed

+3018
-2923
lines changed

ChangeLog

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
08-DEC-2025: 29.2.6
2+
3+
- Changes edit icon naming clash caused by [jgraph/drawio#5375]
4+
5+
08-DEC-2025: 29.2.5
6+
7+
- Fixes anchor points for flipped shapes [jgraph/drawio#5341]
8+
9+
04-DEC-2025: 29.2.4
10+
11+
- Adds edit icon for local .html files [jgraph/drawio#5375]
12+
13+
02-DEC-2025: 29.2.3
14+
15+
- Minor UI fixes
16+
117
01-DEC-2025: 29.2.2
218

319
- AI and licensing tuning

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
29.2.2
1+
29.2.6

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

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

src/main/webapp/js/bootstrap.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,14 +313,14 @@ else
313313
});
314314
});
315315
}
316-
else if (!supportedDomain || navigator.onLine)
316+
else if (!supportedDomain)
317317
{
318318
mxscript('js/PostConfig.js');
319319
}
320320
});
321321
};
322322

323-
if (!supportedDomain || mxIsElectron || navigator.onLine)
323+
if (!supportedDomain || mxIsElectron)
324324
{
325325
mxscript('js/PreConfig.js', loadAppJS);
326326
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ if (!mxIsElectron)
1818
'https://api.github.com https://raw.githubusercontent.com https://gitlab.com ' +
1919
'https://graph.microsoft.com https://my.microsoftpersonalcontent.com https://*.sharepoint.com https://*.sharepoint.de ' +
2020
'https://*.1drv.com https://api.onedrive.com https://dl.dropboxusercontent.com https://api.openai.com ' +
21-
'https://*.google.com https://fonts.gstatic.com https://fonts.googleapis.com; ' +
21+
'https://*.google.com https://fonts.gstatic.com https://fonts.googleapis.com https://api.anthropic.com; ' +
2222
'img-src * data: blob:; media-src * data:; font-src * data:; ' +
2323
// www.draw.io required for browser data migration to app.diagrams.net and
2424
// viewer.diagrams.net required for iframe embed preview

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

Lines changed: 100 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ var EmbedDialog = function(editorUi, result, timeout, ignoreSize, previewFn, tit
683683
text.style.wordBreak = 'break-all';
684684
text.style.marginTop = '10px';
685685
text.style.resize = 'none';
686-
text.style.height = '150px';
686+
text.style.height = '180px';
687687
text.style.width = '440px';
688688
text.style.border = '1px solid gray';
689689
text.value = mxResources.get('updatingDocument');
@@ -723,10 +723,8 @@ var EmbedDialog = function(editorUi, result, timeout, ignoreSize, previewFn, tit
723723

724724
var previewBtn = null;
725725

726-
// Loads forever in IE9
727726
if (EmbedDialog.showPreviewOption && !mxIsElectron &&
728-
(!mxClient.IS_CHROMEAPP || validUrl) && !navigator.standalone && (validUrl ||
729-
(mxClient.IS_SVG && (document.documentMode == null || document.documentMode > 9))))
727+
!navigator.standalone && validUrl)
730728
{
731729
previewBtn = mxUtils.button((previewTitle != null) ? previewTitle :
732730
mxResources.get((result.length < maxSize) ? 'preview' : 'openInNewWindow'), function()
@@ -796,17 +794,14 @@ var EmbedDialog = function(editorUi, result, timeout, ignoreSize, previewFn, tit
796794
buttons.appendChild(previewBtn);
797795
}
798796

799-
if (!validUrl || result.length > 7500)
797+
var downloadBtn = mxUtils.button(mxResources.get('export'), function()
800798
{
801-
var downloadBtn = mxUtils.button(mxResources.get(mxIsElectron ? 'save' : 'download'), function()
802-
{
803-
editorUi.hideDialog();
804-
editorUi.saveData((filename != null) ? filename : 'embed.txt', 'txt', result, 'text/plain');
805-
});
806-
807-
downloadBtn.className = 'geBtn';
808-
buttons.appendChild(downloadBtn);
809-
}
799+
editorUi.hideDialog();
800+
editorUi.saveData((filename != null) ? filename : 'embed.txt', 'txt', result, 'text/plain');
801+
});
802+
803+
downloadBtn.className = 'geBtn';
804+
buttons.appendChild(downloadBtn);
810805

811806
if (!editorUi.isOffline() && result.length < maxSize)
812807
{
@@ -8606,7 +8601,8 @@ var ChatWindow = function(editorUi, x, y, w, h)
86068601
var value = Editor.gptModels[key];
86078602

86088603
if ((value.substring(0, 4) == 'gpt-' && Editor.gptApiKey != null) ||
8609-
(value.substring(0, 7) == 'gemini-' && Editor.geminiApiKey != null))
8604+
(value.substring(0, 7) == 'gemini-' && Editor.geminiApiKey != null) ||
8605+
(value.substring(0, 7) == 'claude-' && Editor.claudeApiKey != null))
86108606
{
86118607
var modelOption = document.createElement('option');
86128608
modelOption.setAttribute('value', value);
@@ -8885,31 +8881,38 @@ var ChatWindow = function(editorUi, x, y, w, h)
88858881
'instruction in your response.';
88868882
}
88878883

8888-
messages.push({'role': 'system', 'content': systemInstruction});
8889-
messages.push({'role': 'user', 'content': thePrompt});
8890-
8891-
var params = (theModel.substring(0, 7) == 'gemini-') ?
8884+
messages.push({role: (theModel.substring(0, 4) == 'gpt-') ?
8885+
'system' : 'assistant', content: systemInstruction});
8886+
messages.push({role: 'user', content: thePrompt});
8887+
8888+
var params = null;
8889+
8890+
if (theModel.substring(0, 7) == 'gemini-')
88928891
{
8893-
"system_instruction": {
8894-
"parts": [
8895-
{
8896-
"text": systemInstruction
8897-
}
8898-
]
8899-
},
8900-
"contents": [
8901-
{
8902-
"parts": [
8903-
{
8904-
"text": thePrompt
8905-
}
8906-
]
8907-
}
8908-
]
8909-
} : {
8910-
model: theModel,
8911-
messages: messages
8912-
};
8892+
params = {
8893+
system_instruction: {
8894+
parts: [{text: systemInstruction}]
8895+
},
8896+
contents: [{
8897+
parts: [{text: thePrompt}
8898+
]}]
8899+
};
8900+
}
8901+
else if (theModel.substring(0, 7) == 'claude-')
8902+
{
8903+
params = {
8904+
max_tokens: 8192,
8905+
model: theModel,
8906+
messages: messages
8907+
};
8908+
}
8909+
else
8910+
{
8911+
params = {
8912+
model: theModel,
8913+
messages: messages
8914+
};
8915+
}
89138916

89148917
var processMessage = mxUtils.bind(this, function()
89158918
{
@@ -9068,23 +9071,26 @@ var ChatWindow = function(editorUi, x, y, w, h)
90689071
buttons.appendChild(btn);
90699072
mxEvent.addListener(btn, 'click', processMessage);
90709073

9071-
btn = btn.cloneNode();
9072-
btn.setAttribute('src', Editor.shareImage);
9073-
btn.setAttribute('title', mxResources.get(!editorUi.isStandaloneApp() ?
9074-
'openInNewWindow' : 'export'));
9075-
buttons.appendChild(btn);
9076-
9077-
mxEvent.addListener(btn, 'click', mxUtils.bind(this, function(evt)
9074+
if (editorUi.getServiceName() == 'draw.io')
90789075
{
9079-
if (!editorUi.isStandaloneApp())
9080-
{
9081-
editorUi.editor.editAsNew(data[1]);
9082-
}
9083-
else
9076+
btn = btn.cloneNode();
9077+
btn.setAttribute('src', Editor.shareImage);
9078+
btn.setAttribute('title', mxResources.get(!editorUi.isStandaloneApp() ?
9079+
'openInNewWindow' : 'export'));
9080+
buttons.appendChild(btn);
9081+
9082+
mxEvent.addListener(btn, 'click', mxUtils.bind(this, function(evt)
90849083
{
9085-
editorUi.saveData('export.xml', 'xml', data[1], 'text/xml');
9086-
}
9087-
}));
9084+
if (!editorUi.isStandaloneApp())
9085+
{
9086+
editorUi.editor.editAsNew(data[1]);
9087+
}
9088+
else
9089+
{
9090+
editorUi.saveData('export.xml', 'xml', data[1], 'text/xml');
9091+
}
9092+
}));
9093+
}
90889094

90899095
btn = btn.cloneNode();
90909096
btn.setAttribute('src', Editor.magnifyImage);
@@ -9168,9 +9174,22 @@ var ChatWindow = function(editorUi, x, y, w, h)
91689174
handleError(e);
91699175
});
91709176

9171-
var url = theModel.substring(0, 7) == 'gemini-' ?
9172-
'https://generativelanguage.googleapis.com/v1beta/models/' + theModel +
9173-
':generateContent' : Editor.gptUrl;
9177+
var url = null;
9178+
9179+
if (theModel.substring(0, 7) == 'gemini-')
9180+
{
9181+
url = 'https://generativelanguage.googleapis.com/v1beta/models/' + theModel +
9182+
':generateContent'
9183+
}
9184+
else if (theModel.substring(0, 7) == 'claude-')
9185+
{
9186+
url = 'https://api.anthropic.com/v1/messages';
9187+
}
9188+
else
9189+
{
9190+
url = Editor.gptUrl;
9191+
}
9192+
91749193
var req = new mxXmlRequest(url, JSON.stringify(params), 'POST');
91759194

91769195
req.setRequestHeaders = mxUtils.bind(this, function(request, params)
@@ -9179,6 +9198,12 @@ var ChatWindow = function(editorUi, x, y, w, h)
91799198
{
91809199
request.setRequestHeader('X-goog-api-key', Editor.geminiApiKey);
91819200
}
9201+
else if (theModel.substring(0, 7) == 'claude-')
9202+
{
9203+
request.setRequestHeader('x-api-key', Editor.claudeApiKey);
9204+
request.setRequestHeader('anthropic-version', '2023-06-01');
9205+
request.setRequestHeader('anthropic-dangerous-direct-browser-access', 'true');
9206+
}
91829207
else
91839208
{
91849209
request.setRequestHeader('Authorization', 'Bearer ' + Editor.gptApiKey);
@@ -9198,9 +9223,22 @@ var ChatWindow = function(editorUi, x, y, w, h)
91989223
if (req.getStatus() >= 200 && req.getStatus() <= 299)
91999224
{
92009225
var response = JSON.parse(req.getText());
9201-
var text = theModel.substring(0, 7) == 'gemini-' ?
9202-
mxUtils.trim(response.candidates[0].content.parts[0].text) :
9203-
mxUtils.trim(response.choices[0].message.content);
9226+
var text = null;
9227+
9228+
if (theModel.substring(0, 7) == 'gemini-')
9229+
{
9230+
text = response.candidates[0].content.parts[0].text;
9231+
}
9232+
else if (theModel.substring(0, 7) == 'claude-')
9233+
{
9234+
text = response.content[0].text;
9235+
}
9236+
else
9237+
{
9238+
text = response.choices[0].message.content;
9239+
}
9240+
9241+
text = mxUtils.trim(text);
92049242
var mermaid = editorUi.extractMermaidDeclaration(text);
92059243
EditorUi.debug('EditorUi.ChatWindow.addMessage',
92069244
'params', params, 'response', response,
@@ -11726,7 +11764,8 @@ var EditShapeDialog = function(editorUi, cell, title)
1172611764
contentDiv.appendChild(textarea);
1172711765

1172811766
var previewDiv = document.createElement('div');
11729-
previewDiv.style.border = '1px solid lightgray';
11767+
previewDiv.style.borderWidth = '1px';
11768+
previewDiv.style.borderStyle = 'solid';
1173011769
previewDiv.style.padding = '20px';
1173111770
previewDiv.style.flexGrow = '1';
1173211771
previewDiv.style.borderRadius = '4px';

src/main/webapp/js/diagramly/Editor.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,12 @@
316316
Editor.geminiApiKey = (urlParams['gemini-api-key'] != null) ?
317317
decodeURIComponent(urlParams['gemini-api-key']) : null;
318318

319+
/**
320+
* Specifies the Gemini API key. Default is null.
321+
*/
322+
Editor.claudeApiKey = (urlParams['claude-api-key'] != null) ?
323+
decodeURIComponent(urlParams['claude-api-key']) : null;
324+
319325
/**
320326
* Specifies the ChatGPT model. Default is 'chatgpt-4o-latest'.
321327
*/
@@ -327,7 +333,12 @@
327333
'Gemini 3 Pro Preview': 'gemini-3-pro-preview',
328334
'Gemini 2.5 Pro': 'gemini-2.5-pro',
329335
'Gemini 2.5 Flash': 'gemini-2.5-flash',
330-
'Gemini 2.0 Flash': 'gemini-2.0-flash'
336+
'Gemini 2.0 Flash': 'gemini-2.0-flash',
337+
'Claude 4.5 Sonnet': 'claude-sonnet-4-5',
338+
'Claude 4.5 Haiku': 'claude-haiku-4-5',
339+
'Claude 4.0 Sonnet': 'claude-sonnet-4-0',
340+
'Claude 3.7 Sonnet': 'claude-3-7-sonnet-latest',
341+
'Claude 3.5 Haiku': 'claude-3-5-haiku-latest'
331342
};
332343

333344
/**
@@ -2702,6 +2713,11 @@
27022713
Editor.geminiApiKey = config.geminiApiKey;
27032714
}
27042715

2716+
if (config.claudeApiKey != null)
2717+
{
2718+
Editor.claudeApiKey = config.claudeApiKey;
2719+
}
2720+
27052721
if (config.gptModels != null)
27062722
{
27072723
Editor.gptModels = config.gptModels;

src/main/webapp/js/diagramly/EditorUi.js

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,7 +1454,9 @@
14541454
// Writes the file as an embedded HTML file
14551455
if (!forceSvg && !forceXml && (forceHtml || (file != null && /(\.html)$/i.test(file.getTitle()))))
14561456
{
1457-
xml = this.getHtml2(mxUtils.getXml(fileNode), graph, (file != null) ? file.getTitle() : null, editLink, redirect);
1457+
xml = this.getHtml2(mxUtils.getXml(fileNode), graph, (file != null) ? file.getTitle() : null,
1458+
editLink, redirect, redirect == null && !EditorUi.isElectronApp &&
1459+
this.getServiceName() == 'draw.io');
14581460
}
14591461
// Maps the XML data to the content attribute in the SVG node
14601462
else if (forceSvg || (!forceXml && file != null && /(\.svg)$/i.test(file.getTitle())))
@@ -2016,19 +2018,23 @@
20162018
/**
20172019
* Same as above but using the new embed code.
20182020
*/
2019-
EditorUi.prototype.getHtml2 = function(xml, graph, title, editLink, redirect)
2021+
EditorUi.prototype.getHtml2 = function(xml, graph, title, editLink, redirect, addEditLink)
20202022
{
20212023
var js = window.DRAWIO_VIEWER_URL || EditorUi.drawHost + '/js/viewer-static.min.js';
2022-
2024+
var data = {highlight: '#0000ff', nav: this.editor.graph.foldingEnabled, resize: true,
2025+
xml: Graph.zapGremlins(xml), toolbar: 'pages zoom layers lightbox'};
2026+
20232027
// Makes XHTML compatible
20242028
if (redirect != null)
20252029
{
20262030
redirect = redirect.replace(/&/g, '&amp;');
20272031
}
2028-
2029-
var data = {highlight: '#0000ff', nav: this.editor.graph.foldingEnabled, resize: true,
2030-
xml: Graph.zapGremlins(xml), toolbar: 'pages zoom layers lightbox'};
2031-
2032+
else if (addEditLink)
2033+
{
2034+
data.editor = window.DRAWIO_BASE_URL;
2035+
data.toolbar += ' editlocal';
2036+
}
2037+
20322038
if (this.pages != null && this.currentPage != null)
20332039
{
20342040
data.page = mxUtils.indexOf(this.pages, this.currentPage);
@@ -5102,23 +5108,6 @@
51025108
new Blob([data], {type: mimeType})
51035109
navigator.msSaveOrOpenBlob(blob, filename);
51045110
}
5105-
// Older versions of IE (binary not supported)
5106-
else if (mxClient.IS_IE)
5107-
{
5108-
var win = window.open('about:blank', '_blank');
5109-
5110-
if (win == null)
5111-
{
5112-
mxUtils.popup(data, true);
5113-
}
5114-
else
5115-
{
5116-
win.document.write(data);
5117-
win.document.close();
5118-
win.document.execCommand('SaveAs', true, filename);
5119-
win.close();
5120-
}
5121-
}
51225111
else if (mxClient.IS_IOS && this.isOffline())
51235112
{
51245113
// Workaround for "WebKitBlobResource error 1" in mobile Safari

0 commit comments

Comments
 (0)