Skip to content

Commit e2ff57b

Browse files
authored
Merge pull request #3 from cosmocode/svg-as-object
Render SVGs as <object> instead of <img>
2 parents 72babf3 + 472d4df commit e2ff57b

File tree

3 files changed

+101
-26
lines changed

3 files changed

+101
-26
lines changed

action.php

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ public function handleAjax(Doku_Event $event)
5858
}
5959

6060
/**
61-
* Return an array of diagrams that are editable,
62-
* based on ACLs and image content ('embed.diagrams.net' or 'draw.io')
61+
* Return an array of diagrams editable by the current user
6362
*
6463
* @param array $images
6564
* @return array
@@ -69,30 +68,32 @@ protected function editableDiagrams($images)
6968
$editable = [];
7069

7170
foreach ($images as $image) {
72-
// skip non SVG files
73-
if (strpos($image, '.svg', - strlen('.svg')) === false) {
74-
continue;
75-
}
76-
// check ACLs
77-
if (auth_quickaclcheck($image) < AUTH_UPLOAD) {
78-
continue;
79-
}
80-
// is it our diagram?
81-
global $conf;
82-
$file = DOKU_INC .
83-
$conf['savedir'] .
84-
DIRECTORY_SEPARATOR .
85-
'media' .
86-
DIRECTORY_SEPARATOR .
87-
preg_replace(['/:/'], [DIRECTORY_SEPARATOR], $image);
88-
89-
$begin = file_get_contents($file, false, null, 0, 500);
90-
// TODO find a better way to detect diagrams
91-
if (strpos($begin, 'embed.diagrams.net') || strpos($begin, 'draw.io')) {
71+
if (auth_quickaclcheck($image) >= AUTH_UPLOAD && $this->isDiagram($image)) {
9272
$editable[] = $image;
9373
}
9474
}
9575

9676
return $editable;
9777
}
78+
79+
/**
80+
* Return true if the image is recognized as our diagram
81+
* based on content ('embed.diagrams.net' or 'draw.io')
82+
*
83+
* @param string $image image id
84+
* @return bool
85+
*/
86+
protected function isDiagram($image)
87+
{
88+
global $conf;
89+
$file = DOKU_INC .
90+
$conf['savedir'] .
91+
DIRECTORY_SEPARATOR .
92+
'media' .
93+
DIRECTORY_SEPARATOR .
94+
preg_replace(['/:/'], [DIRECTORY_SEPARATOR], $image);
95+
96+
$begin = file_get_contents($file, false, null, 0, 500);
97+
return strpos($begin, 'embed.diagrams.net') || strpos($begin, 'draw.io');
98+
}
9899
}

script.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ jQuery(function () {
33
/* DOKUWIKI:include script/service.js */
44
/* DOKUWIKI:include script/elements.js */
55

6-
// add diagram edit button to all SVGs included in wiki pages
7-
const $images = jQuery('img').filter('.media, .medialeft, .mediacenter, .mediaright');
6+
// add diagram edit button to diagram SVGs included in wiki pages
7+
const $images = jQuery('object').filter('.diagrams-svg');
88

99
// collect image IDs with file extension
1010
const imageIds = $images.map(function (key, image) {
11-
return extractIdFromMediaUrl(image.src);
11+
return extractIdFromMediaUrl(image.data);
1212
}).toArray();
1313

1414
let ajaxData = {};
@@ -19,7 +19,7 @@ jQuery(function () {
1919
const attachButtons = function (result) {
2020
const diagrams = JSON.parse(result);
2121
$images.each(function () {
22-
const id = extractIdFromMediaUrl(this.src);
22+
const id = extractIdFromMediaUrl(this.data);
2323
const $current = jQuery(this);
2424
if (diagrams.includes(id)) {
2525
let $editButton = editDiagramButton(id);
@@ -111,3 +111,11 @@ jQuery(function () {
111111
observer.observe(targetNode, config);
112112
});
113113
});
114+
115+
// open links in diagrams in the browser window instead of SVG frame
116+
// TODO this will not work with DokuWiki master as of February 2021 (contentDocument is null)
117+
jQuery(window).on('load', function() {
118+
jQuery('object.diagrams-svg').each( function() {
119+
jQuery(this.contentDocument).find('svg').find('a').attr('target', '_parent');
120+
});
121+
});

syntax.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/**
4+
* Class syntax_plugin_diagrams
5+
*/
6+
class syntax_plugin_diagrams extends DokuWiki_Syntax_Plugin {
7+
8+
/**
9+
* @inheritdoc
10+
*/
11+
public function getType()
12+
{
13+
return 'substition';
14+
}
15+
16+
/**
17+
* @inheritdoc
18+
*/
19+
public function getSort()
20+
{
21+
return 319;
22+
}
23+
24+
/**
25+
* @inheritdoc
26+
*/
27+
public function connectTo($mode)
28+
{
29+
$this->Lexer->addSpecialPattern('\{\{[^\}]+(?:\.svg)[^\}]*?\}\}',$mode,'plugin_diagrams');
30+
}
31+
32+
/**
33+
* Parse SVG syntax into media data
34+
*
35+
* @param string $match
36+
* @param int $state
37+
* @param int $pos
38+
* @param Doku_Handler $handler
39+
* @return array|bool
40+
*/
41+
public function handle($match, $state, $pos, Doku_Handler $handler)
42+
{
43+
return Doku_Handler_Parse_Media($match);
44+
}
45+
46+
/**
47+
* Render the diagram SVG as <object> instead of <img> to allow links
48+
*
49+
* @param string $format
50+
* @param Doku_Renderer $renderer
51+
* @param array $data
52+
* @return bool
53+
*/
54+
public function render($format, Doku_Renderer $renderer, $data)
55+
{
56+
if ($format !== 'xhtml') return false;
57+
58+
$width = $data['width'] ? 'width="' . $data['width'] . '"' : '';
59+
$height = $data['height'] ? 'height="' . $data['height'] . '"' : '';
60+
61+
$tag = '<object data="%s&cache=nocache" type="image/svg+xml" class="diagrams-svg media%s" %s %s></object>';
62+
$renderer->doc .= sprintf($tag, ml($data['src']), $data['align'], $width, $height);
63+
64+
return true;
65+
}
66+
}

0 commit comments

Comments
 (0)