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+""},!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"},/&#x?[\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( + '
%s
', + $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