Overview
Comment:Fix some bugs, improve details in web page editing
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | stable
Files: files | file ages | folders
SHA3-256: c06d471a14d7ba50878a7158f57c77daafbebf6244fd0a1cfbf9b033a01d6c0e
User & Date: bohwaz on 2023-03-21 15:26:57
Other Links: manifest | tags
Context
2023-03-21
15:36
Move onload for iframe so that we are sure it is triggered as soon as possible check-in: 9c90d7416e user: bohwaz tags: trunk, stable
15:26
Fix some bugs, improve details in web page editing check-in: c06d471a14 user: bohwaz tags: trunk, stable
14:17
Page encryption: fix multiple password prompts, handle images and files check-in: 19ed3d39d0 user: bohwaz tags: trunk
Changes

Modified src/include/lib/Garradin/Entities/Web/Page.php from [f7c6bc20c5] to [21fb3dd712].

46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
		'published' => 'DateTime',
		'modified'  => 'DateTime',
		'content'   => 'string',
	];

	const FORMATS_LIST = [
		Render::FORMAT_MARKDOWN => 'MarkDown',
		Render::FORMAT_SKRIV => 'SkrivML',
		Render::FORMAT_ENCRYPTED => 'Chiffré',

	];

	const STATUS_ONLINE = 'online';
	const STATUS_DRAFT = 'draft';

	const STATUS_LIST = [
		self::STATUS_ONLINE => 'En ligne',







<

>







46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
		'published' => 'DateTime',
		'modified'  => 'DateTime',
		'content'   => 'string',
	];

	const FORMATS_LIST = [
		Render::FORMAT_MARKDOWN => 'MarkDown',

		Render::FORMAT_ENCRYPTED => 'Chiffré',
		Render::FORMAT_SKRIV => 'SkrivML',
	];

	const STATUS_ONLINE = 'online';
	const STATUS_DRAFT = 'draft';

	const STATUS_LIST = [
		self::STATUS_ONLINE => 'En ligne',
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
		if (!empty($source['encryption']) ) {
			$this->set('format', Render::FORMAT_ENCRYPTED);
		}
		elseif (empty($source['format'])) {
			$this->set('format', Render::FORMAT_MARKDOWN);
		}

		$this->set('status', empty($source['draft']) ? self::STATUS_ONLINE : self::STATUS_DRAFT);

		return parent::importForm($source);
	}

	public function getBreadcrumbs(): array
	{
		$sql = '







|







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
		if (!empty($source['encryption']) ) {
			$this->set('format', Render::FORMAT_ENCRYPTED);
		}
		elseif (empty($source['format'])) {
			$this->set('format', Render::FORMAT_MARKDOWN);
		}

		$this->set('status', empty($source['status']) ? self::STATUS_ONLINE : $source['status']);

		return parent::importForm($source);
	}

	public function getBreadcrumbs(): array
	{
		$sql = '

Modified src/include/lib/Garradin/Web/Render/Encrypted.php from [42fbb7e0fc] to [742c645396].

1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16

17
18
19
20
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;
use Garradin\Template;
use const Garradin\ADMIN_URL;


class EncryptedSkriv extends AbstractRender
{
	public function render(?string $content = null): string
	{
		$tpl = Template::getInstance();
		$file = $this->file;
		$content = $content ?? $file->fetch();
		$tpl->assign('admin_url', ADMIN_URL);

		$tpl->assign(compact('file', 'content'));
		return $tpl->fetch('common/files/_file_render_encrypted.tpl');
	}
}







>

|







>




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace Garradin\Web\Render;

use Garradin\Entities\Files\File;
use Garradin\Template;
use const Garradin\ADMIN_URL;
use const Garradin\WWW_URL;

class Encrypted extends AbstractRender
{
	public function render(?string $content = null): string
	{
		$tpl = Template::getInstance();
		$file = $this->file;
		$content = $content ?? $file->fetch();
		$tpl->assign('admin_url', ADMIN_URL);
		$tpl->assign('url', WWW_URL . $this->current_path);
		$tpl->assign(compact('file', 'content'));
		return $tpl->fetch('common/files/_file_render_encrypted.tpl');
	}
}

Modified src/include/lib/Garradin/Web/Render/Render.php from [7f37b07c32] to [75beee0f1f].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

	static public function getRenderer(string $format, ?File $file, string $link_prefix = null)
	{
		if ($format == self::FORMAT_SKRIV) {
			return new Skriv($file, $link_prefix);
		}
		else if ($format == self::FORMAT_ENCRYPTED) {
			return new EncryptedSkriv($file, $link_prefix);
		}
		else if ($format == self::FORMAT_MARKDOWN) {
			return new Markdown($file, $link_prefix);
		}
		else {
			throw new \LogicException('Invalid format: ' . $format);
		}







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

	static public function getRenderer(string $format, ?File $file, string $link_prefix = null)
	{
		if ($format == self::FORMAT_SKRIV) {
			return new Skriv($file, $link_prefix);
		}
		else if ($format == self::FORMAT_ENCRYPTED) {
			return new Encrypted($file, $link_prefix);
		}
		else if ($format == self::FORMAT_MARKDOWN) {
			return new Markdown($file, $link_prefix);
		}
		else {
			throw new \LogicException('Invalid format: ' . $format);
		}

Modified src/templates/common/files/_file_render_encrypted.tpl from [66113ac8f7] to [00452ede02].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<noscript>
	<div class="error">
		Vous dever activer javascript pour pouvoir déchiffrer cette page.
	</div>
</noscript>
<script type="text/javascript" src="{$admin_url}static/scripts/web_encryption.js"></script>
<div id="web_encrypted_message">
	<p class="block alert">Cette page est chiffrée.
		<input type="button" onclick="return pleaseDecrypt();" value="Entrer le mot de passe" />
	</p>
</div>
<div class="web-content" style="display: none;" id="web_encrypted_content">
	{$content}
</div>











|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
<noscript>
	<div class="error">
		Vous dever activer javascript pour pouvoir déchiffrer cette page.
	</div>
</noscript>
<script type="text/javascript" src="{$admin_url}static/scripts/web_encryption.js"></script>
<div id="web_encrypted_message">
	<p class="block alert">Cette page est chiffrée.
		<input type="button" onclick="return pleaseDecrypt();" value="Entrer le mot de passe" />
	</p>
</div>
<div class="web-content" style="display: none;" id="web_encrypted_content" data-url="{$url}">
	{$content}
</div>

Modified src/templates/common/files/edit_web.tpl from [6780cd027e] to [5785ce5cc0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{include file="admin/_head.tpl" title="Édition de fichier" custom_js=['web_editor.js']}

<form method="post" action="{$self_url}">
	<p class="textEditor">
		{input type="textarea" name="content" cols="70" rows="30" default=$content data-preview-url="!common/files/_preview.php?f=%s"|local_url|args:$path data-fullscreen="1" data-attachments="0" data-savebtn="1" data-format=$format}
	</p>

	<p class="submit">
		{csrf_field key=$csrf_key}
		{button type="submit" name="save" label="Enregistrer" shape="right" class="main"}
	</p>

</form>

{include file="admin/_foot.tpl"}


|












1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{include file="admin/_head.tpl" title="Édition de fichier" custom_js=['web_editor.js']}

<form method="post" action="{$self_url}" data-focus="textarea">
	<p class="textEditor">
		{input type="textarea" name="content" cols="70" rows="30" default=$content data-preview-url="!common/files/_preview.php?f=%s"|local_url|args:$path data-fullscreen="1" data-attachments="0" data-savebtn="1" data-format=$format}
	</p>

	<p class="submit">
		{csrf_field key=$csrf_key}
		{button type="submit" name="save" label="Enregistrer" shape="right" class="main"}
	</p>

</form>

{include file="admin/_foot.tpl"}

Modified src/templates/web/edit.tpl from [57eed5d57b] to [8ddcf4f5f3].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39

40
41
42
43
44
45
46
{include file="admin/_head.tpl" title="Édition : %s"|args:$page.title current="web" hide_title=true}

{form_errors}

{if $show_diff}
	<h3>Modifications entre votre version et la nouvelle version</h3>
	{diff old=$old_content new=$new_content}
{/if}

<form method="post" action="{$self_url}" class="web-edit web-edit-text" data-focus="#f_content">
	<fieldset class="header">
		<legend>Modification : {$page.title}</legend>
		<p>{input type="text" name="title" source=$page required=true class="full-width" placeholder="Titre" title="Modifier le titre"}</p>
		<div>
			<dl>{input type="list" name="parent" label="Catégorie" default=$parent target="!web/_selector.php?current=%s&parent=%s"|args:$page.path,$page.parent required=true}</dl>
			<dl>{input type="datetime" name="date" label="Date" required=true default=$page.published}</dl>
			<dl>{input type="select" name="format" required=true options=$formats source=$page label="Format"}</dl>
			<dl>{input type="checkbox" name="status" value=$page::STATUS_DRAFT label="Brouillon"}</dl>
			{*
			<dl>
				<dt><label for="f_uri">Adresse de la page</label></dt>
				<dd><tt>{$www_url}{input type="text" name="uri" default=$page.uri required=true title="Utilisée pour désigner l'adresse de la page sur le site. Ne peut comporter que des lettres, des chiffres, des tirets et des tirets bas." pattern="[A-Za-z0-9_-]+"}</tt></dd>
			</dl>
			*}
		</ul>
	</fieldset>

	<fieldset class="editor">
		<div class="textEditor">
			{input type="textarea" name="content" cols="70" rows="35" default=$new_content data-attachments=1 data-savebtn=2 data-preview-url="!common/files/_preview.php?w=%s"|local_url|args:$page.path data-format="#f_format"}
		</div>
	</fieldset>


	<fieldset class="content">
		{$page->render()|raw}
	</fieldset>

	<div class="block">
	</div>


	<fieldset class="properties">
		{*
		<nav class="tabs">
			<ul>
				<li><a id="toggleVisualEditor">Éditeur visuel</a></li>
				<li class="current"><a id="toggleTextEditor">Éditeur texte</a></li>









|







|
<
<
<
<
<
<





|



>






>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18






19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{include file="admin/_head.tpl" title="Édition : %s"|args:$page.title current="web" hide_title=true}

{form_errors}

{if $show_diff}
	<h3>Modifications entre votre version et la nouvelle version</h3>
	{diff old=$old_content new=$new_content}
{/if}

<form method="post" action="{$self_url}" class="web-edit" data-focus="#f_content">
	<fieldset class="header">
		<legend>Modification : {$page.title}</legend>
		<p>{input type="text" name="title" source=$page required=true class="full-width" placeholder="Titre" title="Modifier le titre"}</p>
		<div>
			<dl>{input type="list" name="parent" label="Catégorie" default=$parent target="!web/_selector.php?current=%s&parent=%s"|args:$page.path,$page.parent required=true}</dl>
			<dl>{input type="datetime" name="date" label="Date" required=true default=$page.published}</dl>
			<dl>{input type="select" name="format" required=true options=$formats source=$page label="Format"}</dl>
			<dl>{input type="checkbox" name="status" value=$page::STATUS_DRAFT label="Brouillon" source=$page}</dl>






		</ul>
	</fieldset>

	<fieldset class="editor">
		<div class="textEditor">
			{input type="textarea" name="content" cols="70" rows="20" default=$new_content data-attachments=1 data-savebtn=2 data-preview-url="!common/files/_preview.php?w=%s"|local_url|args:$page.path data-format="#f_format"}
		</div>
	</fieldset>

{*
	<fieldset class="content">
		{$page->render()|raw}
	</fieldset>

	<div class="block">
	</div>
*}

	<fieldset class="properties">
		{*
		<nav class="tabs">
			<ul>
				<li><a id="toggleVisualEditor">Éditeur visuel</a></li>
				<li class="current"><a id="toggleTextEditor">Éditeur texte</a></li>

Modified src/www/admin/static/scripts/web_editor.css from [8621224b2d] to [d40ba89e00].

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51




52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
.textEditor {
    background: var(--gLightBackgroundColor);
    overflow: hidden;
    position: relative;

}

.textEditor textarea {
    margin: 0;
    height: 96%;
    width: 98%;
}

nav.te {
    margin-bottom: .5em;
    height: 30px;
}

nav.te .bold, nav.te .italic, nav.te .title, nav.te .link {
    font-family: Georgia, "Times New Roman", serif;
}

nav.te .bold { font-weight: bold; }
nav.te .italic { font-style: italic; }
nav.te .link { text-decoration: underline; color: var(--gLinkColor); }

nav.te .fullscreen {
    text-indent: -70em;
    width: 32px;
    overflow: hidden;
}

nav.te .file {
    margin-left: 2em;
}

nav.te .save {
    float: right;
    font-weight: bold;
    margin-right: 2em;
}

nav.te .fullscreen {
    background-repeat: no-repeat;
    background-position: center center;
    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEUAAABMTFFOTlBOTlCQ1uMHAAAAA3RSTlMAOcKBmOr4AAAAQUlEQVQI12P4/4D7P8N/B0Yo8XsC23+GZw+4pzM4TmBzYsAGgBKODNcecM9m+D+B7T3DPwfG/Qz/G5iABlzg+g8ANzMax/3kkQoAAAAASUVORK5CYII=");
    float: right;
}

nav.te .preview {
    margin-left: 2em;
}





.textEditor.fullscreen nav.te .fullscreen {
    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEUAAABNTVFOTlBOTlBLB/faAAAAA3RSTlMAOsPdsomtAAAAQElEQVQI12NIEWCRZNi5gTePIe8D/08G6Q/8Txj0P/B/YVj/gf8fAzawHyQhD1ICJvI/8O9k2FnAl8eQosAiCQCgixb13aKGIwAAAABJRU5ErkJggg==");
}

.textEditor nav button.close {
    display: none;
    display: block;
    width: 95%;
}

.textEditor.fullscreen {
    position: fixed;
    top: 0;
    left: 0;


<

>




|





|
















|



|

<
<






<


|


>
>
>
>







<







1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37


38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
.textEditor {
    background: var(--gLightBackgroundColor);

    position: relative;
    height: 100%;
}

.textEditor textarea {
    margin: 0;
    height: calc(100% - 3.5em);
    width: 98%;
}

nav.te {
    margin-bottom: .5em;
    height: 2em;
}

nav.te .bold, nav.te .italic, nav.te .title, nav.te .link {
    font-family: Georgia, "Times New Roman", serif;
}

nav.te .bold { font-weight: bold; }
nav.te .italic { font-style: italic; }
nav.te .link { text-decoration: underline; color: var(--gLinkColor); }

nav.te .fullscreen {
    text-indent: -70em;
    width: 32px;
    overflow: hidden;
}

nav.te .image {
    margin-left: 2em;
}

nav.te .save, nav.te .fullscreen, nav.te .help, nav.te .preview {
    float: right;


}

nav.te .fullscreen {
    background-repeat: no-repeat;
    background-position: center center;
    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEUAAABMTFFOTlBOTlCQ1uMHAAAAA3RSTlMAOcKBmOr4AAAAQUlEQVQI12P4/4D7P8N/B0Yo8XsC23+GZw+4pzM4TmBzYsAGgBKODNcecM9m+D+B7T3DPwfG/Qz/G5iABlzg+g8ANzMax/3kkQoAAAAASUVORK5CYII=");

}

nav.te .help, nav.te .save {
    margin-left: 2em;
}

nav.te .save-label {
    font-weight: bold;
}

.textEditor.fullscreen nav.te .fullscreen {
    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEUAAABNTVFOTlBOTlBLB/faAAAAA3RSTlMAOsPdsomtAAAAQElEQVQI12NIEWCRZNi5gTePIe8D/08G6Q/8Txj0P/B/YVj/gf8fAzawHyQhD1ICJvI/8O9k2FnAl8eQosAiCQCgixb13aKGIwAAAABJRU5ErkJggg==");
}

.textEditor nav button.close {
    display: none;

    width: 95%;
}

.textEditor.fullscreen {
    position: fixed;
    top: 0;
    left: 0;
86
87
88
89
90
91
92
93

94
95
96
97
98

99
100
101
102
103
104
105
}

.textEditor.iframe nav button {
    display: none;
}

.textEditor.iframe nav button.close {
    display: inline-block;

}

.textEditor iframe {
    border: none;
    background: rgba(var(--gLightBackgroundColor), 0.5);

    border-radius: .5em;
    width: 100%;
}

.textEditor iframe.hidden {
    visibility: hidden;
    width: 0px;







|
>





>







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
}

.textEditor.iframe nav button {
    display: none;
}

.textEditor.iframe nav button.close {
    display: block;
    margin: 0 auto;
}

.textEditor iframe {
    border: none;
    background: rgba(var(--gLightBackgroundColor), 0.5);
    border: 1px solid var(--gLightBorderColor);
    border-radius: .5em;
    width: 100%;
}

.textEditor iframe.hidden {
    visibility: hidden;
    width: 0px;
180
181
182
183
184
185
186
187
188


189
190
191
    font-size: 0.8em;
    margin: .5em;
    opacity: 0.8;
}

#confirm_saved {
    position: absolute;
    top: .5em;
    right: 10em;


    text-align: center;
    transition: all .5s, opacity 2s;
}







<
|
>
>

|

182
183
184
185
186
187
188

189
190
191
192
193
194
    font-size: 0.8em;
    margin: .5em;
    opacity: 0.8;
}

#confirm_saved {
    position: absolute;

    right: -.1em;
    top: -.1em;
    margin: 0;
    text-align: center;
    transition: opacity .5s;
}

Modified src/www/admin/static/scripts/web_editor.js from [6022b134db] to [da3e9adcd7].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
(function () {
	g.style('scripts/web_editor.css');

	function showSaved() {
		let c = document.createElement('p');
		c.className = 'block confirm';
		c.id = 'confirm_saved';
		c.innerText = 'Enregistré';
		c.style.right = '-10em';

		document.querySelector('#f_content').parentNode.appendChild(c);

		window.setTimeout(() => {
			c.style.right = '';
		}, 200);

		window.setTimeout(() => {
			c.style.opacity = 0;
		}, 3000);

		window.setTimeout(() => {
			c.remove();
		}, 5000);
	}

	g.script('scripts/lib/text_editor.min.js', function () {
		var t = new textEditor('f_content');
		t.parent = t.textarea.parentNode;

		var config = {








|




|
|







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
(function () {
	g.style('scripts/web_editor.css');

	function showSaved() {
		let c = document.createElement('p');
		c.className = 'block confirm';
		c.id = 'confirm_saved';
		c.innerText = 'Enregistré';
		c.style.opacity = 0;

		document.querySelector('#f_content').parentNode.appendChild(c);

		window.setTimeout(() => {
			c.style.opacity = 1;
		}, 100);

		window.setTimeout(() => {
			c.style.opacity = 0;
		}, 3000);

		window.setTimeout(() => {
			c.remove();
		}, 3500);
	}

	g.script('scripts/lib/text_editor.min.js', function () {
		var t = new textEditor('f_content');
		t.parent = t.textarea.parentNode;

		var config = {
65
66
67
68
69
70
71


72
73
74
75
76
77
78
79
80
81
82
83
84
85

86








87
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102









103
104
105
106
107
108
109

		if (config.fullscreen) {
			toggleFullscreen();
		}

		var openPreview = function ()
		{


			openIFrame('');
			var form = document.createElement('form');
			form.appendChild(t.textarea.cloneNode(true));
			form.firstChild.value = t.textarea.value;
			let f = document.createElement('input');
			f.type = 'hidden';
			f.name = 'format';
			f.value = config.format;
			form.appendChild(f);
			form.target = 'editorFrame';
			form.action = config.preview_url;
			form.style.display = 'none';
			form.method = 'post';
			document.body.appendChild(form);

			form.submit();








			return true;
		};

		var openSyntaxHelp = function ()
		{
			let url = config.format == 'markdown' ? 'markdown.html' : 'skriv.html';
			url = g.admin_url + 'static/doc/' + url;

			g.openFrameDialog(url);

		};

		var openFileInsert = function ()
		{
			let args = new URLSearchParams(window.location.search);
			var uri = args.get('p');
			g.openFrameDialog(g.admin_url + 'web/_attach.php?_dialog&p=' + uri);









		};

		window.te_insertFile = function (file)
		{
			var tag = '<<file|'+file+'>>';

			t.insertAtPosition(t.getSelection().start, tag);







>
>














>

>
>
>
>
>
>
>
>









>






|
>
>
>
>
>
>
>
>
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

		if (config.fullscreen) {
			toggleFullscreen();
		}

		var openPreview = function ()
		{
			var pos = t.textarea.scrollTop / t.textarea.scrollHeight;

			openIFrame('');
			var form = document.createElement('form');
			form.appendChild(t.textarea.cloneNode(true));
			form.firstChild.value = t.textarea.value;
			let f = document.createElement('input');
			f.type = 'hidden';
			f.name = 'format';
			f.value = config.format;
			form.appendChild(f);
			form.target = 'editorFrame';
			form.action = config.preview_url;
			form.style.display = 'none';
			form.method = 'post';
			document.body.appendChild(form);
			t.iframe.style.opacity = .2;
			form.submit();

			// Sync scrolling
			t.iframe.onload = () => {
				t.iframe.style.opacity = 1;
				var scroll = pos * t.iframe.contentWindow.document.body.scrollHeight;
				t.iframe.contentWindow.scrollTo(0, scroll);
			};

			return true;
		};

		var openSyntaxHelp = function ()
		{
			let url = config.format == 'markdown' ? 'markdown.html' : 'skriv.html';
			url = g.admin_url + 'static/doc/' + url;

			g.openFrameDialog(url);
			return true;
		};

		var openFileInsert = function ()
		{
			let args = new URLSearchParams(window.location.search);
			var uri = args.get('p');
			g.openFrameDialog(g.admin_url + 'web/_attach.php?files&_dialog&p=' + uri);
			return true;
		};

		var openImageInsert = function ()
		{
			let args = new URLSearchParams(window.location.search);
			var uri = args.get('p');
			g.openFrameDialog(g.admin_url + 'web/_attach.php?images&_dialog&p=' + uri);
			return true;
		};

		window.te_insertFile = function (file)
		{
			var tag = '<<file|'+file+'>>';

			t.insertAtPosition(t.getSelection().start, tag);
266
267
268
269
270
271
272
273
274
275
276

277
278
279
280











281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297

		let createToolbar = () => {
			appendButton('title', "Titre", applyHeader );
			appendButton('bold', 'Gras', applyBold );
			appendButton('italic', "Italique", applyItalic );
			appendButton('link', "Lien", insertURL);

			appendButton('ext preview', '👁', openPreview, 'Prévisualiser');
			appendButton('ext help', '❓', openSyntaxHelp, 'Aide sur la syntaxe');

			if (config.attachments) {

				appendButton('file', "📎 Fichiers", openFileInsert, 'Insérer fichier / image');
				t.shortcuts.push({ctrl: true, shift: true, key: 'i', callback: openFileInsert});
			}












			if (!config.fullscreen) {
				appendButton('ext fullscreen', 'Plein écran', toggleFullscreen, 'Plein écran');
			}

			if (config.savebtn == 1) {
				appendButton('ext save', 'Enregistrer', save, 'Enregistrer');
			}
			else if (config.savebtn == 2) {
				appendButton('ext save', '⇑', save, 'Enregistrer sans fermer');
			}

			appendButton('ext close', 'Retour à l\'édition', closeIFrame);

			t.parent.insertBefore(toolbar, t.parent.firstChild);
		}

		let toggleFormat = (format) => {







<
<
<

>
|



>
>
>
>
>
>
>
>
>
>
>




<
<
<
<
<
<







287
288
289
290
291
292
293



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314






315
316
317
318
319
320
321

		let createToolbar = () => {
			appendButton('title', "Titre", applyHeader );
			appendButton('bold', 'Gras', applyBold );
			appendButton('italic', "Italique", applyItalic );
			appendButton('link', "Lien", insertURL);




			if (config.attachments) {
				appendButton('image', "🖻", openImageInsert, 'Insérer image');
				appendButton('file', "📎", openFileInsert, 'Insérer fichier');
				t.shortcuts.push({ctrl: true, shift: true, key: 'i', callback: openFileInsert});
			}


			if (config.savebtn == 1) {
				appendButton('ext save save-label', 'Enregistrer', save, 'Enregistrer');
			}
			else if (config.savebtn == 2) {
				appendButton('ext save', '⇑', save, 'Enregistrer sans fermer');
			}

			appendButton('ext preview', '👁', openPreview, 'Prévisualiser');
			appendButton('ext help', '❓', openSyntaxHelp, 'Aide sur la syntaxe');

			if (!config.fullscreen) {
				appendButton('ext fullscreen', 'Plein écran', toggleFullscreen, 'Plein écran');
			}








			appendButton('ext close', 'Retour à l\'édition', closeIFrame);

			t.parent.insertBefore(toolbar, t.parent.firstChild);
		}

		let toggleFormat = (format) => {

Modified src/www/admin/static/scripts/web_encryption.js from [7d94d4ce81] to [e0da77cbde].

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116
117
118
119
120
121
		// Links
		content = content.replace(/\[{2}([^\|\]\n]+?)\|([^\]\n]+?)\]{2}/g, linkTag);
		content = content.replace(/\[{2}(([^\]]+?))\]{2}/g, linkTag);
		content = content.replace(/<(((?:https?|mailto):[^>]+?))>/g, linkTag);
		content = content.replace(/\[([^\]]+?)\]\(([^\)]+?)\)/g, linkTag);

		// Extensions
		content = content.replace(/&lt;&lt;(\w+)([\| ]([^&]+))?&gt;&gt;/, (match, name, separator, params) => {
			params = params.split('|');
			if (name == 'image') {
				var src = params[0];
				var align = params[1] || 'center';
				var caption = params[2] || src;

				var size = align == 'center' ? '500px' : '200px';
				return `<figure class="image img-${align}"><img src="${base_url + src}?${size}" alt="" /><figcaption>${caption}</figcaption></figure>`;

			}
			else if (name == 'file') {
				var src = params[0];
				var ext = src.replace(/^.*\.([^\.]+)$/, '');
				var caption = params[1] || src;
				return `<aside class="file" data-type="${ext}"><a href="${base_url + src}" class="internal-file"><b>${caption}</b> <small>${ext}</small></a>`;
			}
			else {
				return match;
			}
		});

		// nl2br







|




<
|

|
>



|
|
|







93
94
95
96
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
		// Links
		content = content.replace(/\[{2}([^\|\]\n]+?)\|([^\]\n]+?)\]{2}/g, linkTag);
		content = content.replace(/\[{2}(([^\]]+?))\]{2}/g, linkTag);
		content = content.replace(/<(((?:https?|mailto):[^>]+?))>/g, linkTag);
		content = content.replace(/\[([^\]]+?)\]\(([^\)]+?)\)/g, linkTag);

		// Extensions
		content = content.replace(/&lt;&lt;(\w+)([\| ]([^&]+))?&gt;&gt;/g, (match, name, separator, params) => {
			params = params.split('|');
			if (name == 'image') {
				var src = params[0];
				var align = params[1] || 'center';

				var caption = 2 in params ? '<figcaption>' + params[2] + '</figcaption>' : '';
				var size = align == 'center' ? '500px' : '200px';

				return `<figure class="image img-${align}"><a href="${base_url + src}" class="internal-image" target="_image"><img src="${base_url + src}?${size}" alt="" /></a>${caption}</figure>`;
			}
			else if (name == 'file') {
				var src = params[0];
				var ext = (a = src.lastIndexOf('.')) && a > 0 ? src.substr(a+1).toUpperCase() : '';
				var caption = params[1] || src.replace(/\.[^\.]+$/, '');
				return `<aside class="file" data-type="${ext}"><a href="${base_url + src}" class="internal-file"><b>${caption}</b> <small>${ext}</small></a></aside>`;
			}
			else {
				return match;
			}
		});

		// nl2br
247
248
249
250
251
252
253

254




255
256
257
258
259
260
261
		}

		if (!edit)
		{
			elm.style.display = 'block';
			document.getElementById('web_encrypted_message').style.display = 'none';
			base_url = elm.dataset.url.replace(/\/$/, '') + '/';

			elm.innerHTML = formatContent(content);




		}
		else
		{
			elm.value = content;
		}
	};








>
|
>
>
>
>







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
		}

		if (!edit)
		{
			elm.style.display = 'block';
			document.getElementById('web_encrypted_message').style.display = 'none';
			base_url = elm.dataset.url.replace(/\/$/, '') + '/';
			content = formatContent(content);
			elm.innerHTML = content;

			if (content.match(/<img/) && typeof window.enableImageGallery != 'undefined') {
				enableImageGallery();
			}
		}
		else
		{
			elm.value = content;
		}
	};

Modified src/www/admin/static/scripts/web_gallery.js from [5fb6dc7088] to [ac9bac10c3].

18
19
20
21
22
23
24


25
26
27
28
29
30
31
            a.onclick = function (e) {
                e.preventDefault();
                openImageBrowser(items, this.getAttribute('data-pos'));
                return false;
            };
        }
    };



    function openImageBrowser(items, pos)
    {
        div = document.createElement('div');
        div.className = 'imageBrowser';

        var fig = document.createElement('figure');







>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
            a.onclick = function (e) {
                e.preventDefault();
                openImageBrowser(items, this.getAttribute('data-pos'));
                return false;
            };
        }
    };

    window.enableImageGallery = enableGallery;

    function openImageBrowser(items, pos)
    {
        div = document.createElement('div');
        div.className = 'imageBrowser';

        var fig = document.createElement('figure');

Modified src/www/admin/static/styles/web.css from [e5fbbda856] to [5fa3360726].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
.web-edit {
    display: grid;
    grid-template-columns: 1fr 30%;
    grid-template-rows: .1fr 1fr .1fr;
    grid-gap: 1em;
    height: 100vh;
}

.web-edit-text .content, .web-edit-text .block {
    display: none;
}

.web-edit-visual .editor {
    display: none;
}

.web-edit nav ul {
    border: none;
}

.web-edit .properties {
    display: flex;
    flex-direction: row;

}

.web-edit nav ul {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
}

.web-edit nav ul li a {
    border-radius: 0 0 .5em .5em;
}

.web-edit fieldset {
    margin: 0;
}

.web-edit .submit {
    grid-row: 3;
    grid-column: 2;

}

fieldset.header {
    grid-column: span 2;
    margin-top: 1em;
}









|
|













>



















>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
.web-edit {
    display: grid;
    grid-template-columns: 1fr 30%;
    grid-template-rows: .1fr 1fr .1fr;
    grid-gap: 1em;
    height: 100vh;
}

.web-edit .editor textarea[disabled] {
    filter: blur(3px);
}

.web-edit-visual .editor {
    display: none;
}

.web-edit nav ul {
    border: none;
}

.web-edit .properties {
    display: flex;
    flex-direction: row;
    font-size: .9em;
}

.web-edit nav ul {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
}

.web-edit nav ul li a {
    border-radius: 0 0 .5em .5em;
}

.web-edit fieldset {
    margin: 0;
}

.web-edit .submit {
    grid-row: 3;
    grid-column: 2;
    text-align: right;
}

fieldset.header {
    grid-column: span 2;
    margin-top: 1em;
}

Modified src/www/admin/web/_attach.php from [a81a5ef39c] to [78e24e4bd5].

32
33
34
35
36
37
38




39



40


41
42
43
44
45
46
47
48
}, $csrf_key);


$form->runIf('upload', function () use ($page) {
	$new_file = File::uploadMultiple(Utils::dirname($page->file_path), 'file');
}, $csrf_key);





$files = $page->getAttachmentsGallery(true);



$images = $page->getImageGallery(true);


$max_size = Utils::getMaxUploadSize();

$tpl->assign(compact('page', 'files', 'images', 'max_size', 'csrf_key'));

$tpl->assign('custom_js', ['web_files.js']);
$tpl->assign('custom_css', ['!static/scripts/web_editor.css']);

$tpl->display('web/_attach.tpl');







>
>
>
>
|
>
>
>
|
>
>








32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
}, $csrf_key);


$form->runIf('upload', function () use ($page) {
	$new_file = File::uploadMultiple(Utils::dirname($page->file_path), 'file');
}, $csrf_key);

$files = null;
$images = null;

if (isset($_GET['files'])) {
	$files = $page->getAttachmentsGallery(true);
}

if (isset($_GET['images'])) {
	$images = $page->getImageGallery(true);
}

$max_size = Utils::getMaxUploadSize();

$tpl->assign(compact('page', 'files', 'images', 'max_size', 'csrf_key'));

$tpl->assign('custom_js', ['web_files.js']);
$tpl->assign('custom_css', ['!static/scripts/web_editor.css']);

$tpl->display('web/_attach.tpl');