Changeset 3447972
- Timestamp:
- 01/27/2026 02:33:04 PM (2 months ago)
- Location:
- hamelp
- Files:
-
- 2 added
- 12 edited
- 1 copied
-
tags/2.0.2 (copied) (copied from hamelp/trunk)
-
tags/2.0.2/assets/blocks/ai-overview/view.asset.php (modified) (1 diff)
-
tags/2.0.2/assets/blocks/ai-overview/view.js (modified) (1 diff)
-
tags/2.0.2/hamelp.php (modified) (1 diff)
-
tags/2.0.2/readme.txt (modified) (1 diff)
-
tags/2.0.2/src/blocks/ai-overview/utils.js (added)
-
tags/2.0.2/src/blocks/ai-overview/view.js (modified) (1 diff)
-
tags/2.0.2/vendor/composer/installed.php (modified) (2 diffs)
-
trunk/assets/blocks/ai-overview/view.asset.php (modified) (1 diff)
-
trunk/assets/blocks/ai-overview/view.js (modified) (1 diff)
-
trunk/hamelp.php (modified) (1 diff)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/src/blocks/ai-overview/utils.js (added)
-
trunk/src/blocks/ai-overview/view.js (modified) (1 diff)
-
trunk/vendor/composer/installed.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
hamelp/tags/2.0.2/assets/blocks/ai-overview/view.asset.php
r3447047 r3447972 1 <?php return array('dependencies' => array('wp-api-fetch', 'wp-i18n'), 'version' => ' 097d03e44d3442e34ff3');1 <?php return array('dependencies' => array('wp-api-fetch', 'wp-i18n'), 'version' => '3c41d0785b053bdf50c3'); -
hamelp/tags/2.0.2/assets/blocks/ai-overview/view.js
r3447047 r3447972 1 (()=>{"use strict";var e={n:r=>{var t=r&&r.__esModule?()=>r.default:()=>r;return e.d(t,{a:t}),t},d:(r,t)=>{for(var a in t)e.o(t,a)&&!e.o(r,a)&&Object.defineProperty(r,a,{enumerable:!0,get:t[a]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r)};const r=window.wp.apiFetch;var t=e.n(r);const a=window.wp.i18n;document.querySelectorAll(".hamelp-ai-overview").forEach(e=>{const r=e.querySelector("form"),s=e.querySelector("input"), i=e.querySelector(".hamelp-ai-overview__result"),l="true"===e.dataset.showSources;r?.addEventListener("submit",async r=>{r.preventDefault();const n=s.value.trim();if(n){e.classList.remove("has-result","has-error"),e.classList.add("is-loading"),i.innerHTML='<span class="spinner"></span> '+(0,a.__)("Generating answer…","hamelp");try{const r=await t()({path:"/hamelp/v1/ai-overview",method:"POST",data:{query:n}}),s=function(e,r){if(!r?.length)return e;const t={};return r.forEach((e,r)=>{t[e.id]={...e,index:r+1}}),e.replace(/\[ID:(\d+)\]/g,(e,r)=>{const a=t[parseInt(r,10)];return a?`<a href="${a.url}" class="hamelp-ai-overview__ref" title="${a.title}">(Ref. ${a.index})</a>`:e})}(function(e){if(!e)return"";let r=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");return r=r.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),r=r.replace(/__(.+?)__/g,"<strong>$1</strong>"),r=r.replace(/(?<!\w)\*([^*]+?)\*(?!\w)/g,"<em>$1</em>"),r=r.replace(/(?<!\w)_([^_]+?)_(?!\w)/g,"<em>$1</em>"),r=r.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),r.split(/\n\n+/).map(e=>{const r=e.trim();if(!r)return"";const t=r.split("\n");return t.some(e=>/^\d+\.\s/.test(e.trim()))&&t.every(e=>/^\d+\.\s/.test(e.trim())||!e.trim())?`<ol>${t.filter(e=>e.trim()).map(e=>`<li>${e.replace(/^\d+\.\s/,"")}</li>`).join("")}</ol>`:t.some(e=>/^[-*]\s/.test(e.trim()))&&t.every(e=>/^[-*]\s/.test(e.trim())||!e.trim())?`<ul>${t.filter(e=>e.trim()).map(e=>`<li>${e.replace(/^[-*]\s/,"")}</li>`).join("")}</ul>`:`<p>${r.replace(/\n/g,"<br>")}</p>`}).filter(e=>e).join("")}(r.answer),r.sources);let o=`<div class="hamelp-ai-overview__answer">${s}</div>`;l&&r.sources?.length&&(o+='<div class="hamelp-ai-overview__sources"><p>'+(0,a.__)("Related FAQs:","hamelp")+"</p><ul>",r.sources.forEach(e=>{o+=`<li><a href="${e.url}">${e.title}</a></li>`}),o+="</ul></div>"),i.innerHTML=o,e.classList.remove("is-loading"),e.classList.add("has-result")}catch(r){i.innerHTML=`<div class="hamelp-ai-overview__error">${r.message||(0,a.__)("An error occurred.","hamelp")}</div>`,e.classList.remove("is-loading"),e.classList.add("has-error")}}})})})();1 (()=>{"use strict";var e={n:r=>{var t=r&&r.__esModule?()=>r.default:()=>r;return e.d(t,{a:t}),t},d:(r,t)=>{for(var a in t)e.o(t,a)&&!e.o(r,a)&&Object.defineProperty(r,a,{enumerable:!0,get:t[a]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r)};const r=window.wp.apiFetch;var t=e.n(r);const a=window.wp.i18n;document.querySelectorAll(".hamelp-ai-overview").forEach(e=>{const r=e.querySelector("form"),s=e.querySelector("input"),l=e.querySelector(".hamelp-ai-overview__result"),i="true"===e.dataset.showSources;r?.addEventListener("submit",async r=>{r.preventDefault();const n=s.value.trim();if(n){e.classList.remove("has-result","has-error"),e.classList.add("is-loading"),l.innerHTML='<span class="spinner"></span> '+(0,a.__)("Generating answer…","hamelp");try{const r=await t()({path:"/hamelp/v1/ai-overview",method:"POST",data:{query:n}}),s=function(e,r){if(!r?.length)return e;const t={};return r.forEach((e,r)=>{t[e.id]={...e,index:r+1}}),e.replace(/\[ID:\d+(?:,\s*ID:\d+)*\]/g,e=>{const r=[...e.matchAll(/ID:(\d+)/g)].map(e=>parseInt(e[1],10)).map(e=>{const r=t[e];return r?`<a href="${r.url}" class="hamelp-ai-overview__ref" title="${r.title}">(Ref. ${r.index})</a>`:null}).filter(Boolean);return r.length?r.join(" "):e})}(function(e){if(!e)return"";let r=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");return r=r.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),r=r.replace(/__(.+?)__/g,"<strong>$1</strong>"),r=r.replace(/(?<!\w)\*([^*]+?)\*(?!\w)/g,"<em>$1</em>"),r=r.replace(/(?<!\w)_([^_]+?)_(?!\w)/g,"<em>$1</em>"),r=r.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),r.split(/\n\n+/).map(e=>{const r=e.trim();if(!r)return"";const t=r.split("\n");return t.some(e=>/^\d+\.\s/.test(e.trim()))&&t.every(e=>/^\d+\.\s/.test(e.trim())||!e.trim())?`<ol>${t.filter(e=>e.trim()).map(e=>`<li>${e.replace(/^\d+\.\s/,"")}</li>`).join("")}</ol>`:t.some(e=>/^[-*]\s/.test(e.trim()))&&t.every(e=>/^[-*]\s/.test(e.trim())||!e.trim())?`<ul>${t.filter(e=>e.trim()).map(e=>`<li>${e.replace(/^[-*]\s/,"")}</li>`).join("")}</ul>`:`<p>${r.replace(/\n/g,"<br>")}</p>`}).filter(e=>e).join("")}(r.answer),r.sources);let o=`<div class="hamelp-ai-overview__answer">${s}</div>`;i&&r.sources?.length&&(o+='<div class="hamelp-ai-overview__sources"><p>'+(0,a.__)("Related FAQs:","hamelp")+"</p><ul>",r.sources.forEach(e=>{o+=`<li><a href="${e.url}">${e.title}</a></li>`}),o+="</ul></div>"),l.innerHTML=o,e.classList.remove("is-loading"),e.classList.add("has-result")}catch(r){l.innerHTML=`<div class="hamelp-ai-overview__error">${r.message||(0,a.__)("An error occurred.","hamelp")}</div>`,e.classList.remove("is-loading"),e.classList.add("has-error")}}})})})(); -
hamelp/tags/2.0.2/hamelp.php
r3447191 r3447972 4 4 * Plugin URI: https://wordpress.org/plugins/hamelp 5 5 * Description: FAQ generator by Hametuha. 6 * Version: 2.0. 16 * Version: 2.0.2 7 7 * Author: Hametuha INC. 8 8 * Author URI: https://hametuha.co.jp -
hamelp/tags/2.0.2/readme.txt
r3447191 r3447972 4 4 Tags: faq,help 5 5 Tested up to: 6.9 6 Stable Tag: 2.0. 16 Stable Tag: 2.0.2 7 7 License: GPL 3.0 or later 8 8 License URI: https://www.gnu.org/licenses/gpl-3.0.html -
hamelp/tags/2.0.2/src/blocks/ai-overview/view.js
r3447191 r3447972 7 7 import apiFetch from '@wordpress/api-fetch'; 8 8 import { __ } from '@wordpress/i18n'; 9 10 /** 11 * Convert simple markdown to HTML. 12 * 13 * Supports: bold, italic, links, lists (ordered/unordered), paragraphs. 14 * 15 * @param {string} text Markdown text. 16 * @return {string} HTML string. 17 */ 18 function parseMarkdown( text ) { 19 if ( ! text ) { 20 return ''; 21 } 22 23 // Escape HTML special characters first 24 let html = text 25 .replace( /&/g, '&' ) 26 .replace( /</g, '<' ) 27 .replace( />/g, '>' ); 28 29 // Bold: **text** or __text__ 30 html = html.replace( /\*\*(.+?)\*\*/g, '<strong>$1</strong>' ); 31 html = html.replace( /__(.+?)__/g, '<strong>$1</strong>' ); 32 33 // Italic: *text* or _text_ (but not inside words) 34 html = html.replace( /(?<!\w)\*([^*]+?)\*(?!\w)/g, '<em>$1</em>' ); 35 html = html.replace( /(?<!\w)_([^_]+?)_(?!\w)/g, '<em>$1</em>' ); 36 37 // Links: [text](url) 38 html = html.replace( 39 /\[([^\]]+)\]\(([^)]+)\)/g, 40 '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>' 41 ); 42 43 // Split into paragraphs by double newlines 44 const paragraphs = html.split( /\n\n+/ ); 45 46 const processedParagraphs = paragraphs.map( ( para ) => { 47 const trimmed = para.trim(); 48 if ( ! trimmed ) { 49 return ''; 50 } 51 52 // Check if this is a list 53 const lines = trimmed.split( '\n' ); 54 55 // Check for ordered list (1. 2. 3.) 56 const hasOrderedItems = lines.some( ( line ) => 57 /^\d+\.\s/.test( line.trim() ) 58 ); 59 if ( hasOrderedItems ) { 60 const isOrderedList = lines.every( 61 ( line ) => /^\d+\.\s/.test( line.trim() ) || ! line.trim() 62 ); 63 if ( isOrderedList ) { 64 const items = lines 65 .filter( ( line ) => line.trim() ) 66 .map( 67 ( line ) => 68 `<li>${ line.replace( /^\d+\.\s/, '' ) }</li>` 69 ) 70 .join( '' ); 71 return `<ol>${ items }</ol>`; 72 } 73 } 74 75 // Check for unordered list (- or *) 76 const hasUnorderedItems = lines.some( ( line ) => 77 /^[-*]\s/.test( line.trim() ) 78 ); 79 if ( hasUnorderedItems ) { 80 const isUnorderedList = lines.every( 81 ( line ) => /^[-*]\s/.test( line.trim() ) || ! line.trim() 82 ); 83 if ( isUnorderedList ) { 84 const items = lines 85 .filter( ( line ) => line.trim() ) 86 .map( 87 ( line ) => 88 `<li>${ line.replace( /^[-*]\s/, '' ) }</li>` 89 ) 90 .join( '' ); 91 return `<ul>${ items }</ul>`; 92 } 93 } 94 95 // Regular paragraph - convert single newlines to <br> 96 return `<p>${ trimmed.replace( /\n/g, '<br>' ) }</p>`; 97 } ); 98 99 return processedParagraphs.filter( ( p ) => p ).join( '' ); 100 } 101 102 /** 103 * Replace [ID:xxx] references in HTML with linked source indices. 104 * 105 * @param {string} html Parsed HTML string. 106 * @param {Array} sources Array of { id, title, url } objects. 107 * @return {string} HTML with references replaced by links. 108 */ 109 function replaceIdReferences( html, sources ) { 110 if ( ! sources?.length ) { 111 return html; 112 } 113 const sourceMap = {}; 114 sources.forEach( ( source, i ) => { 115 sourceMap[ source.id ] = { ...source, index: i + 1 }; 116 } ); 117 return html.replace( /\[ID:(\d+)\]/g, ( match, id ) => { 118 const source = sourceMap[ parseInt( id, 10 ) ]; 119 if ( source ) { 120 return `<a href="${ source.url }" class="hamelp-ai-overview__ref" title="${ source.title }">(Ref. ${ source.index })</a>`; 121 } 122 return match; 123 } ); 124 } 9 import { parseMarkdown, replaceIdReferences } from './utils'; 125 10 126 11 document.querySelectorAll( '.hamelp-ai-overview' ).forEach( ( container ) => { -
hamelp/tags/2.0.2/vendor/composer/installed.php
r3447191 r3447972 2 2 'root' => array( 3 3 'name' => 'hametuha/hamelp', 4 'pretty_version' => 'v2.0. 1',5 'version' => '2.0. 1.0',6 'reference' => ' ebdd600a0831b7a436fc5a5cba8c9f9487183f33',4 'pretty_version' => 'v2.0.2', 5 'version' => '2.0.2.0', 6 'reference' => 'cec9f36d5013096c7c46ab983233b3fcb5f7fbe6', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../', … … 12 12 'versions' => array( 13 13 'hametuha/hamelp' => array( 14 'pretty_version' => 'v2.0. 1',15 'version' => '2.0. 1.0',16 'reference' => ' ebdd600a0831b7a436fc5a5cba8c9f9487183f33',14 'pretty_version' => 'v2.0.2', 15 'version' => '2.0.2.0', 16 'reference' => 'cec9f36d5013096c7c46ab983233b3fcb5f7fbe6', 17 17 'type' => 'wordpress-plugin', 18 18 'install_path' => __DIR__ . '/../../', -
hamelp/trunk/assets/blocks/ai-overview/view.asset.php
r3447047 r3447972 1 <?php return array('dependencies' => array('wp-api-fetch', 'wp-i18n'), 'version' => ' 097d03e44d3442e34ff3');1 <?php return array('dependencies' => array('wp-api-fetch', 'wp-i18n'), 'version' => '3c41d0785b053bdf50c3'); -
hamelp/trunk/assets/blocks/ai-overview/view.js
r3447047 r3447972 1 (()=>{"use strict";var e={n:r=>{var t=r&&r.__esModule?()=>r.default:()=>r;return e.d(t,{a:t}),t},d:(r,t)=>{for(var a in t)e.o(t,a)&&!e.o(r,a)&&Object.defineProperty(r,a,{enumerable:!0,get:t[a]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r)};const r=window.wp.apiFetch;var t=e.n(r);const a=window.wp.i18n;document.querySelectorAll(".hamelp-ai-overview").forEach(e=>{const r=e.querySelector("form"),s=e.querySelector("input"), i=e.querySelector(".hamelp-ai-overview__result"),l="true"===e.dataset.showSources;r?.addEventListener("submit",async r=>{r.preventDefault();const n=s.value.trim();if(n){e.classList.remove("has-result","has-error"),e.classList.add("is-loading"),i.innerHTML='<span class="spinner"></span> '+(0,a.__)("Generating answer…","hamelp");try{const r=await t()({path:"/hamelp/v1/ai-overview",method:"POST",data:{query:n}}),s=function(e,r){if(!r?.length)return e;const t={};return r.forEach((e,r)=>{t[e.id]={...e,index:r+1}}),e.replace(/\[ID:(\d+)\]/g,(e,r)=>{const a=t[parseInt(r,10)];return a?`<a href="${a.url}" class="hamelp-ai-overview__ref" title="${a.title}">(Ref. ${a.index})</a>`:e})}(function(e){if(!e)return"";let r=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");return r=r.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),r=r.replace(/__(.+?)__/g,"<strong>$1</strong>"),r=r.replace(/(?<!\w)\*([^*]+?)\*(?!\w)/g,"<em>$1</em>"),r=r.replace(/(?<!\w)_([^_]+?)_(?!\w)/g,"<em>$1</em>"),r=r.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),r.split(/\n\n+/).map(e=>{const r=e.trim();if(!r)return"";const t=r.split("\n");return t.some(e=>/^\d+\.\s/.test(e.trim()))&&t.every(e=>/^\d+\.\s/.test(e.trim())||!e.trim())?`<ol>${t.filter(e=>e.trim()).map(e=>`<li>${e.replace(/^\d+\.\s/,"")}</li>`).join("")}</ol>`:t.some(e=>/^[-*]\s/.test(e.trim()))&&t.every(e=>/^[-*]\s/.test(e.trim())||!e.trim())?`<ul>${t.filter(e=>e.trim()).map(e=>`<li>${e.replace(/^[-*]\s/,"")}</li>`).join("")}</ul>`:`<p>${r.replace(/\n/g,"<br>")}</p>`}).filter(e=>e).join("")}(r.answer),r.sources);let o=`<div class="hamelp-ai-overview__answer">${s}</div>`;l&&r.sources?.length&&(o+='<div class="hamelp-ai-overview__sources"><p>'+(0,a.__)("Related FAQs:","hamelp")+"</p><ul>",r.sources.forEach(e=>{o+=`<li><a href="${e.url}">${e.title}</a></li>`}),o+="</ul></div>"),i.innerHTML=o,e.classList.remove("is-loading"),e.classList.add("has-result")}catch(r){i.innerHTML=`<div class="hamelp-ai-overview__error">${r.message||(0,a.__)("An error occurred.","hamelp")}</div>`,e.classList.remove("is-loading"),e.classList.add("has-error")}}})})})();1 (()=>{"use strict";var e={n:r=>{var t=r&&r.__esModule?()=>r.default:()=>r;return e.d(t,{a:t}),t},d:(r,t)=>{for(var a in t)e.o(t,a)&&!e.o(r,a)&&Object.defineProperty(r,a,{enumerable:!0,get:t[a]})},o:(e,r)=>Object.prototype.hasOwnProperty.call(e,r)};const r=window.wp.apiFetch;var t=e.n(r);const a=window.wp.i18n;document.querySelectorAll(".hamelp-ai-overview").forEach(e=>{const r=e.querySelector("form"),s=e.querySelector("input"),l=e.querySelector(".hamelp-ai-overview__result"),i="true"===e.dataset.showSources;r?.addEventListener("submit",async r=>{r.preventDefault();const n=s.value.trim();if(n){e.classList.remove("has-result","has-error"),e.classList.add("is-loading"),l.innerHTML='<span class="spinner"></span> '+(0,a.__)("Generating answer…","hamelp");try{const r=await t()({path:"/hamelp/v1/ai-overview",method:"POST",data:{query:n}}),s=function(e,r){if(!r?.length)return e;const t={};return r.forEach((e,r)=>{t[e.id]={...e,index:r+1}}),e.replace(/\[ID:\d+(?:,\s*ID:\d+)*\]/g,e=>{const r=[...e.matchAll(/ID:(\d+)/g)].map(e=>parseInt(e[1],10)).map(e=>{const r=t[e];return r?`<a href="${r.url}" class="hamelp-ai-overview__ref" title="${r.title}">(Ref. ${r.index})</a>`:null}).filter(Boolean);return r.length?r.join(" "):e})}(function(e){if(!e)return"";let r=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");return r=r.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),r=r.replace(/__(.+?)__/g,"<strong>$1</strong>"),r=r.replace(/(?<!\w)\*([^*]+?)\*(?!\w)/g,"<em>$1</em>"),r=r.replace(/(?<!\w)_([^_]+?)_(?!\w)/g,"<em>$1</em>"),r=r.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),r.split(/\n\n+/).map(e=>{const r=e.trim();if(!r)return"";const t=r.split("\n");return t.some(e=>/^\d+\.\s/.test(e.trim()))&&t.every(e=>/^\d+\.\s/.test(e.trim())||!e.trim())?`<ol>${t.filter(e=>e.trim()).map(e=>`<li>${e.replace(/^\d+\.\s/,"")}</li>`).join("")}</ol>`:t.some(e=>/^[-*]\s/.test(e.trim()))&&t.every(e=>/^[-*]\s/.test(e.trim())||!e.trim())?`<ul>${t.filter(e=>e.trim()).map(e=>`<li>${e.replace(/^[-*]\s/,"")}</li>`).join("")}</ul>`:`<p>${r.replace(/\n/g,"<br>")}</p>`}).filter(e=>e).join("")}(r.answer),r.sources);let o=`<div class="hamelp-ai-overview__answer">${s}</div>`;i&&r.sources?.length&&(o+='<div class="hamelp-ai-overview__sources"><p>'+(0,a.__)("Related FAQs:","hamelp")+"</p><ul>",r.sources.forEach(e=>{o+=`<li><a href="${e.url}">${e.title}</a></li>`}),o+="</ul></div>"),l.innerHTML=o,e.classList.remove("is-loading"),e.classList.add("has-result")}catch(r){l.innerHTML=`<div class="hamelp-ai-overview__error">${r.message||(0,a.__)("An error occurred.","hamelp")}</div>`,e.classList.remove("is-loading"),e.classList.add("has-error")}}})})})(); -
hamelp/trunk/hamelp.php
r3447191 r3447972 4 4 * Plugin URI: https://wordpress.org/plugins/hamelp 5 5 * Description: FAQ generator by Hametuha. 6 * Version: 2.0. 16 * Version: 2.0.2 7 7 * Author: Hametuha INC. 8 8 * Author URI: https://hametuha.co.jp -
hamelp/trunk/readme.txt
r3447191 r3447972 4 4 Tags: faq,help 5 5 Tested up to: 6.9 6 Stable Tag: 2.0. 16 Stable Tag: 2.0.2 7 7 License: GPL 3.0 or later 8 8 License URI: https://www.gnu.org/licenses/gpl-3.0.html -
hamelp/trunk/src/blocks/ai-overview/view.js
r3447191 r3447972 7 7 import apiFetch from '@wordpress/api-fetch'; 8 8 import { __ } from '@wordpress/i18n'; 9 10 /** 11 * Convert simple markdown to HTML. 12 * 13 * Supports: bold, italic, links, lists (ordered/unordered), paragraphs. 14 * 15 * @param {string} text Markdown text. 16 * @return {string} HTML string. 17 */ 18 function parseMarkdown( text ) { 19 if ( ! text ) { 20 return ''; 21 } 22 23 // Escape HTML special characters first 24 let html = text 25 .replace( /&/g, '&' ) 26 .replace( /</g, '<' ) 27 .replace( />/g, '>' ); 28 29 // Bold: **text** or __text__ 30 html = html.replace( /\*\*(.+?)\*\*/g, '<strong>$1</strong>' ); 31 html = html.replace( /__(.+?)__/g, '<strong>$1</strong>' ); 32 33 // Italic: *text* or _text_ (but not inside words) 34 html = html.replace( /(?<!\w)\*([^*]+?)\*(?!\w)/g, '<em>$1</em>' ); 35 html = html.replace( /(?<!\w)_([^_]+?)_(?!\w)/g, '<em>$1</em>' ); 36 37 // Links: [text](url) 38 html = html.replace( 39 /\[([^\]]+)\]\(([^)]+)\)/g, 40 '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>' 41 ); 42 43 // Split into paragraphs by double newlines 44 const paragraphs = html.split( /\n\n+/ ); 45 46 const processedParagraphs = paragraphs.map( ( para ) => { 47 const trimmed = para.trim(); 48 if ( ! trimmed ) { 49 return ''; 50 } 51 52 // Check if this is a list 53 const lines = trimmed.split( '\n' ); 54 55 // Check for ordered list (1. 2. 3.) 56 const hasOrderedItems = lines.some( ( line ) => 57 /^\d+\.\s/.test( line.trim() ) 58 ); 59 if ( hasOrderedItems ) { 60 const isOrderedList = lines.every( 61 ( line ) => /^\d+\.\s/.test( line.trim() ) || ! line.trim() 62 ); 63 if ( isOrderedList ) { 64 const items = lines 65 .filter( ( line ) => line.trim() ) 66 .map( 67 ( line ) => 68 `<li>${ line.replace( /^\d+\.\s/, '' ) }</li>` 69 ) 70 .join( '' ); 71 return `<ol>${ items }</ol>`; 72 } 73 } 74 75 // Check for unordered list (- or *) 76 const hasUnorderedItems = lines.some( ( line ) => 77 /^[-*]\s/.test( line.trim() ) 78 ); 79 if ( hasUnorderedItems ) { 80 const isUnorderedList = lines.every( 81 ( line ) => /^[-*]\s/.test( line.trim() ) || ! line.trim() 82 ); 83 if ( isUnorderedList ) { 84 const items = lines 85 .filter( ( line ) => line.trim() ) 86 .map( 87 ( line ) => 88 `<li>${ line.replace( /^[-*]\s/, '' ) }</li>` 89 ) 90 .join( '' ); 91 return `<ul>${ items }</ul>`; 92 } 93 } 94 95 // Regular paragraph - convert single newlines to <br> 96 return `<p>${ trimmed.replace( /\n/g, '<br>' ) }</p>`; 97 } ); 98 99 return processedParagraphs.filter( ( p ) => p ).join( '' ); 100 } 101 102 /** 103 * Replace [ID:xxx] references in HTML with linked source indices. 104 * 105 * @param {string} html Parsed HTML string. 106 * @param {Array} sources Array of { id, title, url } objects. 107 * @return {string} HTML with references replaced by links. 108 */ 109 function replaceIdReferences( html, sources ) { 110 if ( ! sources?.length ) { 111 return html; 112 } 113 const sourceMap = {}; 114 sources.forEach( ( source, i ) => { 115 sourceMap[ source.id ] = { ...source, index: i + 1 }; 116 } ); 117 return html.replace( /\[ID:(\d+)\]/g, ( match, id ) => { 118 const source = sourceMap[ parseInt( id, 10 ) ]; 119 if ( source ) { 120 return `<a href="${ source.url }" class="hamelp-ai-overview__ref" title="${ source.title }">(Ref. ${ source.index })</a>`; 121 } 122 return match; 123 } ); 124 } 9 import { parseMarkdown, replaceIdReferences } from './utils'; 125 10 126 11 document.querySelectorAll( '.hamelp-ai-overview' ).forEach( ( container ) => { -
hamelp/trunk/vendor/composer/installed.php
r3447191 r3447972 2 2 'root' => array( 3 3 'name' => 'hametuha/hamelp', 4 'pretty_version' => 'v2.0. 1',5 'version' => '2.0. 1.0',6 'reference' => ' ebdd600a0831b7a436fc5a5cba8c9f9487183f33',4 'pretty_version' => 'v2.0.2', 5 'version' => '2.0.2.0', 6 'reference' => 'cec9f36d5013096c7c46ab983233b3fcb5f7fbe6', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../', … … 12 12 'versions' => array( 13 13 'hametuha/hamelp' => array( 14 'pretty_version' => 'v2.0. 1',15 'version' => '2.0. 1.0',16 'reference' => ' ebdd600a0831b7a436fc5a5cba8c9f9487183f33',14 'pretty_version' => 'v2.0.2', 15 'version' => '2.0.2.0', 16 'reference' => 'cec9f36d5013096c7c46ab983233b3fcb5f7fbe6', 17 17 'type' => 'wordpress-plugin', 18 18 'install_path' => __DIR__ . '/../../',
Note: See TracChangeset
for help on using the changeset viewer.