diff --git a/netbox_documentation/templates/netbox_documentation/document.html b/netbox_documentation/templates/netbox_documentation/document.html
index 7dfa96e..d1a11e1 100644
--- a/netbox_documentation/templates/netbox_documentation/document.html
+++ b/netbox_documentation/templates/netbox_documentation/document.html
@@ -40,6 +40,29 @@
.documentation-content .doc-cell-blue { background: #dbeafe !important; color: #212529; }
.documentation-content .doc-cell-middle { vertical-align: middle !important; }
.documentation-content p { max-width: 90rem; }
+ .documentation-content .doc-code-block { position: relative; margin: 0 0 1rem; }
+ .documentation-content pre {
+ margin: 0;
+ padding: .85rem 4.5rem .85rem 1rem;
+ background: #1e1e1e !important;
+ color: #e9ecef !important;
+ border-radius: 6px;
+ font-family: Consolas, 'Courier New', monospace;
+ font-size: 10pt;
+ line-height: 1.5;
+ white-space: pre-wrap;
+ overflow-x: auto;
+ }
+ .documentation-content pre * { background: transparent !important; font-family: inherit !important; }
+ .documentation-content pre ::selection,
+ .documentation-content pre::selection { background: #4c8bf5 !important; color: #fff !important; }
+ .documentation-content .doc-code-copy {
+ position: absolute; top: .4rem; right: .4rem;
+ padding: .15rem .5rem; font-size: .75rem;
+ color: #e9ecef; background: rgba(255,255,255,.1);
+ border: 1px solid rgba(255,255,255,.25); border-radius: 4px;
+ }
+ .documentation-content .doc-code-copy:hover { background: rgba(255,255,255,.2); }
.documentation-content table { cursor: zoom-in; }
#documentation-viewer.documentation-page-focus {
position: fixed;
@@ -120,6 +143,36 @@
openViewer();
});
});
+ viewer.querySelectorAll('.documentation-content pre').forEach(pre => {
+ const wrapper = document.createElement('div');
+ wrapper.className = 'doc-code-block';
+ pre.parentNode.insertBefore(wrapper, pre);
+ wrapper.appendChild(pre);
+ const copyButton = document.createElement('button');
+ copyButton.type = 'button';
+ copyButton.className = 'doc-code-copy';
+ copyButton.innerHTML = ' Kopieren';
+ copyButton.addEventListener('click', async () => {
+ const text = pre.innerText.replace(/
+$/, '');
+ try {
+ await navigator.clipboard.writeText(text);
+ } catch (error) {
+ // Fallback for plain-HTTP deployments without Clipboard API.
+ const area = document.createElement('textarea');
+ area.value = text;
+ area.style.position = 'fixed';
+ area.style.opacity = '0';
+ document.body.appendChild(area);
+ area.select();
+ document.execCommand('copy');
+ area.remove();
+ }
+ copyButton.innerHTML = ' Kopiert';
+ setTimeout(() => { copyButton.innerHTML = ' Kopieren'; }, 1500);
+ });
+ wrapper.appendChild(copyButton);
+ });
document.addEventListener('keydown', event => {
if (event.key === 'Escape' && viewer.classList.contains('documentation-page-focus')) closeViewer();
});
diff --git a/netbox_documentation/templates/netbox_documentation/document_edit.html b/netbox_documentation/templates/netbox_documentation/document_edit.html
index 4a8c2e5..2f86f61 100644
--- a/netbox_documentation/templates/netbox_documentation/document_edit.html
+++ b/netbox_documentation/templates/netbox_documentation/document_edit.html
@@ -31,10 +31,10 @@
license_key: 'gpl',
height: 650,
menubar: 'file edit view insert format tools table help',
- plugins: 'advlist anchor autolink charmap code fullscreen image link lists media preview searchreplace table visualblocks wordcount',
+ plugins: 'advlist anchor autolink charmap code codesample fullscreen image link lists media preview searchreplace table visualblocks wordcount',
toolbar: [
'undo redo | blocks styles fontfamily fontsize | bold italic underline strikethrough | forecolor backcolor',
- 'alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table tablecellcolor link image media | removeformat code fullscreen'
+ 'alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table tablecellcolor link image media codesample | removeformat code fullscreen'
],
toolbar_mode: 'sliding',
table_toolbar: 'tableprops tablecellprops tablecellcolor | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol | tablemergecells tablesplitcells | tabledelete',
@@ -88,9 +88,24 @@
.doc-cell-red { background: #ffe3e3 !important; }
.doc-cell-blue { background: #dbeafe !important; }
.doc-cell-middle { vertical-align: middle !important; }
+ pre { background: #1e1e1e; color: #e9ecef; padding: .75rem 1rem; border-radius: 6px; font-family: Consolas, 'Courier New', monospace; font-size: 10pt; white-space: pre-wrap; }
+ pre ::selection, pre::selection { background: #4c8bf5; color: #fff; }
`,
+ codesample_global_prismjs: false,
+ codesample_languages: [
+ {text: 'Bash / Shell', value: 'bash'},
+ {text: 'PowerShell', value: 'powershell'},
+ {text: 'Cisco / Netzwerk-Konfiguration', value: 'none'},
+ {text: 'Python', value: 'python'},
+ {text: 'JSON', value: 'json'},
+ {text: 'YAML', value: 'yaml'},
+ {text: 'SQL', value: 'sql'},
+ {text: 'HTML/XML', value: 'markup'},
+ {text: 'JavaScript', value: 'javascript'},
+ {text: 'Nur Text', value: 'plaintext'}
+ ],
browser_spellcheck: true,
- contextmenu: 'link image table',
+ contextmenu: 'link image table codesample',
promotion: false,
branding: false,
convert_unsafe_embeds: true,