Wiki source code of Linkding + SingleFile Test

Version 12.1 by XWikiGuest on 2026/03/11 20:55

Show last authors
1 = Linkding + SingleFile Test =
2
3 Bookmarks met archief-viewer. Klik op het archief-icoon om de opgeslagen versie te bekijken.
4
5 {{html clean="false"}}
6 <style>
7 #ldsf-container {
8 display: flex;
9 height: 75vh;
10 border: 1px solid #4e5d6c;
11 border-radius: 4px;
12 overflow: hidden;
13 background: #1a2a3a;
14 }
15 #ldsf-left {
16 width: 35%;
17 min-width: 200px;
18 max-width: 60%;
19 overflow-y: auto;
20 background: #2b3e50;
21 display: flex;
22 flex-direction: column;
23 }
24 #ldsf-divider {
25 width: 6px;
26 background: #4e5d6c;
27 cursor: col-resize;
28 flex-shrink: 0;
29 transition: background 0.2s;
30 }
31 #ldsf-divider:hover, #ldsf-divider.dragging { background: #df691a; }
32 #ldsf-right {
33 flex: 1;
34 min-width: 200px;
35 display: flex;
36 flex-direction: column;
37 background: #fff;
38 }
39 #ldsf-status { color: #6b7c8d; font-size: 13px; padding: 8px 12px; flex-shrink: 0; }
40 #ldsf-bookmarks { overflow-y: auto; flex: 1; }
41 #ldsf-bookmarks ul { list-style: none; padding: 0; margin: 0; }
42 #ldsf-bookmarks li {
43 padding: 6px 12px;
44 border-bottom: 1px solid rgba(78,93,108,0.3);
45 display: flex;
46 align-items: center;
47 gap: 8px;
48 }
49 #ldsf-bookmarks li:hover { background: #3b4e60; }
50 #ldsf-bookmarks a {
51 color: #5bc0de;
52 text-decoration: none;
53 white-space: nowrap;
54 overflow: hidden;
55 text-overflow: ellipsis;
56 font-size: 13px;
57 }
58 #ldsf-bookmarks a:hover { color: #df691a; }
59 #ldsf-bookmarks .sf-btn {
60 cursor: pointer;
61 background: #4e5d6c;
62 border: none;
63 color: #5bc0de;
64 padding: 2px 6px;
65 border-radius: 3px;
66 font-size: 13px;
67 flex-shrink: 0;
68 }
69 #ldsf-bookmarks .sf-btn:hover { background: #df691a; color: #fff; }
70 #ldsf-viewer-bar {
71 display: none;
72 justify-content: space-between;
73 align-items: center;
74 padding: 4px 12px;
75 background: #2b3e50;
76 color: #6b7c8d;
77 font-size: 12px;
78 flex-shrink: 0;
79 border-bottom: 1px solid #4e5d6c;
80 }
81 #ldsf-viewer-bar .close-btn {
82 cursor: pointer;
83 background: none;
84 border: none;
85 color: #d9534f;
86 font-size: 18px;
87 padding: 0 4px;
88 }
89 #ldsf-viewer-bar .close-btn:hover { color: #ff6b6b; }
90 #ldsf-viewer-frame {
91 width: 100%;
92 flex: 1;
93 border: none;
94 background: #fff;
95 }
96 #ldsf-placeholder {
97 display: flex;
98 align-items: center;
99 justify-content: center;
100 flex: 1;
101 color: #6b7c8d;
102 font-size: 16px;
103 background: #2b3e50;
104 }
105 </style>
106
107 <div id="ldsf-container">
108 <div id="ldsf-left">
109 <div id="ldsf-status">Laden...</div>
110 <div id="ldsf-bookmarks"></div>
111 </div>
112 <div id="ldsf-divider"></div>
113 <div id="ldsf-right">
114 <div id="ldsf-viewer-bar">
115 <span id="ldsf-viewer-title">...</span>
116 <span class="close-btn" data-sfclose="1">&times;</span>
117 </div>
118 <div id="ldsf-placeholder">Klik op &#128196; om archief te bekijken</div>
119 <iframe id="ldsf-viewer-frame" sandbox="allow-same-origin" style="display:none"></iframe>
120 </div>
121 </div>
122
123 <script>
124 var LDSF_LINKDING_URL = 'https://bookmarks.rhebergen.org/api/bookmarks/';
125 var LDSF_TOKEN = '3b7443e0f84e2b2b269adebb96d7475e4a5e653e';
126 var LDSF_TAG = 'Nuclear-&-Energy';
127 var LDSF_COUNT = 20;
128 var LDSF_SHARE = 'eT2X9ttBHK5GoEY';
129 var LDSF_WEBDAV = 'https://cloud.rhebergen.org/public.php/webdav/';
130 var LDSF_AUTH = 'Basic ' + btoa(LDSF_SHARE + ':');
131 var ldsf_urlToFile = {};
132 var ldsf_archiveMap = {};
133
134 function ldsfFindArchive(url) {
135 var v = [url, url.replace(/\/$/, ''), url + '/', url.replace(/\?.*$/, '')];
136 for (var i = 0; i < v.length; i++) { if (ldsf_urlToFile[v[i]]) return ldsf_urlToFile[v[i]]; }
137 return null;
138 }
139
140 function ldsfOpen(idx) {
141 var f = ldsf_archiveMap[idx];
142 if (f) ldsfShowArchive(f);
143 }
144
145 function ldsfShowArchive(filename) {
146 document.getElementById('ldsf-viewer-title').textContent = filename.replace(/\.html?$/i, '');
147 document.getElementById('ldsf-viewer-bar').style.display = 'flex';
148 document.getElementById('ldsf-placeholder').style.display = 'none';
149 var frame = document.getElementById('ldsf-viewer-frame');
150 frame.style.display = 'block';
151 frame.srcdoc = '<p style="padding:20px;color:#666">Laden...</p>';
152 fetch(LDSF_WEBDAV + encodeURIComponent(filename), { headers: { 'Authorization': LDSF_AUTH } })
153 .then(function(r) { return r.text(); })
154 .then(function(html) { frame.srcdoc = html; })
155 .catch(function(err) { frame.srcdoc = '<p style="padding:20px;color:red">Fout: ' + err.message + '</p>'; });
156 }
157
158 function ldsfCloseViewer() {
159 document.getElementById('ldsf-viewer-bar').style.display = 'none';
160 document.getElementById('ldsf-viewer-frame').style.display = 'none';
161 document.getElementById('ldsf-placeholder').style.display = 'flex';
162 }
163
164 function ldsfLoadBookmarks() {
165 var apiUrl = LDSF_LINKDING_URL + '?limit=' + LDSF_COUNT + '&q=%23' + encodeURIComponent(LDSF_TAG);
166 fetch(apiUrl, { headers: { 'Authorization': 'Token ' + LDSF_TOKEN } })
167 .then(function(r) { return r.json(); })
168 .then(function(data) {
169 var total = data.count || 0;
170 var archiveCount = 0;
171 var container = document.getElementById('ldsf-bookmarks');
172 var html = '<ul>';
173
174 (data.results || []).forEach(function(bm, idx) {
175 var title = bm.title || bm.website_title || bm.url;
176 var fname = ldsfFindArchive(bm.url);
177 if (fname) { archiveCount++; ldsf_archiveMap[String(idx)] = fname; }
178 html += '<li>';
179 if (fname) html += '<span class="sf-btn" data-sfidx="' + idx + '" title="Archief bekijken">&#128196;</span>';
180 html += '<a href="' + bm.url + '" target="_blank">' + title + '</a></li>';
181 });
182
183 html += '</ul>';
184 container.innerHTML = html;
185 document.getElementById('ldsf-status').textContent = total + ' bookmarks, ' + archiveCount + ' met archief';
186 })
187 .catch(function(err) { document.getElementById('ldsf-status').textContent = 'Fout: ' + err.message; });
188 }
189
190 // Global click handler for archive buttons and close button
191 document.addEventListener('click', function(e) {
192 var el = e.target;
193 if (el && el.getAttribute) {
194 if (el.getAttribute('data-sfidx') !== null) {
195 var idx = el.getAttribute('data-sfidx');
196 if (ldsf_archiveMap[idx]) ldsfShowArchive(ldsf_archiveMap[idx]);
197 }
198 if (el.getAttribute('data-sfclose') !== null) {
199 ldsfCloseViewer();
200 }
201 }
202 }, true);
203
204 // Draggable divider
205 var ldsf_divider = document.getElementById('ldsf-divider');
206 var ldsf_left = document.getElementById('ldsf-left');
207 var ldsf_dragging = false;
208
209 ldsf_divider.addEventListener('mousedown', function(e) {
210 ldsf_dragging = true;
211 ldsf_divider.classList.add('dragging');
212 e.preventDefault();
213 });
214 document.addEventListener('mousemove', function(e) {
215 if (!ldsf_dragging) return;
216 var container = document.getElementById('ldsf-container');
217 var rect = container.getBoundingClientRect();
218 var w = e.clientX - rect.left;
219 if (w >= 200 && w <= rect.width * 0.6) ldsf_left.style.width = w + 'px';
220 });
221 document.addEventListener('mouseup', function() {
222 if (ldsf_dragging) { ldsf_dragging = false; ldsf_divider.classList.remove('dragging'); }
223 });
224
225 // Load index then bookmarks
226 fetch(LDSF_WEBDAV + 'index.json', { headers: { 'Authorization': LDSF_AUTH } })
227 .then(function(r) { return r.ok ? r.json() : {}; })
228 .then(function(idx) {
229 Object.keys(idx).forEach(function(f) { ldsf_urlToFile[idx[f]] = f; });
230 ldsfLoadBookmarks();
231 })
232 .catch(function() { ldsfLoadBookmarks(); });
233 </script>
234 {{/html}}