diff --git a/assets/css/code.css b/assets/css/code.css
new file mode 100644
index 0000000..c11cf39
--- /dev/null
+++ b/assets/css/code.css
@@ -0,0 +1,161 @@
+/**
+ * Code block styles
+ *
+ * Frontend and editor preview styles for the Zeitfresser code block feature.
+ * The selectors are scoped to avoid leaking into unrelated blocks or plugins.
+ */
+
+/* -------------------------------------------------------------------------
+ Code block wrapper
+------------------------------------------------------------------------- */
+
+.ztfr-code {
+ position: relative;
+ background-color: var(--footer-color);
+ color: var(--light-color);
+ padding: 1.1rem 1.2rem;
+ margin: 1rem 0;
+ border-radius: 6px;
+ max-width: 100%;
+ overflow-x: auto;
+ font-family: var(--secondary-font);
+ font-size: 0.870rem;
+ line-height: 1.6;
+ font-weight: 400;
+ border: 1px solid rgba(248, 248, 242, 0.08);
+}
+
+/* -------------------------------------------------------------------------
+ Prism overrides
+------------------------------------------------------------------------- */
+
+.ztfr-code pre,
+.ztfr-code code {
+ background: transparent;
+ color: inherit;
+}
+
+.ztfr-code pre[class*="language-"],
+.ztfr-code code[class*="language-"] {
+ background: transparent !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ white-space: pre-wrap !important;
+ word-break: break-word !important;
+ overflow-wrap: break-word !important;
+}
+
+.ztfr-code pre[class*="language-"] {
+ overflow-x: visible !important;
+}
+
+.ztfr-code pre code {
+ display: block;
+ padding: 1rem;
+ overflow-x: auto;
+ white-space: pre-wrap;
+ word-break: break-word;
+ overflow-wrap: break-word;
+}
+
+/* -------------------------------------------------------------------------
+ Copy button
+------------------------------------------------------------------------- */
+
+.ztfr-code__copy {
+ position: absolute;
+ top: 0.75rem;
+ right: 0.75rem;
+ background-color: var(--footer-color);
+ color: var(--light-color);
+ border: 1px solid rgba(248, 248, 242, 0.12);
+ border-radius: 4px;
+ font-size: 0.72rem;
+ line-height: 1;
+ padding: 0.45rem 0.65rem;
+ cursor: pointer;
+ opacity: 0;
+ pointer-events: none;
+ transition:
+ opacity 0.2s ease,
+ background-color 0.2s ease,
+ color 0.2s ease,
+ border-color 0.2s ease;
+}
+
+.ztfr-code:hover .ztfr-code__copy {
+ opacity: 1;
+ pointer-events: auto;
+}
+
+.ztfr-code__copy:hover {
+ background-color: var(--hover-color);
+ color: #f8f8f2;
+}
+
+.ztfr-code__copy:focus {
+ opacity: 1;
+ pointer-events: auto;
+
+ outline: 2px solid #bd93f9;
+ outline-offset: 2px;
+}
+
+/* -------------------------------------------------------------------------
+ Dracula token colors
+------------------------------------------------------------------------- */
+
+.ztfr-code .token.comment,
+.ztfr-code .token.prolog,
+.ztfr-code .token.doctype,
+.ztfr-code .token.cdata {
+ color: #6272a4;
+}
+
+.ztfr-code .token.punctuation {
+ color: #f8f8f2;
+}
+
+.ztfr-code .token.tag,
+.ztfr-code .token.constant,
+.ztfr-code .token.symbol,
+.ztfr-code .token.deleted {
+ color: #ff79c6;
+}
+
+.ztfr-code .token.attr-name,
+.ztfr-code .token.property,
+.ztfr-code .token.selector,
+.ztfr-code .token.important,
+.ztfr-code .token.atrule {
+ color: #8be9fd;
+}
+
+.ztfr-code .token.attr-value,
+.ztfr-code .token.string,
+.ztfr-code .token.char,
+.ztfr-code .token.inserted {
+ color: #f1fa8c;
+}
+
+.ztfr-code .token.keyword,
+.ztfr-code .token.boolean,
+.ztfr-code .token.number {
+ color: #bd93f9;
+}
+
+.ztfr-code .token.operator,
+.ztfr-code .token.entity,
+.ztfr-code .token.url {
+ color: #f8f8f2;
+}
+
+.ztfr-code .token.function,
+.ztfr-code .token.class-name {
+ color: #50fa7b;
+}
+
+.block-editor-block-list__layout .ztfr-code,
+.editor-styles-wrapper .ztfr-code {
+ margin: 0;
+}
diff --git a/assets/css/editor.css b/assets/css/editor.css
new file mode 100644
index 0000000..5ba140d
--- /dev/null
+++ b/assets/css/editor.css
@@ -0,0 +1,116 @@
+/**
+ * Editor styles
+ *
+ * Scoped styles for Gutenberg and Classic Editor.
+ */
+
+/* -------------------------------------------------------------------------
+ Editor base
+------------------------------------------------------------------------- */
+
+.editor-styles-wrapper,
+.mce-content-body {
+ font-family: var(--secondary-font);
+ line-height: 1.7;
+}
+
+/* -------------------------------------------------------------------------
+ Shared code block preview
+------------------------------------------------------------------------- */
+
+.editor-styles-wrapper .ztfr-code,
+.editor-styles-wrapper pre.language-yaml,
+.mce-content-body pre.language-yaml {
+ position: relative;
+ background-color: #282a36;
+ color: #f8f8f2;
+ border: 1px solid rgba(248, 248, 242, 0.08);
+ border-radius: 6px;
+ padding: 1rem 1.2rem;
+ margin: 1rem 0;
+ max-width: 100%;
+ overflow-x: auto;
+ font-family: var(--secondary-font);
+ font-size: 0.95rem;
+ line-height: 1.7;
+ box-sizing: border-box;
+}
+
+/* -------------------------------------------------------------------------
+ Gutenberg preview
+------------------------------------------------------------------------- */
+
+.editor-styles-wrapper .ztfr-code pre,
+.editor-styles-wrapper .ztfr-code code {
+ background: transparent;
+ color: inherit;
+}
+
+.editor-styles-wrapper .ztfr-code pre.language-yaml,
+.editor-styles-wrapper .ztfr-code code.language-yaml {
+ background: transparent !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ white-space: pre-wrap !important;
+ word-break: break-word !important;
+ overflow-wrap: break-word !important;
+}
+
+.editor-styles-wrapper .ztfr-code pre code {
+ display: block;
+ white-space: pre-wrap;
+ word-break: break-word;
+ overflow-wrap: break-word;
+}
+
+/* -------------------------------------------------------------------------
+ Classic Editor preview
+------------------------------------------------------------------------- */
+
+.mce-content-body pre.language-yaml {
+ white-space: pre-wrap;
+ word-break: break-word;
+ overflow-wrap: break-word;
+}
+
+.mce-content-body pre.language-yaml code.language-yaml {
+ display: block;
+ background: transparent;
+ color: inherit;
+ padding: 0;
+ margin: 0;
+ white-space: pre-wrap;
+ word-break: break-word;
+ overflow-wrap: break-word;
+}
+
+/* -------------------------------------------------------------------------
+ Editor label
+------------------------------------------------------------------------- */
+
+.editor-styles-wrapper .ztfr-code.is-editor-preview::before,
+.mce-content-body pre.language-yaml::before {
+ content: "YAML";
+ display: inline-block;
+ margin-bottom: 0.75rem;
+ padding: 0.2rem 0.45rem;
+ border-radius: 4px;
+ background: #44475a;
+ color: #f8f8f2;
+ font-size: 0.72rem;
+ line-height: 1;
+ letter-spacing: 0.03em;
+}
+
+/* -------------------------------------------------------------------------
+ Lists
+------------------------------------------------------------------------- */
+
+.editor-styles-wrapper ul,
+.editor-styles-wrapper ol,
+.mce-content-body ul,
+.mce-content-body ol {
+ margin-left: 0;
+ padding-left: 1.25em;
+ list-style-position: outside;
+}
diff --git a/assets/js/code-block.js b/assets/js/code-block.js
new file mode 100644
index 0000000..772f6c6
--- /dev/null
+++ b/assets/js/code-block.js
@@ -0,0 +1,94 @@
+/**
+ * Code Block UI Enhancements
+ *
+ * Handles:
+ * - Copy button
+ * - Prism highlight trigger
+ */
+
+(function () {
+ 'use strict';
+
+ function copyText(text, onSuccess, onError) {
+ if (!text) {
+ return;
+ }
+
+ if (navigator.clipboard && window.isSecureContext) {
+ navigator.clipboard.writeText(text).then(onSuccess).catch(onError);
+ return;
+ }
+
+ const textarea = document.createElement('textarea');
+ textarea.value = text;
+ textarea.setAttribute('readonly', 'readonly');
+ textarea.style.position = 'fixed';
+ textarea.style.opacity = '0';
+ textarea.style.pointerEvents = 'none';
+
+ document.body.appendChild(textarea);
+ textarea.focus();
+ textarea.select();
+
+ try {
+ document.execCommand('copy');
+ onSuccess();
+ } catch (error) {
+ onError();
+ }
+
+ document.body.removeChild(textarea);
+ }
+
+ function initCodeUI() {
+ const wrappers = document.querySelectorAll('.ztfr-code');
+
+ if (!wrappers.length) {
+ return;
+ }
+
+ wrappers.forEach(function (wrapper) {
+ const code = wrapper.querySelector('code');
+
+ if (!code) {
+ return;
+ }
+
+ if (!wrapper.querySelector('.ztfr-code__copy')) {
+ const button = document.createElement('button');
+ button.className = 'ztfr-code__copy';
+ button.type = 'button';
+ button.setAttribute('aria-label', 'Copy code');
+ button.textContent = 'Copy';
+
+ button.addEventListener('click', function () {
+ const text = code.textContent;
+
+ copyText(
+ text,
+ function () {
+ button.textContent = 'Copied';
+ window.setTimeout(function () {
+ button.textContent = 'Copy';
+ }, 2000);
+ },
+ function () {
+ button.textContent = 'Error';
+ window.setTimeout(function () {
+ button.textContent = 'Copy';
+ }, 2000);
+ }
+ );
+ });
+
+ wrapper.appendChild(button);
+ }
+ });
+
+ if (typeof Prism !== 'undefined') {
+ Prism.highlightAll();
+ }
+ }
+
+ document.addEventListener('DOMContentLoaded', initCodeUI);
+})();
diff --git a/assets/js/editor.js b/assets/js/editor.js
new file mode 100644
index 0000000..d96a8b1
--- /dev/null
+++ b/assets/js/editor.js
@@ -0,0 +1,113 @@
+(function () {
+ 'use strict';
+
+ /**
+ * Gutenberg block
+ */
+ if (
+ window.wp &&
+ window.wp.blocks &&
+ window.wp.element &&
+ window.wp.i18n &&
+ window.wp.components &&
+ window.wp.blockEditor
+ ) {
+ const blocks = window.wp.blocks;
+ const element = window.wp.element;
+ const i18n = window.wp.i18n;
+ const blockEditor = window.wp.blockEditor;
+
+ const el = element.createElement;
+ const __ = i18n.__;
+ const PlainText = blockEditor.PlainText;
+
+ blocks.registerBlockType('ztfr/code-block', {
+ title: __('Code', 'zeitfresser'),
+ icon: 'editor-code',
+ category: 'formatting',
+ description: __('Insert a styled YAML code block.', 'zeitfresser'),
+ supports: {
+ html: false
+ },
+ attributes: {
+ content: {
+ type: 'string',
+ default: ''
+ }
+ },
+
+ edit: function (props) {
+ const content = props.attributes.content || '';
+
+ return el(
+ 'div',
+ {
+ className: 'ztfr-code is-editor-preview',
+ 'data-language': 'yaml'
+ },
+ el(
+ 'pre',
+ { className: 'language-yaml' },
+ el(PlainText, {
+ tagName: 'code',
+ className: 'language-yaml',
+ value: content,
+ placeholder: __('Write or paste YAML code hereā¦', 'zeitfresser'),
+ onChange: function (value) {
+ props.setAttributes({ content: value });
+ }
+ })
+ )
+ );
+ },
+
+ save: function (props) {
+ const content = props.attributes.content || '';
+
+ return el(
+ 'pre',
+ { className: 'language-yaml' },
+ el(
+ 'code',
+ { className: 'language-yaml' },
+ content
+ )
+ );
+ }
+ });
+ }
+
+ /**
+ * Classic Editor TinyMCE button
+ */
+ if (window.tinymce && window.tinymce.PluginManager) {
+ function escapeHtml(text) {
+ return String(text)
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''');
+ }
+
+ window.tinymce.PluginManager.add('ztfr_code_block', function (editor) {
+ function insertCodeBlock() {
+ const selectedText = editor.selection.getContent({ format: 'text' });
+ const code = selectedText || 'your_key: your_value';
+ const safeCode = escapeHtml(code);
+
+ editor.insertContent(
+ '
' +
+ safeCode +
+ '
'
+ );
+ }
+
+ editor.addButton('ztfr_code_block', {
+ text: 'Code',
+ icon: false,
+ onclick: insertCodeBlock
+ });
+ });
+ }
+})();
diff --git a/assets/js/prism.js b/assets/js/prism.js
new file mode 100644
index 0000000..f0c9bed
--- /dev/null
+++ b/assets/js/prism.js
@@ -0,0 +1,8 @@
+/* PrismJS 1.30.0
+https://prismjs.com/download#themes=prism&languages=markup+css+clike+javascript+yaml */
+var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var P=w.value;if(n.length>e.length)return;if(!(P instanceof i)){var E,S=1;if(y){if(!(E=l(b,A,e,m))||E.index>=e.length)break;var L=E.index,O=E.index+E[0].length,C=A;for(C+=w.value.length;L>=C;)C+=(w=w.next).value.length;if(A=C-=w.value.length,w.value instanceof i)continue;for(var j=w;j!==n.tail&&(Cg.reach&&(g.reach=W);var I=w.prev;if(_&&(I=u(n,I,_),A+=_.length),c(n,I,S),w=u(n,I,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),S>1){var T={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,T),g&&T.reach>g.reach&&(g.reach=T.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""+i.tag+">"},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
+Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml;
+!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism);
+Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/};
+Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript;
+!function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",a="(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*".replace(//g,(function(){return"[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]"})),d="\"(?:[^\"\\\\\r\n]|\\\\.)*\"|'(?:[^'\\\\\r\n]|\\\\.)*'";function o(e,n){n=(n||"").replace(/m/g,"")+"m";var r="([:\\-,[{]\\s*(?:\\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\\]|\\}|(?:[\r\n]\\s*)?#))".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return e}));return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp("([\\-:]\\s*(?:\\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\\S[^\r\n]*(?:\\2[^\r\n]+)*)".replace(/<>/g,(function(){return t}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp("((?:^|[:\\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\\s*:\\s)".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return"(?:"+a+"|"+d+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("false|true","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism);
diff --git a/editor-style.css b/editor-style.css
deleted file mode 100644
index 35be90c..0000000
--- a/editor-style.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/* Align lists in the Classic Editor */
-ul, ol {
- margin-left: 0 !important;
- padding-left: 1.0em !important;
- list-style-position: inside !important;
-}
-
diff --git a/functions.php b/functions.php
index c0ecf23..4ae8467 100644
--- a/functions.php
+++ b/functions.php
@@ -51,6 +51,7 @@ require get_template_directory() . '/inc/utilities/toc.php';
* ------------------------------------------------------------------------
*/
require get_template_directory() . '/inc/tools/image-optimizer.php';
+require get_template_directory() . '/inc/tools/code-block.php';
/**
* ------------------------------------------------------------------------
@@ -142,8 +143,6 @@ function zeitfresser_setup() {
register_nav_menus( array(
'menu-1' => esc_html__( 'Primary', 'zeitfresser' ),
));
-
- add_editor_style( 'editor-style.css' );
}
add_action( 'after_setup_theme', 'zeitfresser_setup' );
@@ -248,6 +247,13 @@ function zeitfresser_scripts() {
}
add_action( 'wp_enqueue_scripts', 'zeitfresser_scripts', 10 );
+// Editor Styles
+function zeitfresser_editor_styles_setup() {
+ add_theme_support( 'editor-styles' );
+ add_editor_style( 'assets/css/editor.css' );
+}
+add_action( 'after_setup_theme', 'zeitfresser_editor_styles_setup' );
+
/**
* ------------------------------------------------------------------------
* Performance Tweaks
@@ -693,11 +699,3 @@ function zeitfresser_responsive_image_sizes( $sizes, $size ) {
return $sizes;
}
add_filter( 'wp_calculate_image_sizes', 'zeitfresser_responsive_image_sizes', 10, 2 );
-
-/**
- * Delete Cookie Button
- */
- add_filter( 'comment_form_default_fields', function( $fields ) {
- unset( $fields['cookies'] );
- return $fields;
-});
diff --git a/inc/tools/code-block.php b/inc/tools/code-block.php
new file mode 100644
index 0000000..dd227ed
--- /dev/null
+++ b/inc/tools/code-block.php
@@ -0,0 +1,211 @@
+]*)>]*)>(.*?)<\/code><\/pre>/s',
+ function ( $matches ) {
+
+ $pre_attrs = $matches[1];
+ $code_attrs = $matches[2];
+ $code = $matches[3];
+
+ if ( false === strpos( $pre_attrs, 'language-' ) ) {
+ $pre_attrs .= ' class="language-yaml"';
+ }
+
+ if ( false === strpos( $code_attrs, 'language-' ) ) {
+ $code_attrs .= ' class="language-yaml"';
+ }
+
+ return sprintf(
+ '',
+ $pre_attrs,
+ $code_attrs,
+ $code
+ );
+ },
+ $content
+ );
+
+ return $content;
+}
+add_filter( 'the_content', 'ztfr_wrap_code_blocks', 20 );
diff --git a/inc/utilities/helpers.php b/inc/utilities/helpers.php
index 04f29ad..d6fc024 100644
--- a/inc/utilities/helpers.php
+++ b/inc/utilities/helpers.php
@@ -224,3 +224,11 @@ if ( ! function_exists( 'zeitfresser_asset' ) ) {
return get_template_directory_uri() . '/assets/' . ltrim($path, '/');
}
}
+
+/**
+ * Delete Cookie Button
+ */
+ add_filter( 'comment_form_default_fields', function( $fields ) {
+ unset( $fields['cookies'] );
+ return $fields;
+});
diff --git a/style.css b/style.css
index d440da9..25a1717 100644
--- a/style.css
+++ b/style.css
@@ -5,7 +5,7 @@ Author: Zeitfresser
Author URI: https://ztfr.eu/
Theme URI: https://ztfr.eu/
Description: Zeitfresser Wordpress Theme
-Version: 2.5
+Version: 2.6
Tested up to: 6.2
Requires PHP: 7.0
License: GNU General Public License v2 or later