UNPKG

markdown-to-json-ld

Version:

Transform Markdown to JSON-LD with Advanced Table & Annotation Support for JavaScript developers optimizing for AI and NLWeb

2 lines (1 loc) 19.1 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("js-yaml")):"function"==typeof define&&define.amd?define(["exports","js-yaml"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).MarkdownToJsonLd={},e.jsyaml)}(this,(function(e,t){"use strict";function n(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,h(r.key),r)}}function i(e,t,n){return t&&a(e.prototype,t),n&&a(e,n),Object.defineProperty(e,"prototype",{writable:!1}),e}function o(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=m(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,a=function(){};return{s:a,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,o=!0,c=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return o=e.done,e},e:function(e){c=!0,i=e},f:function(){try{o||null==n.return||n.return()}finally{if(c)throw i}}}}function c(e,t,n){return(t=h(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?l(Object(n),!0).forEach((function(t){c(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function u(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,i,o,c=[],l=!0,s=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(r=i.call(n)).done)&&(c.push(r.value),c.length!==t);l=!0);}catch(e){s=!0,a=e}finally{try{if(!l&&null!=n.return&&(o=n.return(),Object(o)!==o))return}finally{if(s)throw a}}return c}}(e,t)||m(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(e){return function(e){if(Array.isArray(e))return n(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||m(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function h(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}function m(e,t){if(e){if("string"==typeof e)return n(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?n(e,t):void 0}}var f=function(){return i((function e(){r(this,e)}),[{key:"extractMetadata",value:function(e){var n=e.match(/^---\n([\s\S]*?)\n---\n/);if(!n)return{};try{var r=n[1].trim();return t.load(r)||{}}catch(e){return console.error("YAML parsing error:",e),{}}}},{key:"extractContext",value:function(e){var t=e.match(/^@context:\s*(https?:\/\/[^\s]+)$/m);return t?t[1]:"https://schema.org"}},{key:"extractTables",value:function(e){for(var t=this,n=[],r=this.removeYamlAndContext(e).split("\n"),a=null,i=[],o=[],c=0;c<r.length;c++){var l=r[c].trim();if(l.match(/^\|.*\|$/)){var s=l.split("|").slice(1,-1).map((function(e){return e.trim()}));if(a){if(!s.every((function(e){return e.match(/^[-:\s]*$/)}))){var u=s.map((function(e){return t.cleanText(e)}));u.some((function(e){return e.length>0}))&&o.push(u)}}else i=s.map((function(e){return t.cleanText(e)})),a={"@type":"Table",name:"Table ".concat(n.length+1),description:"Data table with columns: ".concat(i.join(", "))}}else if(l.match(/^\|[-:\s|]+\|$/));else if(a&&(i.length>0||o.length>0)){var p=this.processTableToSchema(i,o,n.length+1);n.push(p),a=null,i=[],o=[]}}if(a&&(i.length>0||o.length>0)){var h=this.processTableToSchema(i,o,n.length+1);n.push(h)}return n}},{key:"processTableToSchema",value:function(e,t,n){var r=this.analyzeTableType(e,t),a={"@type":r.type,name:r.name||"Table ".concat(n),description:this.generateTableDescription(e,t,r)};switch(r.category){case"pricing":return this.createPricingTable(a,e,t);case"comparison":return this.createComparisonTable(a,e,t);case"specification":return this.createSpecificationTable(a,e,t);case"listing":return this.createListingTable(a,e,t);case"dataset":return this.createDatasetTable(a,e,t);default:return this.createGenericTable(a,e,t)}}},{key:"analyzeTableType",value:function(e,t){var n=e.join(" ").toLowerCase(),r=t.flat().join(" ").toLowerCase();return n.match(/price|cost|plan|tier|subscription|fee|rate/)||r.match(/\$|€|£|¥|₹|\d+\.\d{2}|free|premium|basic|pro/)?{type:"Table",category:"pricing",name:"Pricing Comparison Table"}:n.match(/vs|versus|compare|feature|support|included|type|model/)||e.length>2&&t.some((function(e){return e.some((function(e){return e&&e.toString().toLowerCase().match(/yes|no|✓|✗|included|supported|available|none|limited|partial/)}))}))?{type:"Table",category:"comparison",name:"Feature Comparison Table"}:n.match(/spec|specification|property|attribute|parameter|value|requirement/)||e.some((function(e){return e.match(/spec|model|version|size|weight|dimension/)}))?{type:"Table",category:"specification",name:"Specifications Table"}:n.match(/name|title|item|product|service|company|organization/)&&t.length>3?{type:"Table",category:"listing",name:"Directory Listing Table"}:e.length>3&&t.length>5&&e.some((function(e){return e.match(/data|metric|value|count|number|amount/)}))?{type:"Dataset",category:"dataset",name:"Data Table"}:{type:"Table",category:"generic",name:"Data Table"}}},{key:"generateTableDescription",value:function(e,t,n){var r=t.length,a=e.length,i="A ".concat(n.category," table with ").concat(a," columns and ").concat(r," rows");switch(n.category){case"pricing":i+=" containing pricing information and plan comparisons";break;case"comparison":i+=" comparing features and capabilities across different options";break;case"specification":i+=" listing technical specifications and properties";break;case"listing":i+=" providing a directory of items, companies, or resources";break;case"dataset":i+=" containing structured data for analysis";break;default:i+=" with structured tabular data"}return e.length>0&&(i+=". Columns: ".concat(e.slice(0,3).join(", ")),e.length>3&&(i+=" and ".concat(e.length-3," more"))),i+"."}},{key:"createPricingTable",value:function(e,t,n){var r=t.findIndex((function(e){return e.toLowerCase().match(/price|cost|fee|rate/)})),a=t.findIndex((function(e){return e.toLowerCase().match(/plan|tier|name|package/)}));e.about={"@type":"PriceSpecification",description:"Pricing information and plan comparisons"};var i="Pricing table containing: ";n.length>0&&(i+=n.map((function(e){var t=a>=0?e[a]:"Plan",n=r>=0?e[r]:"Price not specified";return"".concat(t,": ").concat(n)})).join(", "));return e.text=i,e}},{key:"createComparisonTable",value:function(e,t,n){e["@type"]="Table",e.about={"@type":"Thing",name:"Feature Comparison",description:"Comparison of features, capabilities, or characteristics"};var r="";if(t.length>0&&(r="Comparison table with columns: ".concat(t.join(", "),". ")),n.length>0){var a=n.slice(0,3).map((function(e){return t.map((function(t,n){return"".concat(t,": ").concat(e[n]||"N/A")})).join(", ")}));r+="Data includes: ".concat(a.join("; "),"."),n.length>3&&(r+=" (".concat(n.length-3," more rows)"))}return e.text=r.trim(),e}},{key:"createSpecificationTable",value:function(e,t,n){e.about={"@type":"Product",description:"Technical specifications and properties"};var r=t.findIndex((function(e){return e.toLowerCase().match(/property|spec|feature|attribute/)})),a=t.findIndex((function(e){return e.toLowerCase().match(/value|specification|detail/)})),i="Specification table with properties: ";n.length>0&&(i+=n.slice(0,5).map((function(e){var t=r>=0?e[r]:"Property ".concat(n.indexOf(e)+1),i=a>=0?e[a]:"Value not specified";return"".concat(t,": ").concat(i)})).join(", "),n.length>5&&(i+=" and ".concat(n.length-5," more specifications")));return e.text=i,e}},{key:"createListingTable",value:function(e,t,n){var r=t.findIndex((function(e){return e.toLowerCase().match(/name|title|company|organization|item/)})),a=t.findIndex((function(e){return e.toLowerCase().match(/url|website|link/)})),i="Directory listing with entries: ";n.length>0&&(i+=n.slice(0,3).map((function(e){var t=r>=0?e[r]:"Item ".concat(n.indexOf(e)+1),i="";if(a>=0&&e[a]){var o=e[a];!o.startsWith("http")||o.includes("example.com")||o.includes("docs.octl.org")||o.match(/\.(test|invalid|local)($|\/)/)||(i=" (".concat(o,")"))}return t+i})).join(", "),n.length>3&&(i+=" and ".concat(n.length-3," more items")));return e.text=i,e}},{key:"createDatasetTable",value:function(e,t,n){e["@type"]="Dataset",e.description="Dataset with ".concat(t.length," variables and ").concat(n.length," observations");var r="Dataset containing ".concat(n.length," rows of data with variables: ").concat(t.join(", "),"."),a=this.detectNumericColumns(t,n);return a.length>0&&(r+=" Includes ".concat(a.length," numeric variables with statistical analysis available.")),e.text=r,e}},{key:"createGenericTable",value:function(e,t,n){return this.addTableStructure(e,t,n)}},{key:"addTableStructure",value:function(e,t,n){var r="";if(t.length>0&&(r="Table headers: ".concat(t.join(", "),". ")),n.length>0){var a=n.slice(0,3).map((function(e){return t.map((function(t,n){return"".concat(t,": ").concat(e[n]||"N/A")})).join(", ")}));r+="Sample data: ".concat(a.join("; "),"."),n.length>3&&(r+=" (".concat(n.length-3," more rows)"))}return e.text=r.trim(),e.description=e.description||"Data table with ".concat(t.length," columns and ").concat(n.length," rows"),e}},{key:"extractPrice",value:function(e){var t=e.match(/([$€£¥₹])\s*(\d+(?:\.\d{2})?)|(\d+(?:\.\d{2})?)\s*(USD|EUR|GBP|JPY|INR)/i);if(t){var n=t[1],r=t[2]||t[3],a=n?{$:"USD","€":"EUR","£":"GBP","¥":"JPY","₹":"INR"}[n]:t[4];return{amount:parseFloat(r),currency:a}}return null}},{key:"detectNumericColumns",value:function(e,t){var n=[];return e.forEach((function(e,r){var a=t.map((function(e){return e[r]})).filter((function(e){return e&&!isNaN(parseFloat(e))})).map((function(e){return parseFloat(e)}));a.length>.5*t.length&&n.push({name:e,index:r,count:a.length,min:Math.min.apply(Math,p(a)),max:Math.max.apply(Math,p(a)),average:a.reduce((function(e,t){return e+t}),0)/a.length})})),n}},{key:"extractLists",value:function(e){var t,n=[],r=null,a=[],i=null,c=o(this.removeYamlAndContext(e).split("\n"));try{for(c.s();!(t=c.n()).done;){var l=t.value.trim(),s=l.match(/^[-*+]\s+(.+)$/),u=l.match(/^\d+\.\s+(.+)$/);if(s||u){var p=s?s[1]:u[1],h=s?"unordered":"ordered";r&&i===h||(r&&a.length>0&&(r.itemListElement=a,r.numberOfItems=a.length,n.push(r)),r={"@type":"ItemList",name:"".concat(s?"Bulleted":"Numbered"," List ").concat(n.length+1),description:"A ".concat(s?"bulleted":"numbered"," list of items")},a=[],i=h),a.push({"@type":"ListItem",name:this.cleanText(p),position:a.length+1})}else r&&""===l||r&&!l.match(/^#/)&&l&&a.length>0&&(r.itemListElement=a,r.numberOfItems=a.length,n.push(r),r=null,a=[],i=null)}}catch(e){c.e(e)}finally{c.f()}return r&&a.length>0&&(r.itemListElement=a,r.numberOfItems=a.length,n.push(r)),n}},{key:"extractLinks",value:function(e){for(var t,n=[],r=/\[([^\]]+)\]\(([^)]+)\)(?!@\{)/g;null!==(t=r.exec(e));){var a=u(t,3),i=a[1],o=a[2];if(o.startsWith("http")){var c="WebPage";o.includes("github.com")?c="SoftwareSourceCode":o.includes("youtube.com")||o.includes("youtu.be")?c="VideoObject":o.match(/\.(pdf|doc|docx)$/i)?c="DigitalDocument":o.match(/\.(jpg|jpeg|png|gif|svg)$/i)&&(c="ImageObject"),n.push({"@type":c,name:this.cleanText(i),url:o,"@id":o})}}return n}},{key:"extractAnnotations",value:function(e){for(var t,n=[],r=/\[([^\]]*?)\](?:\(([^)]+)\))?@\{([^}]+)\}/g;null!==(t=r.exec(e));){var a=u(t,4),i=a[1],o=a[2],c=a[3],l=this.parseAnnotation(i,o,c);l&&n.push(l)}return n}},{key:"parseAnnotation",value:function(e,t,n){for(var r=n.split(",").map((function(e){return e.trim()})),a=r[0],i={"@type":a},o=1;o<r.length;o++){var c=u(r[o].split("=").map((function(e){return e.trim()})),2),l=c[0],p=c[1];if(l&&p)if("@id"===l)i["@id"]=p;else if(l.includes(".")){var h=u(l.split("."),2),m=h[0],f=h[1];i[m]=i[m]||{},i[m][f]="publisher"===m&&"name"===f?p:this.processValue(p)}else i[l]=this.processValue(p)}return!i.name&&e&&(i.name=e),t&&(i.url=t),"Person"===a&&e&&!i.givenName&&(i.givenName=e),i.license&&"string"==typeof i.license&&i.license.startsWith("http")&&(i.license={"@id":i.license}),s({"@context":"https://schema.org"},i)}},{key:"processValue",value:function(e){return e.match(/^https?:\/\//)||e.startsWith("#"),e}},{key:"extractTitle",value:function(e){var t=this.removeYamlAndContext(e).match(/^#\s+(.+)$/m);return t?this.cleanText(t[1]):null}},{key:"extractDescription",value:function(e,t){var n,r="",a=o(this.removeYamlAndContext(e).split("\n"));try{for(a.s();!(n=a.n()).done;){var i=n.value.trim();!i||i.match(/^#+\s/)||i.match(/^\|.*\|$/)||i.match(/^\|[-:\s|]+\|$/)||i.match(/^[-*+]\s/)||i.match(/^\d+\.\s/)||i.match(/^\[.*\]@\{/)||(r+=" "+this.cleanText(i))}}catch(e){a.e(e)}finally{a.f()}return r.length>0?r.trim().split(/\s+/).slice(0,t).join(" "):null}},{key:"extractArticleBody",value:function(e){var t=this.removeYamlAndContext(e);return this.cleanText(t).split("\n").map((function(e){return e.trim()})).filter((function(e){return e&&!e.includes("--- end of article")})).join(" ")}},{key:"extractSections",value:function(e){var t,n=[],r=null,a=[],i=o(this.removeYamlAndContext(e).split("\n"));try{for(i.s();!(t=i.n()).done;){var c=t.value.trim();if(!c.includes("--- end of article")){var l=c.match(/^(#{2,})\s+(.+)$/);if(l){var s=l[2];if(r&&a.length>0){var u=this.cleanText(a.join("\n").trim());u&&n.push({"@type":"WebPageElement",name:this.cleanText(r),text:u,cssSelector:"#".concat(this.cleanText(r).toLowerCase().replace(/\s+/g,"-").replace(/[^\w-]/g,"")),position:n.length+1})}r=s,a=[]}else r&&c&&a.push(c)}}}catch(e){i.e(e)}finally{i.f()}if(r&&a.length>0){var p=this.cleanText(a.join("\n").trim());p&&n.push({"@type":"WebPageElement",name:this.cleanText(r),text:p,cssSelector:"#".concat(this.cleanText(r).toLowerCase().replace(/\s+/g,"-").replace(/[^\w-]/g,"")),position:n.length+1})}return n}},{key:"extractFaqQuestions",value:function(e){var t,n=[],r=!1,a=null,i=[],c=o(this.removeYamlAndContext(e).split("\n"));try{for(c.s();!(t=c.n()).done;){var l=t.value;l.match(/^##\s+(FAQ|Frequently Asked Questions)/i)?r=!0:r&&l.match(/^###\s+/)?(a&&i.length&&n.push({"@type":"Question",name:this.cleanText(a),acceptedAnswer:{"@type":"Answer",text:this.cleanText(i.join(" ").trim())}}),a=l.replace(/^###\s+/,"").trim(),i=[]):r&&a&&l.trim()&&!l.includes("--- end of article")&&i.push(l.trim())}}catch(e){c.e(e)}finally{c.f()}return a&&i.length&&n.push({"@type":"Question",name:this.cleanText(a),acceptedAnswer:{"@type":"Answer",text:this.cleanText(i.join(" ").trim())}}),n}},{key:"removeYamlAndContext",value:function(e){var t=e.replace(/^@context:\s*https?:\/\/[^\n]+\n\n?/m,"");return t=t.replace(/^---\n[\s\S]*?\n---\n/,"")}},{key:"cleanText",value:function(e){var t=e;return t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=t.replace(/\*\*\*([^*]+)\*\*\*/g,"$1")).replace(/\*\*([^*]+)\*\*/g,"$1")).replace(/\*([^*]+)\*/g,"$1")).replace(/___([^_]+)___/g,"$1")).replace(/__([^_]+)__/g,"$1")).replace(/_([^_]+)_/g,"$1")).replace(/`([^`]+)`/g,"$1")).replace(/```[\s\S]*?```/g,(function(e){return e.replace(/```[\w]*\n?/g,"").replace(/```/g,"")}))).replace(/~~([^~]+)~~/g,"$1")).replace(/\[([^\]]+)\]\([^)]+\)(?!@\{)/g,"$1")).replace(/\[([^\]]*?)\](?:\(([^)]+)\))?@\{([^}]+)\}/g,"$1")).replace(/^#+\s*/gm,"")).replace(/^\s*[-*+]\s+/gm,"")).replace(/^\s*\d+\.\s+/gm,"")).replace(/^\s*>\s+/gm,"")).replace(/\|([^|\n]*)\|/g,(function(e,t){return t.split("|").map((function(e){return e.trim()})).join(" ")}))).replace(/\|/g,"")).replace(/^\s*\|[-:\s|]+\|\s*$/gm,"")).replace(/\n{3,}/g,"\n\n")).replace(/[ \t]+/g," ")).trim()}}])}(),d=function(){return i((function e(){r(this,e)}),null,[{key:"transform",value:function(e,t){var n,r=new f,a=r.extractContext(e),i="".concat(t.baseUrl.replace(/\/$/,""),"/").concat(t.slug),o=r.extractAnnotations(e),c=r.extractTitle(e);n=t.description?t.description:r.extractDescription(e,t.descriptionLength);var l=r.extractArticleBody(e),s=r.extractFaqQuestions(e),u=r.extractSections(e),h=r.extractTables(e),m=r.extractLists(e),d=r.extractLinks(e,i),g="HowTo"===t.type||c&&c.toLowerCase().includes("how to")||c&&c.toLowerCase().startsWith("how "),y={"@context":a,"@type":g?"HowTo":t.type,name:c||"Untitled Article",description:n||l.slice(0,t.descriptionLength),datePublished:t.date,author:this.processAuthors(t.author,i),publisher:this.processPublisher(t.publisher),keywords:t.keywords,about:t.categories.map((function(e){return{"@type":"Thing",name:e}}))};if(g)u.length>0&&(y.step=u.map((function(e,t){return{"@type":"HowToStep",name:e.name,text:e.text,position:t+1,url:"".concat(i,"#").concat(e.cssSelector.replace("#",""))}}))),y.totalTime="PT30M";else{y.articleBody=l,y.url=i;var v=[];u.length>0&&v.push.apply(v,p(u)),h.length>0&&v.push.apply(v,p(h)),v.length>0&&(y.hasPart=v)}if(d.length>0){var b=d.filter((function(e){return e.url&&e.url.startsWith("http")}));b.length>0&&(y.mentions=b.map((function(e){return{"@id":e.url}})))}var x=[y];return s.length>0&&x.push({"@context":a,"@type":"FAQPage",name:"FAQ: ".concat(y.name),mainEntity:s,mainEntityOfPage:{"@type":"WebPage","@id":i},datePublished:y.datePublished,author:y.author,publisher:y.publisher}),m.forEach((function(e){e["@context"]=a,x.push(e)})),d.forEach((function(e){e["@context"]=a,e.url&&e.url.startsWith("http")&&x.push(e)})),o.forEach((function(e,t){e["@context"]=a,e["@id"]&&!e["@id"].startsWith("http")&&delete e["@id"],x.push(e)})),x}},{key:"processAuthors",value:function(e,t){return e.map((function(e){return{"@type":"Person",name:e}}))}},{key:"processPublisher",value:function(e){return s({"@type":"Organization"},e)}}])}();e.EnhancedMarkdownParser=f,e.JsonLDTransformer=d}));