Changeset 3415429
- Timestamp:
- 12/09/2025 01:01:43 PM (4 months ago)
- Location:
- link-extension-for-xfn/trunk
- Files:
-
- 1 added
- 5 edited
-
NAMING-UPDATE-SUMMARY.md (added)
-
build/index.asset.php (modified) (1 diff)
-
build/index.js (modified) (1 diff)
-
link-extension-for-xfn.php (modified) (3 diffs)
-
readme.txt (modified) (1 diff)
-
src/index.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
link-extension-for-xfn/trunk/build/index.asset.php
r3415410 r3415429 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' => ' 8b2c4ff3924bf52fb03b');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'); -
link-extension-for-xfn/trunk/build/index.js
r3415410 r3415429 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 > XFN Link Extension)"),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 > XFN Link Extension)"),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"].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)")})(); -
link-extension-for-xfn/trunk/link-extension-for-xfn.php
r3415410 r3415429 90 90 public function add_settings_page() { 91 91 add_options_page( 92 __( ' XFN Link ExtensionSettings', 'link-extension-for-xfn' ),93 __( ' XFN Link Extension', 'link-extension-for-xfn' ),92 __( 'Link Extension for XFN Settings', 'link-extension-for-xfn' ), 93 __( 'Link Extension for XFN', 'link-extension-for-xfn' ), 94 94 'manage_options', 95 95 'xfn-link-extension', … … 571 571 deactivate_plugins( plugin_basename( __FILE__ ) ); 572 572 wp_die( 573 esc_html__( ' XFN Link Extensionrequires WordPress 6.4 or higher.', 'link-extension-for-xfn' ),573 esc_html__( 'Link Extension for XFN requires WordPress 6.4 or higher.', 'link-extension-for-xfn' ), 574 574 esc_html__( 'Plugin Activation Error', 'link-extension-for-xfn' ), 575 575 array( 'back_link' => true ) … … 580 580 deactivate_plugins( plugin_basename( __FILE__ ) ); 581 581 wp_die( 582 esc_html__( ' XFN Link Extensionrequires PHP 7.4 or higher.', 'link-extension-for-xfn' ),582 esc_html__( 'Link Extension for XFN requires PHP 7.4 or higher.', 'link-extension-for-xfn' ), 583 583 esc_html__( 'Plugin Activation Error', 'link-extension-for-xfn' ), 584 584 array( 'back_link' => true ) -
link-extension-for-xfn/trunk/readme.txt
r3415420 r3415429 1 1 === Link Extension for XFN === 2 2 3 Contributors:courane013 Developers: courane01 4 4 Tags: xfn, links, relationships, accessibility, gutenberg 5 5 Tested up to: 6.9 -
link-extension-for-xfn/trunk/src/index.js
r3415410 r3415429 1534 1534 console.log( '[XFN] ✓ Inspector Controls for link blocks (ENABLED)' ); 1535 1535 } else { 1536 console.log( '[XFN] ✗ Inspector Controls for link blocks (DISABLED - enable in Settings > XFN Link Extension)' );1536 console.log( '[XFN] ✗ Inspector Controls for link blocks (DISABLED - enable in Settings > Link Extension for XFN)' ); 1537 1537 } 1538 1538 … … 1540 1540 console.log( '[XFN] ✓ Floating toolbar for link blocks (ENABLED)' ); 1541 1541 } else { 1542 console.log( '[XFN] ✗ Floating toolbar for link blocks (DISABLED - enable in Settings > XFN Link Extension)' );1542 console.log( '[XFN] ✗ Floating toolbar for link blocks (DISABLED - enable in Settings > Link Extension for XFN)' ); 1543 1543 } 1544 1544
Note: See TracChangeset
for help on using the changeset viewer.