Changeset 3415636
- Timestamp:
- 12/09/2025 04:55:01 PM (4 months ago)
- Location:
- link-extension-for-xfn
- Files:
-
- 8 added
- 5 edited
-
assets/blueprints (added)
-
assets/blueprints/blueprint.json (added)
-
trunk/XFN-TESTING-GUIDE.md (added)
-
trunk/assets (added)
-
trunk/assets/blueprints (added)
-
trunk/assets/blueprints/blueprint.json (added)
-
trunk/build/index.asset.php (modified) (1 diff)
-
trunk/build/index.js (modified) (1 diff)
-
trunk/link-extension-for-xfn.php (modified) (1 diff)
-
trunk/readme.txt (modified) (6 diffs)
-
trunk/src/index.js (modified) (4 diffs)
-
trunk/xfn-checker.js (added)
-
trunk/xfn-test-page-content.html (added)
Legend:
- Unmodified
- Added
- Removed
-
link-extension-for-xfn/trunk/build/index.asset.php
r3415429 r3415636 1 <?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-rich-text'), 'version' => ' a7ec83b0894a6256c5f3');1 <?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-rich-text'), 'version' => '36fd7e2b8a644596151d'); -
link-extension-for-xfn/trunk/build/index.js
r3415429 r3415636 1 (()=>{"use strict";const e=window.wp.i18n,n=window.wp.hooks,o=window.wp.components,t=window.wp.blockEditor,l=window.wp.compose,i=(window.wp.element,window.wp.data,window.wp.richText),s=window.ReactJSXRuntime;(0,i.registerFormatType)("xfn-link-extension/xfn-rel",{title:(0,e.__)("XFN Relationship","link-extension-for-xfn"),tagName:"a",className:null,attributes:{rel:"rel",href:"href"},edit:()=>null}),console.log("[XFN] XFN format type registered");const r={friendship:{type:"radio",label:(0,e.__)("Friendship","link-extension-for-xfn"),description:(0,e.__)("Your friendship level (choose one)","link-extension-for-xfn"),options:[{label:(0,e.__)("Contact","link-extension-for-xfn"),value:"contact"},{label:(0,e.__)("Acquaintance","link-extension-for-xfn"),value:"acquaintance"},{label:(0,e.__)("Friend","link-extension-for-xfn"),value:"friend"}]},physical:{type:"checkbox",label:(0,e.__)("Physical","link-extension-for-xfn"),description:(0,e.__)("Have you met this person?","link-extension-for-xfn"),options:[{label:(0,e.__)("Met","link-extension-for-xfn"),value:"met"}]},professional:{type:"checkbox",label:(0,e.__)("Professional","link-extension-for-xfn"),description:(0,e.__)("Professional relationships","link-extension-for-xfn"),options:[{label:(0,e.__)("Co-worker","link-extension-for-xfn"),value:"co-worker"},{label:(0,e.__)("Colleague","link-extension-for-xfn"),value:"colleague"}]},geographical:{type:"radio",label:(0,e.__)("Geographical","link-extension-for-xfn"),description:(0,e.__)("Geographical relationship","link-extension-for-xfn"),options:[{label:(0,e.__)("Co-resident","link-extension-for-xfn"),value:"co-resident"},{label:(0,e.__)("Neighbor","link-extension-for-xfn"),value:"neighbor"}]},family:{type:"radio",label:(0,e.__)("Family","link-extension-for-xfn"),description:(0,e.__)("Family relationship","link-extension-for-xfn"),options:[{label:(0,e.__)("Child","link-extension-for-xfn"),value:"child"},{label:(0,e.__)("Parent","link-extension-for-xfn"),value:"parent"},{label:(0,e.__)("Sibling","link-extension-for-xfn"),value:"sibling"},{label:(0,e.__)("Spouse","link-extension-for-xfn"),value:"spouse"},{label:(0,e.__)("Kin","link-extension-for-xfn"),value:"kin"}]},romantic:{type:"checkbox",label:(0,e.__)("Romantic","link-extension-for-xfn"),description:(0,e.__)("Romantic relationships","link-extension-for-xfn"),options:[{label:(0,e.__)("Muse","link-extension-for-xfn"),value:"muse"},{label:(0,e.__)("Crush","link-extension-for-xfn"),value:"crush"},{label:(0,e.__)("Date","link-extension-for-xfn"),value:"date"},{label:(0,e.__)("Sweetheart","link-extension-for-xfn"),value:"sweetheart"}]},identity:{type:"checkbox",label:(0,e.__)("Identity","link-extension-for-xfn"),description:(0,e.__)("Is this your own content?","link-extension-for-xfn"),options:[{label:(0,e.__)("Me","link-extension-for-xfn"),value:"me"}]}};function c(e){if(!e)return{xfn:[],other:[]};const n=["contact","acquaintance","friend","met","co-worker","colleague","co-resident","neighbor","child","parent","sibling","spouse","kin","muse","crush","date","sweetheart","me"],o=e.split(/\s+/).filter(Boolean),t=[],l=[];return o.forEach(e=>{n.includes(e)?t.push(e):l.push(e)}),{xfn:t,other:l}}function a(e,n){const o=[...n,...e].filter(Boolean);return[...new Set(o)].join(" ")}function d(e,n){return e.rel?e.rel:e.metadata?.rel?e.metadata.rel:""}const u=({attributes:n,setAttributes:l,name:i})=>{const u=d(n),{xfn:p,other:g}=c(u),f=(e,o,t)=>{let i=[...p];if("radio"===r[e].type){const n=r[e].options.map(e=>e.value);i=i.filter(e=>!n.includes(e)),t&&i.push(o)}else t?i.includes(o)||i.push(o):i=i.filter(e=>e!==o);(e=>{const o=a(e,g);!function(e,n,o){e.hasOwnProperty("rel")?n({rel:o||void 0}):n({metadata:{...e.metadata||{},rel:o||void 0}})}(n,l,o)})(i)},b=["core/button","core/image","core/navigation-link","core/site-logo","core/post-title","core/query-title" ].includes(i);return(0,s.jsx)(t.InspectorControls,{children:(0,s.jsxs)(o.PanelBody,{title:(0,e.__)("XFN Relationships","link-extension-for-xfn"),initialOpen:b,className:"xfn-inspector-panel",children:[(0,s.jsx)("p",{className:"xfn-panel-description",children:(0,e.__)("Describe your relationship to the people or organizations you link to using XFN (XHTML Friends Network) markup.","link-extension-for-xfn")}),Object.entries(r).map(([n,t])=>{if("radio"===t.type){const l=t.options.find(e=>p.includes(e.value))?.value||"",i=[{label:(0,e.__)("None","link-extension-for-xfn"),value:""},...t.options];return(0,s.jsx)("div",{className:"xfn-category-section",children:(0,s.jsx)(o.RadioControl,{label:t.label,help:t.description,selected:l,options:i,onChange:e=>{f(n,e,""!==e)}})},n)}return(0,s.jsxs)("div",{className:"xfn-category-section",children:[(0,s.jsx)("h4",{className:"xfn-category-title",children:t.label}),(0,s.jsx)("p",{className:"xfn-category-help",children:t.description}),t.options.map(e=>(0,s.jsx)(o.CheckboxControl,{label:e.label,checked:p.includes(e.value),onChange:o=>{f(n,e.value,o)}},e.value))]},n)}),p.length>0&&(0,s.jsxs)("div",{className:"xfn-selected-summary",children:[(0,s.jsx)("h4",{children:(0,e.__)("Selected Relationships:","link-extension-for-xfn")}),(0,s.jsx)("div",{className:"xfn-pills",children:p.map(e=>(0,s.jsx)("span",{className:`xfn-pill xfn-pill-${e}`,children:e},e))})]})]})})};let p=[],g=[],f=null,b=null;function x(){setTimeout(()=>{const n=document.querySelector(".block-editor-link-control");if(!n)return;const o=n.querySelector(".block-editor-link-control__tools .components-button");if(!o)return;if("true"!==o.getAttribute("aria-expanded"))return;const t=n.querySelector(".block-editor-link-control__settings");if(!t)return;if(t.querySelector(".xfn-collapsible-section"))return;console.log("[XFN] Attempting to find link value from React...");const l=n,i=Object.keys(l).find(e=>e.startsWith("__react"));if(i){const e=l[i];console.log("[XFN] React instance found:",e);let n=e,o=0;for(;n&&o<10;){if(n.memoizedProps?.value){b=n.memoizedProps.value,f=n.memoizedProps.onChange,window.currentLinkValue=b,window.currentLinkOnChange=f,console.log("[XFN] Found link value:",b),console.log("[XFN] Link value keys:",Object.keys(b)),console.log("[XFN] Link value rel:",b.rel),console.log("[XFN] Found onChange:",f);break}n=n.return||n._owner,o++}}console.log("[XFN] Looking for rel input in link control...");const s=t.querySelectorAll("input");console.log("[XFN] All inputs in settings panel:",s),s.forEach((e,n)=>{console.log(`[XFN] Input ${n}:`,{type:e.type,id:e.id,name:e.name,placeholder:e.placeholder,value:e.value,element:e})});let u=n.querySelector('input[type="text"][placeholder*="rel" i]');if(console.log("[XFN] Try 1 (placeholder*=rel):",u),u||(u=n.querySelector('input[id*="rel" i]'),console.log("[XFN] Try 2 (id*=rel):",u)),!u){const e=t.querySelectorAll('input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"])');console.log("[XFN] Try 3 - text-like inputs in settings:",e),e.length>0&&(u=e[e.length-1])}console.log("[XFN] Final rel input found:",!!u),u&&(console.log("[XFN] Rel input element:",u),console.log("[XFN] Rel input current value:",u.value));let x="";const h=wp.data.select("core/block-editor").getSelectedBlock();if(h&&["core/button","core/image","core/navigation-link","core/site-logo","core/post-title","core/query-title"].includes(h.name))x=d(h.attributes,h.name),console.log("[XFN] Got rel from block-level link attributes:",x);else if(b?.url&&h?.attributes?.content){let e=h.attributes.content;if("object"==typeof e&&e.toHTMLString&&(e=e.toHTMLString()),"string"==typeof e&&e.includes(b.url)){const n=(new DOMParser).parseFromString(e,"text/html"),o=Array.from(n.querySelectorAll("a")).find(e=>e.getAttribute("href")===b.url);o&&(x=o.getAttribute("rel")||"",console.log("[XFN] Got rel from existing link in content:",x))}}!x&&b&&b.rel?(x=b.rel,console.log("[XFN] Got rel from link value:",x)):!x&&u&&(x=u.value,console.log("[XFN] Got rel from input:",x));const{xfn:N,other:F}=c(x);p=[...N],g=[...F],console.log("[XFN] Initial XFN values:",p),console.log("[XFN] Initial other values:",g);const m=document.createElement("div");m.className="xfn-collapsible-section",m.innerHTML=function(n){let o=`\n\t\t<button \n\t\t\tclass="xfn-section-toggle components-button is-tertiary" \n\t\t\taria-expanded="false" \n\t\t\ttype="button"\n\t\t>\n\t\t\tXFN ${n.length>0?`<span class="xfn-count-badge">${n.length}</span>`:""}\n\t\t\t<svg class="xfn-chevron" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">\n\t\t\t\t<path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"/>\n\t\t\t</svg>\n\t\t</button>\n\t\t<div class="xfn-section-content" style="display: none;">\n\t\t\t<p class="xfn-section-description">\n\t\t\t\t${(0,e.__)("Describe your relationship to this person or organization","link-extension-for-xfn")}\n\t\t\t</p>\n\t`;return Object.entries(r).forEach(([t,l])=>{if(o+=`<div class="xfn-category" data-category="${t}">`,o+=`<h4>${l.label}</h4>`,"radio"===l.type){const t=l.options.find(e=>n.includes(e.value))?.value||"";o+='<div class="xfn-button-group">',o+=`<button class="components-button is-compact ${""===t?"is-pressed":""}" data-value="">${(0,e.__)("None","link-extension-for-xfn")}</button>`,l.options.forEach(e=>{o+=`<button class="components-button is-compact ${t===e.value?"is-pressed":""}" data-value="${e.value}">${e.label}</button>`}),o+="</div>"}else o+='<div class="xfn-button-group">',l.options.forEach(e=>{const t=n.includes(e.value);o+=`<button class="components-button is-compact ${t?"is-pressed":""}" data-value="${e.value}">${e.label}</button>`}),o+="</div>";o+="</div>"}),n.length>0&&(o+='<div class="xfn-summary">',o+=`<h4>${(0,e.__)("Active Relationships:","link-extension-for-xfn")}</h4>`,o+='<div class="xfn-pills">',n.forEach(e=>{o+=`<span class="xfn-pill xfn-pill-${e}">${e}</span> `}),o+="</div></div>"),o+="</div>",o}(p),t.appendChild(m),function(n,o){const t=n.querySelector(".xfn-section-toggle"),l=n.querySelector(".xfn-section-content"),i=t.querySelector(".xfn-chevron"),s=n.closest(".block-editor-link-control")||document;t.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation();const n=!("true"===t.getAttribute("aria-expanded"));t.setAttribute("aria-expanded",n),l.style.display=n?"block":"none",i.style.transform=n?"rotate(180deg)":"rotate(0deg)"}),n.querySelectorAll(".xfn-button-group .components-button").forEach(l=>{l.addEventListener("click",l=>{l.preventDefault(),l.stopPropagation();const i=l.target.closest(".xfn-category").dataset.category,c=l.target.dataset.value,d=l.target.closest(".xfn-button-group");if("radio"===r[i].type){const e=r[i].options.map(e=>e.value);p=p.filter(n=>!e.includes(n)),c&&p.push(c),d.querySelectorAll(".components-button").forEach(e=>{e.classList.remove("is-pressed")}),l.target.classList.add("is-pressed")}else l.target.classList.contains("is-pressed")?(p=p.filter(e=>e!==c),l.target.classList.remove("is-pressed")):(p.includes(c)||p.push(c),l.target.classList.add("is-pressed"));(()=>{const l=a(p,g);if(console.log("[XFN] Updating XFN values:",{xfnValues:p,otherValues:g,newRel:l}),o){o.value=l,console.log("[XFN] Updated rel input field to:",l);const e=new Event("input",{bubbles:!0});o.dispatchEvent(e);const n=new Event("change",{bubbles:!0});o.dispatchEvent(n)}window.pendingXFNRel=l,window.pendingXFNUrl=b?.url,console.log("[XFN] Stored pending XFN rel:",window.pendingXFNRel),console.log("[XFN] Stored pending XFN url:",window.pendingXFNUrl),b={...b||{},rel:l||""},console.log("[XFN] Stored rel value (will apply on Submit):",b);const i=s.querySelector('.block-editor-link-control__search-submit, button[type="submit"]');i&&(i.removeAttribute("aria-disabled"),i.removeAttribute("disabled"),i.classList.add("xfn-apply-ready")),function(n){let o=n.querySelector(".xfn-summary");if(0===p.length)return void(o&&o.remove());o||(o=document.createElement("div"),o.className="xfn-summary",n.querySelector(".xfn-section-content").appendChild(o));let t=`<h4>${(0,e.__)("Active Relationships:","link-extension-for-xfn")}</h4>`;t+='<div class="xfn-pills">',p.forEach(e=>{t+=`<span class="xfn-pill xfn-pill-${e}">${e}</span> `}),t+="</div>",o.innerHTML=t}(n),function(e){let n=e.querySelector(".xfn-count-badge");0!==p.length?(n||(n=document.createElement("span"),n.className="xfn-count-badge",e.insertBefore(n,e.querySelector(".xfn-chevron"))),n.textContent=p.length):n&&n.remove()}(t)})()})})}(m,u),console.log("[XFN] Looking for Apply button...");const X=n.querySelectorAll("button");console.log("[XFN] All buttons in link control:",X);const w=n.querySelector('.block-editor-link-control__search-submit, button[type="submit"]');w?(console.log("[XFN] Found Apply button (will save XFN on click)"),w.addEventListener("click",e=>{if(console.log("[XFN] ===== Apply button clicked! ====="),console.log("[XFN] Current XFN values:",p),console.log("[XFN] Current link value:",b),p.length>0){const e=a(p,g);console.log("[XFN] Storing XFN rel for post-link-creation:",e),window.pendingXFNRel=e,window.pendingXFNUrl=b?.url,console.log("[XFN] Scheduling XFN application attempts..."),setTimeout(()=>{console.log("[XFN] Attempt 1 (100ms)..."),k()},100),setTimeout(()=>{console.log("[XFN] Attempt 2 (300ms)..."),k()},300),setTimeout(()=>{console.log("[XFN] Attempt 3 (500ms)..."),k()},500),setTimeout(()=>{console.log("[XFN] Attempt 4 (1000ms)..."),k()},1e3)}else console.log("[XFN] No XFN values selected, skipping");o&&"true"===o.getAttribute("aria-expanded")&&setTimeout(()=>o.click(),150)},!0),console.log("[XFN] Apply button interceptor attached")):console.warn("[XFN] Apply button not found!")},100)}function k(){if(console.log("[XFN] ===== Applying XFN to created link ====="),console.log("[XFN] Pending XFN rel:",window.pendingXFNRel),console.log("[XFN] Pending XFN url:",window.pendingXFNUrl),!window.pendingXFNRel||!window.pendingXFNUrl)return console.log("[XFN] No pending XFN data to apply"),!1;const e=wp.data.select("core/block-editor").getSelectedBlock();if(!e)return console.log("[XFN] No selected block found"),!1;if(console.log("[XFN] Selected block:",e.name),console.log("[XFN] Selected block clientId:",e.clientId),console.log("[XFN] Selected block attributes:",e.attributes),console.log("[XFN] Block innerBlocks:",e.innerBlocks),["core/button","core/image","core/navigation-link","core/site-logo","core/post-title","core/query-title"].includes(e.name)){console.log("[XFN] This is a block-level link, updating rel attribute directly...");const n=d(e.attributes,e.name);console.log("[XFN] Existing rel:",n);const{other:o}=c(n);console.log("[XFN] Existing other values:",o);const{xfn:t}=c(window.pendingXFNRel);console.log("[XFN] Pending XFN values:",t);const l=a(t,o);if(console.log("[XFN] New combined rel:",l),e.attributes.hasOwnProperty("rel"))wp.data.dispatch("core/block-editor").updateBlockAttributes(e.clientId,{rel:l||void 0}),console.log("[XFN] ✓ Updated rel attribute on block");else{const n=e.attributes.metadata||{};wp.data.dispatch("core/block-editor").updateBlockAttributes(e.clientId,{metadata:{...n,rel:l||void 0}}),console.log("[XFN] ✓ Updated metadata.rel attribute on block")}if(window.currentLinkOnChange&&"function"==typeof window.currentLinkOnChange)try{const e={...window.currentLinkValue||{},rel:l||""};window.currentLinkOnChange(e),console.log("[XFN] ✓ Also called onChange with updated rel")}catch(e){console.warn("[XFN] Could not call onChange:",e)}return window.pendingXFNRel=null,window.pendingXFNUrl=null,console.log("[XFN] ✓✓✓ Block-level link updated successfully! ✓✓✓"),!0}let n=e.attributes.content;if(console.log("[XFN] Block content:",n),console.log("[XFN] Block content type:",typeof n),n&&"object"==typeof n&&n.toHTMLString&&(console.log("[XFN] Converting RichTextData to HTML string..."),n=n.toHTMLString(),console.log("[XFN] Converted content:",n)),!n||"string"!=typeof n)return console.warn("[XFN] Block has no string content or unable to convert to string"),!1;const o=n.includes(window.pendingXFNUrl);if(console.log("[XFN] URL in content?",o),!o)return console.warn("[XFN] Pending URL not found in block content"),console.log("[XFN] Looking for:",window.pendingXFNUrl),console.log("[XFN] In content:",n),!1;console.log("[XFN] Found URL in block content, attempting to update using proper WordPress approach...");try{const{xfn:o,other:t}=c(window.pendingXFNRel),l=(new DOMParser).parseFromString(n,"text/html"),i=l.querySelectorAll("a");let s=!1;if(i.forEach(e=>{if(e.getAttribute("href")===window.pendingXFNUrl){const n=e.getAttribute("rel")||"",{other:l}=c(n),i=a(o,l.length?l:t);console.log("[XFN] Setting rel attribute:",i),e.setAttribute("rel",i),s=!0}}),s){const n=l.body.innerHTML;return console.log("[XFN] Updating block with new content..."),wp.data.dispatch("core/block-editor").updateBlockAttributes(e.clientId,{content:n}),console.log("[XFN] ✓ Block content updated"),window.pendingXFNRel=null,window.pendingXFNUrl=null,setTimeout(()=>{const n=wp.data.select("core/block-editor").getBlock(e.clientId);console.log("[XFN] Verification - Current content:",n?.attributes?.content)},100),!0}}catch(e){console.error("[XFN] Error updating link:",e)}return console.warn("[XFN] Could not update link"),!1}const h=(0,l.createHigherOrderComponent)(e=>n=>{const{attributes:o,name:t}=n,l=window.linkexfoData?.settings||{enable_inspector_controls:!1,enable_floating_toolbar:!1};return(["core/button","core/image","core/navigation-link","core/site-logo","core/post-title","core/query-title"].includes(t)||o.hasOwnProperty("url")||o.hasOwnProperty("href")||o.hasOwnProperty("linkDestination"))&&l.enable_inspector_controls?(d(o),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(e,{...n}),(0,s.jsx)(u,{...n})]})):(0,s.jsx)(e,{...n})},"withXFNControls");window.linkexfoData?.settings?.enable_inspector_controls&&((0,n.addFilter)("editor.BlockEdit","xfn-link-extension/with-xfn-controls",h),console.log("[XFN] Inspector Controls enabled")),(0,n.addFilter)("blocks.getSaveContent.extraProps","xfn-link-extension/add-rel-to-links",(e,n,o)=>(console.log("[XFN] getSaveContent filter called for:",n.name),p.length>0&&console.log("[XFN] Injecting XFN values into saved content:",p),e)),"undefined"!=typeof document&&(console.log("[XFN] Starting XFN monitoring in 1 second..."),setTimeout(()=>{console.log("[XFN] XFN monitoring started!"),new MutationObserver(e=>{e.forEach(e=>{"childList"===e.type&&Array.from(e.addedNodes).forEach(e=>{e.nodeType===Node.ELEMENT_NODE&&((e.classList?.contains("block-editor-link-control")||e.querySelector?.(".block-editor-link-control"))&&x(),(e.classList?.contains("block-editor-link-control__settings")||e.querySelector?.(".block-editor-link-control__settings"))&&x())}),"attributes"===e.type&&"aria-expanded"===e.attributeName&&x()})}).observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["aria-expanded"]}),document.addEventListener("click",e=>{e.target.closest(".block-editor-link-control__tools .components-button")&&setTimeout(x,50)})},1e3)),console.log("%c[XFN] Link Extension loaded successfully!","color: #00a32a; font-weight: bold; font-size: 14px;"),console.log("[XFN] Controls will appear in:");const N=window.linkexfoData?.settings||{enable_inspector_controls:!1,enable_floating_toolbar:!1};N.enable_inspector_controls?console.log("[XFN] ✓ Inspector Controls for link blocks (ENABLED)"):console.log("[XFN] ✗ Inspector Controls for link blocks (DISABLED - enable in Settings > Link Extension for XFN)"),N.enable_floating_toolbar?console.log("[XFN] ✓ Floating toolbar for link blocks (ENABLED)"):console.log("[XFN] ✗ Floating toolbar for link blocks (DISABLED - enable in Settings > Link Extension for XFN)"),console.log("[XFN] ✓ Collapsible XFN section in Link Advanced Panel (ALWAYS ENABLED)")})();1 (()=>{"use strict";const e=window.wp.i18n,n=window.wp.hooks,o=window.wp.components,t=window.wp.blockEditor,l=window.wp.compose,i=(window.wp.element,window.wp.data,window.wp.richText),s=window.ReactJSXRuntime;(0,i.registerFormatType)("xfn-link-extension/xfn-rel",{title:(0,e.__)("XFN Relationship","link-extension-for-xfn"),tagName:"a",className:null,attributes:{rel:"rel",href:"href"},edit:()=>null}),console.log("[XFN] XFN format type registered");const r={friendship:{type:"radio",label:(0,e.__)("Friendship","link-extension-for-xfn"),description:(0,e.__)("Your friendship level (choose one)","link-extension-for-xfn"),options:[{label:(0,e.__)("Contact","link-extension-for-xfn"),value:"contact"},{label:(0,e.__)("Acquaintance","link-extension-for-xfn"),value:"acquaintance"},{label:(0,e.__)("Friend","link-extension-for-xfn"),value:"friend"}]},physical:{type:"checkbox",label:(0,e.__)("Physical","link-extension-for-xfn"),description:(0,e.__)("Have you met this person?","link-extension-for-xfn"),options:[{label:(0,e.__)("Met","link-extension-for-xfn"),value:"met"}]},professional:{type:"checkbox",label:(0,e.__)("Professional","link-extension-for-xfn"),description:(0,e.__)("Professional relationships","link-extension-for-xfn"),options:[{label:(0,e.__)("Co-worker","link-extension-for-xfn"),value:"co-worker"},{label:(0,e.__)("Colleague","link-extension-for-xfn"),value:"colleague"}]},geographical:{type:"radio",label:(0,e.__)("Geographical","link-extension-for-xfn"),description:(0,e.__)("Geographical relationship","link-extension-for-xfn"),options:[{label:(0,e.__)("Co-resident","link-extension-for-xfn"),value:"co-resident"},{label:(0,e.__)("Neighbor","link-extension-for-xfn"),value:"neighbor"}]},family:{type:"radio",label:(0,e.__)("Family","link-extension-for-xfn"),description:(0,e.__)("Family relationship","link-extension-for-xfn"),options:[{label:(0,e.__)("Child","link-extension-for-xfn"),value:"child"},{label:(0,e.__)("Parent","link-extension-for-xfn"),value:"parent"},{label:(0,e.__)("Sibling","link-extension-for-xfn"),value:"sibling"},{label:(0,e.__)("Spouse","link-extension-for-xfn"),value:"spouse"},{label:(0,e.__)("Kin","link-extension-for-xfn"),value:"kin"}]},romantic:{type:"checkbox",label:(0,e.__)("Romantic","link-extension-for-xfn"),description:(0,e.__)("Romantic relationships","link-extension-for-xfn"),options:[{label:(0,e.__)("Muse","link-extension-for-xfn"),value:"muse"},{label:(0,e.__)("Crush","link-extension-for-xfn"),value:"crush"},{label:(0,e.__)("Date","link-extension-for-xfn"),value:"date"},{label:(0,e.__)("Sweetheart","link-extension-for-xfn"),value:"sweetheart"}]},identity:{type:"checkbox",label:(0,e.__)("Identity","link-extension-for-xfn"),description:(0,e.__)("Is this your own content?","link-extension-for-xfn"),options:[{label:(0,e.__)("Me","link-extension-for-xfn"),value:"me"}]}};function c(e){if(!e)return{xfn:[],other:[]};const n=["contact","acquaintance","friend","met","co-worker","colleague","co-resident","neighbor","child","parent","sibling","spouse","kin","muse","crush","date","sweetheart","me"],o=e.split(/\s+/).filter(Boolean),t=[],l=[];return o.forEach(e=>{n.includes(e)?t.push(e):l.push(e)}),{xfn:t,other:l}}function a(e,n){const o=[...n,...e].filter(Boolean);return[...new Set(o)].join(" ")}function d(e,n){return e.rel?e.rel:e.metadata?.rel?e.metadata.rel:""}const u=({attributes:n,setAttributes:l,name:i})=>{const u=d(n),{xfn:p,other:g}=c(u),f=(e,o,t)=>{let i=[...p];if("radio"===r[e].type){const n=r[e].options.map(e=>e.value);i=i.filter(e=>!n.includes(e)),t&&i.push(o)}else t?i.includes(o)||i.push(o):i=i.filter(e=>e!==o);(e=>{const o=a(e,g);!function(e,n,o){e.hasOwnProperty("rel")?n({rel:o||void 0}):n({metadata:{...e.metadata||{},rel:o||void 0}})}(n,l,o)})(i)},b=["core/button","core/image","core/navigation-link","core/site-logo","core/post-title","core/query-title","core/embed"].includes(i);return(0,s.jsx)(t.InspectorControls,{children:(0,s.jsxs)(o.PanelBody,{title:(0,e.__)("XFN Relationships","link-extension-for-xfn"),initialOpen:b,className:"xfn-inspector-panel",children:[(0,s.jsx)("p",{className:"xfn-panel-description",children:(0,e.__)("Describe your relationship to the people or organizations you link to using XFN (XHTML Friends Network) markup.","link-extension-for-xfn")}),Object.entries(r).map(([n,t])=>{if("radio"===t.type){const l=t.options.find(e=>p.includes(e.value))?.value||"",i=[{label:(0,e.__)("None","link-extension-for-xfn"),value:""},...t.options];return(0,s.jsx)("div",{className:"xfn-category-section",children:(0,s.jsx)(o.RadioControl,{label:t.label,help:t.description,selected:l,options:i,onChange:e=>{f(n,e,""!==e)}})},n)}return(0,s.jsxs)("div",{className:"xfn-category-section",children:[(0,s.jsx)("h4",{className:"xfn-category-title",children:t.label}),(0,s.jsx)("p",{className:"xfn-category-help",children:t.description}),t.options.map(e=>(0,s.jsx)(o.CheckboxControl,{label:e.label,checked:p.includes(e.value),onChange:o=>{f(n,e.value,o)}},e.value))]},n)}),p.length>0&&(0,s.jsxs)("div",{className:"xfn-selected-summary",children:[(0,s.jsx)("h4",{children:(0,e.__)("Selected Relationships:","link-extension-for-xfn")}),(0,s.jsx)("div",{className:"xfn-pills",children:p.map(e=>(0,s.jsx)("span",{className:`xfn-pill xfn-pill-${e}`,children:e},e))})]})]})})};let p=[],g=[],f=null,b=null;function x(){setTimeout(()=>{const n=document.querySelector(".block-editor-link-control");if(!n)return;const o=n.querySelector(".block-editor-link-control__tools .components-button");if(!o)return;if("true"!==o.getAttribute("aria-expanded"))return;const t=n.querySelector(".block-editor-link-control__settings");if(!t)return;if(t.querySelector(".xfn-collapsible-section"))return;console.log("[XFN] Attempting to find link value from React...");const l=n,i=Object.keys(l).find(e=>e.startsWith("__react"));if(i){const e=l[i];console.log("[XFN] React instance found:",e);let n=e,o=0;for(;n&&o<10;){if(n.memoizedProps?.value){b=n.memoizedProps.value,f=n.memoizedProps.onChange,window.currentLinkValue=b,window.currentLinkOnChange=f,console.log("[XFN] Found link value:",b),console.log("[XFN] Link value keys:",Object.keys(b)),console.log("[XFN] Link value rel:",b.rel),console.log("[XFN] Found onChange:",f);break}n=n.return||n._owner,o++}}console.log("[XFN] Looking for rel input in link control...");const s=t.querySelectorAll("input");console.log("[XFN] All inputs in settings panel:",s),s.forEach((e,n)=>{console.log(`[XFN] Input ${n}:`,{type:e.type,id:e.id,name:e.name,placeholder:e.placeholder,value:e.value,element:e})});let u=n.querySelector('input[type="text"][placeholder*="rel" i]');if(console.log("[XFN] Try 1 (placeholder*=rel):",u),u||(u=n.querySelector('input[id*="rel" i]'),console.log("[XFN] Try 2 (id*=rel):",u)),!u){const e=t.querySelectorAll('input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"])');console.log("[XFN] Try 3 - text-like inputs in settings:",e),e.length>0&&(u=e[e.length-1])}console.log("[XFN] Final rel input found:",!!u),u&&(console.log("[XFN] Rel input element:",u),console.log("[XFN] Rel input current value:",u.value));let x="";const h=wp.data.select("core/block-editor").getSelectedBlock();if(h&&["core/button","core/image","core/navigation-link","core/site-logo","core/post-title","core/query-title","core/embed"].includes(h.name))x=d(h.attributes,h.name),console.log("[XFN] Got rel from block-level link attributes:",x);else if(b?.url&&h?.attributes?.content){let e=h.attributes.content;if("object"==typeof e&&e.toHTMLString&&(e=e.toHTMLString()),"string"==typeof e&&e.includes(b.url)){const n=(new DOMParser).parseFromString(e,"text/html"),o=Array.from(n.querySelectorAll("a")).find(e=>e.getAttribute("href")===b.url);o&&(x=o.getAttribute("rel")||"",console.log("[XFN] Got rel from existing link in content:",x))}}!x&&b&&b.rel?(x=b.rel,console.log("[XFN] Got rel from link value:",x)):!x&&u&&(x=u.value,console.log("[XFN] Got rel from input:",x));const{xfn:N,other:F}=c(x);p=[...N],g=[...F],console.log("[XFN] Initial XFN values:",p),console.log("[XFN] Initial other values:",g);const m=document.createElement("div");m.className="xfn-collapsible-section",m.innerHTML=function(n){let o=`\n\t\t<button \n\t\t\tclass="xfn-section-toggle components-button is-tertiary" \n\t\t\taria-expanded="false" \n\t\t\ttype="button"\n\t\t>\n\t\t\tXFN ${n.length>0?`<span class="xfn-count-badge">${n.length}</span>`:""}\n\t\t\t<svg class="xfn-chevron" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">\n\t\t\t\t<path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"/>\n\t\t\t</svg>\n\t\t</button>\n\t\t<div class="xfn-section-content" style="display: none;">\n\t\t\t<p class="xfn-section-description">\n\t\t\t\t${(0,e.__)("Describe your relationship to this person or organization","link-extension-for-xfn")}\n\t\t\t</p>\n\t`;return Object.entries(r).forEach(([t,l])=>{if(o+=`<div class="xfn-category" data-category="${t}">`,o+=`<h4>${l.label}</h4>`,"radio"===l.type){const t=l.options.find(e=>n.includes(e.value))?.value||"";o+='<div class="xfn-button-group">',o+=`<button class="components-button is-compact ${""===t?"is-pressed":""}" data-value="">${(0,e.__)("None","link-extension-for-xfn")}</button>`,l.options.forEach(e=>{o+=`<button class="components-button is-compact ${t===e.value?"is-pressed":""}" data-value="${e.value}">${e.label}</button>`}),o+="</div>"}else o+='<div class="xfn-button-group">',l.options.forEach(e=>{const t=n.includes(e.value);o+=`<button class="components-button is-compact ${t?"is-pressed":""}" data-value="${e.value}">${e.label}</button>`}),o+="</div>";o+="</div>"}),n.length>0&&(o+='<div class="xfn-summary">',o+=`<h4>${(0,e.__)("Active Relationships:","link-extension-for-xfn")}</h4>`,o+='<div class="xfn-pills">',n.forEach(e=>{o+=`<span class="xfn-pill xfn-pill-${e}">${e}</span> `}),o+="</div></div>"),o+="</div>",o}(p),t.appendChild(m),function(n,o){const t=n.querySelector(".xfn-section-toggle"),l=n.querySelector(".xfn-section-content"),i=t.querySelector(".xfn-chevron"),s=n.closest(".block-editor-link-control")||document;t.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation();const n=!("true"===t.getAttribute("aria-expanded"));t.setAttribute("aria-expanded",n),l.style.display=n?"block":"none",i.style.transform=n?"rotate(180deg)":"rotate(0deg)"}),n.querySelectorAll(".xfn-button-group .components-button").forEach(l=>{l.addEventListener("click",l=>{l.preventDefault(),l.stopPropagation();const i=l.target.closest(".xfn-category").dataset.category,c=l.target.dataset.value,d=l.target.closest(".xfn-button-group");if("radio"===r[i].type){const e=r[i].options.map(e=>e.value);p=p.filter(n=>!e.includes(n)),c&&p.push(c),d.querySelectorAll(".components-button").forEach(e=>{e.classList.remove("is-pressed")}),l.target.classList.add("is-pressed")}else l.target.classList.contains("is-pressed")?(p=p.filter(e=>e!==c),l.target.classList.remove("is-pressed")):(p.includes(c)||p.push(c),l.target.classList.add("is-pressed"));(()=>{const l=a(p,g);if(console.log("[XFN] Updating XFN values:",{xfnValues:p,otherValues:g,newRel:l}),o){o.value=l,console.log("[XFN] Updated rel input field to:",l);const e=new Event("input",{bubbles:!0});o.dispatchEvent(e);const n=new Event("change",{bubbles:!0});o.dispatchEvent(n)}window.pendingXFNRel=l,window.pendingXFNUrl=b?.url,console.log("[XFN] Stored pending XFN rel:",window.pendingXFNRel),console.log("[XFN] Stored pending XFN url:",window.pendingXFNUrl),b={...b||{},rel:l||""},console.log("[XFN] Stored rel value (will apply on Submit):",b);const i=s.querySelector('.block-editor-link-control__search-submit, button[type="submit"]');i&&(i.removeAttribute("aria-disabled"),i.removeAttribute("disabled"),i.classList.add("xfn-apply-ready")),function(n){let o=n.querySelector(".xfn-summary");if(0===p.length)return void(o&&o.remove());o||(o=document.createElement("div"),o.className="xfn-summary",n.querySelector(".xfn-section-content").appendChild(o));let t=`<h4>${(0,e.__)("Active Relationships:","link-extension-for-xfn")}</h4>`;t+='<div class="xfn-pills">',p.forEach(e=>{t+=`<span class="xfn-pill xfn-pill-${e}">${e}</span> `}),t+="</div>",o.innerHTML=t}(n),function(e){let n=e.querySelector(".xfn-count-badge");0!==p.length?(n||(n=document.createElement("span"),n.className="xfn-count-badge",e.insertBefore(n,e.querySelector(".xfn-chevron"))),n.textContent=p.length):n&&n.remove()}(t)})()})})}(m,u),console.log("[XFN] Looking for Apply button...");const X=n.querySelectorAll("button");console.log("[XFN] All buttons in link control:",X);const w=n.querySelector('.block-editor-link-control__search-submit, button[type="submit"]');w?(console.log("[XFN] Found Apply button (will save XFN on click)"),w.addEventListener("click",e=>{if(console.log("[XFN] ===== Apply button clicked! ====="),console.log("[XFN] Current XFN values:",p),console.log("[XFN] Current link value:",b),p.length>0){const e=a(p,g);console.log("[XFN] Storing XFN rel for post-link-creation:",e),window.pendingXFNRel=e,window.pendingXFNUrl=b?.url,console.log("[XFN] Scheduling XFN application attempts..."),setTimeout(()=>{console.log("[XFN] Attempt 1 (100ms)..."),k()},100),setTimeout(()=>{console.log("[XFN] Attempt 2 (300ms)..."),k()},300),setTimeout(()=>{console.log("[XFN] Attempt 3 (500ms)..."),k()},500),setTimeout(()=>{console.log("[XFN] Attempt 4 (1000ms)..."),k()},1e3)}else console.log("[XFN] No XFN values selected, skipping");o&&"true"===o.getAttribute("aria-expanded")&&setTimeout(()=>o.click(),150)},!0),console.log("[XFN] Apply button interceptor attached")):console.warn("[XFN] Apply button not found!")},100)}function k(){if(console.log("[XFN] ===== Applying XFN to created link ====="),console.log("[XFN] Pending XFN rel:",window.pendingXFNRel),console.log("[XFN] Pending XFN url:",window.pendingXFNUrl),!window.pendingXFNRel||!window.pendingXFNUrl)return console.log("[XFN] No pending XFN data to apply"),!1;const e=wp.data.select("core/block-editor").getSelectedBlock();if(!e)return console.log("[XFN] No selected block found"),!1;if(console.log("[XFN] Selected block:",e.name),console.log("[XFN] Selected block clientId:",e.clientId),console.log("[XFN] Selected block attributes:",e.attributes),console.log("[XFN] Block innerBlocks:",e.innerBlocks),["core/button","core/image","core/navigation-link","core/site-logo","core/post-title","core/query-title","core/embed"].includes(e.name)){console.log("[XFN] This is a block-level link, updating rel attribute directly...");const n=d(e.attributes,e.name);console.log("[XFN] Existing rel:",n);const{other:o}=c(n);console.log("[XFN] Existing other values:",o);const{xfn:t}=c(window.pendingXFNRel);console.log("[XFN] Pending XFN values:",t);const l=a(t,o);if(console.log("[XFN] New combined rel:",l),e.attributes.hasOwnProperty("rel"))wp.data.dispatch("core/block-editor").updateBlockAttributes(e.clientId,{rel:l||void 0}),console.log("[XFN] ✓ Updated rel attribute on block");else{const n=e.attributes.metadata||{};wp.data.dispatch("core/block-editor").updateBlockAttributes(e.clientId,{metadata:{...n,rel:l||void 0}}),console.log("[XFN] ✓ Updated metadata.rel attribute on block")}if(window.currentLinkOnChange&&"function"==typeof window.currentLinkOnChange)try{const e={...window.currentLinkValue||{},rel:l||""};window.currentLinkOnChange(e),console.log("[XFN] ✓ Also called onChange with updated rel")}catch(e){console.warn("[XFN] Could not call onChange:",e)}return window.pendingXFNRel=null,window.pendingXFNUrl=null,console.log("[XFN] ✓✓✓ Block-level link updated successfully! ✓✓✓"),!0}let n=e.attributes.content;if(console.log("[XFN] Block content:",n),console.log("[XFN] Block content type:",typeof n),n&&"object"==typeof n&&n.toHTMLString&&(console.log("[XFN] Converting RichTextData to HTML string..."),n=n.toHTMLString(),console.log("[XFN] Converted content:",n)),!n||"string"!=typeof n)return console.warn("[XFN] Block has no string content or unable to convert to string"),!1;const o=n.includes(window.pendingXFNUrl);if(console.log("[XFN] URL in content?",o),!o)return console.warn("[XFN] Pending URL not found in block content"),console.log("[XFN] Looking for:",window.pendingXFNUrl),console.log("[XFN] In content:",n),!1;console.log("[XFN] Found URL in block content, attempting to update using proper WordPress approach...");try{const{xfn:o,other:t}=c(window.pendingXFNRel),l=(new DOMParser).parseFromString(n,"text/html"),i=l.querySelectorAll("a");let s=!1;if(i.forEach(e=>{if(e.getAttribute("href")===window.pendingXFNUrl){const n=e.getAttribute("rel")||"",{other:l}=c(n),i=a(o,l.length?l:t);console.log("[XFN] Setting rel attribute:",i),e.setAttribute("rel",i),s=!0}}),s){const n=l.body.innerHTML;return console.log("[XFN] Updating block with new content..."),wp.data.dispatch("core/block-editor").updateBlockAttributes(e.clientId,{content:n}),console.log("[XFN] ✓ Block content updated"),window.pendingXFNRel=null,window.pendingXFNUrl=null,setTimeout(()=>{const n=wp.data.select("core/block-editor").getBlock(e.clientId);console.log("[XFN] Verification - Current content:",n?.attributes?.content)},100),!0}}catch(e){console.error("[XFN] Error updating link:",e)}return console.warn("[XFN] Could not update link"),!1}const h=(0,l.createHigherOrderComponent)(e=>n=>{const{attributes:o,name:t}=n,l=window.linkexfoData?.settings||{enable_inspector_controls:!1,enable_floating_toolbar:!1};return(["core/button","core/image","core/navigation-link","core/site-logo","core/post-title","core/query-title","core/embed"].includes(t)||o.hasOwnProperty("url")||o.hasOwnProperty("href")||o.hasOwnProperty("linkDestination"))&&l.enable_inspector_controls?(d(o),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(e,{...n}),(0,s.jsx)(u,{...n})]})):(0,s.jsx)(e,{...n})},"withXFNControls");window.linkexfoData?.settings?.enable_inspector_controls&&((0,n.addFilter)("editor.BlockEdit","xfn-link-extension/with-xfn-controls",h),console.log("[XFN] Inspector Controls enabled")),(0,n.addFilter)("blocks.getSaveContent.extraProps","xfn-link-extension/add-rel-to-links",(e,n,o)=>(console.log("[XFN] getSaveContent filter called for:",n.name),p.length>0&&console.log("[XFN] Injecting XFN values into saved content:",p),e)),"undefined"!=typeof document&&(console.log("[XFN] Starting XFN monitoring in 1 second..."),setTimeout(()=>{console.log("[XFN] XFN monitoring started!"),new MutationObserver(e=>{e.forEach(e=>{"childList"===e.type&&Array.from(e.addedNodes).forEach(e=>{e.nodeType===Node.ELEMENT_NODE&&((e.classList?.contains("block-editor-link-control")||e.querySelector?.(".block-editor-link-control"))&&x(),(e.classList?.contains("block-editor-link-control__settings")||e.querySelector?.(".block-editor-link-control__settings"))&&x())}),"attributes"===e.type&&"aria-expanded"===e.attributeName&&x()})}).observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["aria-expanded"]}),document.addEventListener("click",e=>{e.target.closest(".block-editor-link-control__tools .components-button")&&setTimeout(x,50)})},1e3)),console.log("%c[XFN] Link Extension loaded successfully!","color: #00a32a; font-weight: bold; font-size: 14px;"),console.log("[XFN] Controls will appear in:");const N=window.linkexfoData?.settings||{enable_inspector_controls:!1,enable_floating_toolbar:!1};N.enable_inspector_controls?console.log("[XFN] ✓ Inspector Controls for link blocks (ENABLED)"):console.log("[XFN] ✗ Inspector Controls for link blocks (DISABLED - enable in Settings > Link Extension for XFN)"),N.enable_floating_toolbar?console.log("[XFN] ✓ Floating toolbar for link blocks (ENABLED)"):console.log("[XFN] ✗ Floating toolbar for link blocks (DISABLED - enable in Settings > Link Extension for XFN)"),console.log("[XFN] ✓ Collapsible XFN section in Link Advanced Panel (ALWAYS ENABLED)")})(); -
link-extension-for-xfn/trunk/link-extension-for-xfn.php
r3415433 r3415636 654 654 return XFN_Link_Extension::sanitize_rel_attribute( $rel_value ); 655 655 } 656 657 /** 658 * Filter embed block output to add XFN rel attributes 659 * 660 * Modifies the rendered HTML of embed blocks to include XFN relationships 661 * stored in block metadata. Adds rel attributes to any links found in the 662 * embed output, or adds a data-rel attribute to the figure element. 663 * 664 * @since 1.0.2 665 * @param string $block_content The block content about to be rendered 666 * @param array $block The full block, including name and attributes 667 * @return string Modified block content with XFN attributes 668 */ 669 function xfn_render_embed_block( $block_content, $block ) { 670 // Only process embed blocks 671 if ( 'core/embed' !== $block['blockName'] ) { 672 return $block_content; 673 } 674 675 // Check if block has XFN metadata 676 if ( empty( $block['attrs']['metadata']['rel'] ) ) { 677 return $block_content; 678 } 679 680 $rel_value = $block['attrs']['metadata']['rel']; 681 682 // Sanitize the rel value 683 $rel_value = XFN_Link_Extension::sanitize_rel_attribute( $rel_value ); 684 685 if ( empty( $rel_value ) ) { 686 return $block_content; 687 } 688 689 // Try to find and modify any existing links in the embed output 690 if ( preg_match( '/<a\s+([^>]*?)>/', $block_content ) ) { 691 // Embed contains a link - add rel to it 692 $block_content = preg_replace_callback( 693 '/<a\s+([^>]*?)>/', 694 function( $matches ) use ( $rel_value ) { 695 $attrs = $matches[1]; 696 697 // Check if rel already exists 698 if ( preg_match( '/rel=["\']([^"\']*)["\']/', $attrs, $rel_match ) ) { 699 // Combine existing rel with XFN 700 $existing_rel = $rel_match[1]; 701 $parsed = XFN_Link_Extension::parse_rel_attribute( $existing_rel ); 702 $new_xfn = XFN_Link_Extension::parse_rel_attribute( $rel_value ); 703 $combined = XFN_Link_Extension::combine_rel_values( $new_xfn['xfn'], $parsed['other'] ); 704 705 // Replace existing rel 706 $attrs = preg_replace( 707 '/rel=["\'][^"\']*["\']/', 708 'rel="' . esc_attr( $combined ) . '"', 709 $attrs 710 ); 711 } else { 712 // Add new rel attribute 713 $attrs .= ' rel="' . esc_attr( $rel_value ) . '"'; 714 } 715 716 return '<a ' . $attrs . '>'; 717 }, 718 $block_content 719 ); 720 } else { 721 // No link in embed output - add data-xfn-rel to figure element for semantic purposes 722 $block_content = preg_replace( 723 '/<figure\s+([^>]*?)class="([^"]*)"([^>]*)>/', 724 '<figure $1class="$2"$3 data-xfn-rel="' . esc_attr( $rel_value ) . '">', 725 $block_content 726 ); 727 } 728 729 return $block_content; 730 } 731 add_filter( 'render_block', 'xfn_render_embed_block', 10, 2 ); -
link-extension-for-xfn/trunk/readme.txt
r3415433 r3415636 35 35 36 36 * **Link Advanced Panel** (Always enabled): Collapsible XFN section in link popovers for inline links - works immediately after installation 37 * **Inspector Controls** (Optional): Panel in the block sidebar for Button, Image, and Navigationblocks - enable in Settings → Link Extension for XFN37 * **Inspector Controls** (Optional): Panel in the block sidebar for Button, Image, Navigation, and Embed blocks - enable in Settings → Link Extension for XFN 38 38 39 39 ### Seamless Integration with WordPress 40 40 The plugin extends the existing link interfaces without disrupting your workflow: 41 41 42 * Works with Paragraph, Button, Navigation, List, and all other link-supporting blocks42 * Works with Paragraph, Button, Navigation, List, Embed, and all other link-supporting blocks 43 43 * Compatible with both Post Editor and Site Editor 44 44 * Preserves existing rel attributes (nofollow, noopener, noreferrer) … … 65 65 After installation, XFN options are immediately available for inline links (links within paragraphs, headings, lists). 66 66 67 To use XFN with Button, Image, and Navigationblocks, go to **Settings → Link Extension for XFN** and enable **Inspector Controls**.67 To use XFN with Button, Image, Navigation, and Embed blocks, go to **Settings → Link Extension for XFN** and enable **Inspector Controls**. 68 68 69 69 ### Method 1: Using Link Advanced Panel (Always Available) … … 77 77 ### Method 2: Using Inspector Controls (Enable in Settings) 78 78 1. Go to Settings → Link Extension for XFN and enable Inspector Controls 79 2. Select a Button, Image, or Navigationblock79 2. Select a Button, Image, Navigation, or Embed block 80 80 3. Look in the right sidebar - "XFN Relationships" panel opens by default 81 81 4. Select relationships using radio buttons and checkboxes organized by category … … 127 127 Enhance your site navigation with relationship context using the Inspector Controls. Mark links to your social profiles, partner sites, or affiliated organizations with the organized collapsible interface. 128 128 129 ### Embed Block 130 Add semantic meaning to embedded content from YouTube, Twitter, and other platforms. Use the Inspector Controls to indicate relationships with embedded content creators, marking videos from colleagues, friends, or your own channels. Perfect for blogrolls, resource pages, and content aggregation. 131 129 132 ### Paragraph Block (Inline Links) 130 133 For inline links within paragraph content, use the collapsible XFN section in the link popover's Advanced area to add relationship context without overwhelming the interface. … … 203 206 XFN controls are available in two locations, both featuring collapsible interfaces: 204 207 1. **Link Advanced Panel** (Always available): In the Advanced section of inline link popovers as a collapsible "XFN" section 205 2. **Inspector Controls** (Enable in Settings): In the block settings sidebar under "XFN Relationships" panel for Button, Image, and Navigationblocks208 2. **Inspector Controls** (Enable in Settings): In the block settings sidebar under "XFN Relationships" panel for Button, Image, Navigation, and Embed blocks 206 209 207 210 ### Why use a collapsible interface? … … 348 351 3. No configuration required - XFN options will immediately appear in: 349 352 - **Link Advanced Panel** (Always available): Collapsible XFN section in the Advanced area of link popovers for inline links 350 - **Inspector Controls** (Optional): Panel in the block sidebar for Button, Image, and Navigationblocks - enable in Settings → Link Extension for XFN353 - **Inspector Controls** (Optional): Panel in the block sidebar for Button, Image, Navigation, and Embed blocks - enable in Settings → Link Extension for XFN 351 354 4. Start adding relationship context to your links using the intuitive collapsible interface 352 355 -
link-extension-for-xfn/trunk/src/index.js
r3415429 r3415636 505 505 'core/post-title', 506 506 'core/query-title', 507 'core/embed', 507 508 ]; 508 509 const shouldBeOpenByDefault = blockLevelLinks.includes( name ); … … 770 771 'core/post-title', 771 772 'core/query-title', 773 'core/embed', 772 774 ]; 773 775 … … 1214 1216 'core/post-title', 1215 1217 'core/query-title', 1218 'core/embed', 1216 1219 ]; 1217 1220 … … 1451 1454 'core/post-title', 1452 1455 'core/query-title', 1456 'core/embed', 1453 1457 ]; 1454 1458
Note: See TracChangeset
for help on using the changeset viewer.