@manototh/do11y 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/do11y.js +1099 -0
- package/dist/do11y.min.js +1 -0
- package/examples/do11y-config.example.js +40 -0
- package/examples/sync-do11y-to-docs.yml +100 -0
- package/package.json +34 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){let e=`0.0.1`,t=!!window.__do11yInitialized;window.__do11yInitialized=!0;let n={destination:`supabase`,supabaseUrl:``,supabaseKey:``,supabaseTable:`do11y_events`,httpEndpoint:``,httpHeaders:{},debug:!1,flushInterval:5e3,maxBatchSize:10,trackOutboundLinks:!0,trackInternalLinks:!0,trackScrollDepth:!0,scrollThresholds:[25,50,75,90],allowedDomains:null,respectDNT:!0,maxRetries:2,retryDelay:1e3,rateLimitMs:100,framework:`mintlify`,trackSectionVisibility:!0,sectionVisibleThreshold:3,trackTabSwitches:!0,trackTocClicks:!0,trackExpandCollapse:!0,trackFeedback:!0,tabContainerSelector:null,tocSelector:null,feedbackSelector:null,searchSelector:null,copyButtonSelector:null,codeBlockSelector:null,navigationSelector:null,footerSelector:null,contentSelector:null},r={mintlify:{searchSelector:`#search-bar-entry, #search-bar-entry-mobile, [class*="search"]`,copyButtonSelector:`[class*="copy"], button[aria-label*="copy" i]`,codeBlockSelector:`pre, [class*="code"]`,navigationSelector:`nav, [role="navigation"], #navbar, #sidebar, [class*="nav"], [class*="sidebar"]`,footerSelector:`footer, [role="contentinfo"], [class*="footer"]`,contentSelector:`main, article, [role="main"], [class*="content"]`,tabContainerSelector:`[role="tablist"], [class*="tab"]`,tocSelector:`#table-of-contents, [data-testid="table-of-contents"], [class*="table-of-contents"], [class*="toc"]`,feedbackSelector:`[class*="feedback"], [class*="helpful"]`},docusaurus:{searchSelector:`.DocSearch, .DocSearch-Button`,copyButtonSelector:`button.clean-btn[aria-label*="copy" i], button[class*="copyButton"]`,codeBlockSelector:`pre, [class*="code"]`,navigationSelector:`nav, [role="navigation"], .navbar, .sidebar, [class*="nav"], [class*="sidebar"]`,footerSelector:`footer, [role="contentinfo"], [class*="footer"]`,contentSelector:`main, article, [role="main"], [class*="content"]`,tabContainerSelector:`.tabs[role="tablist"], [class*="tabs"]`,tocSelector:`.table-of-contents, [class*="toc"]`,feedbackSelector:`[class*="feedback"], [class*="helpful"]`},nextra:{searchSelector:`.nextra-search input, input[placeholder*="search" i], button[aria-label*="search" i]`,copyButtonSelector:`button[class*="copy"], button[aria-label*="copy" i], button[title*="copy" i]`,codeBlockSelector:`pre, [class*="code"]`,navigationSelector:`nav, [role="navigation"], [class*="nav"], [class*="sidebar"]`,footerSelector:`footer, [role="contentinfo"], [class*="footer"]`,contentSelector:`main, article, [role="main"], [class*="content"]`,tabContainerSelector:`[role="tablist"], [class*="tab"]`,tocSelector:`.nextra-toc, [class*="toc"]`,feedbackSelector:`[class*="feedback"], [class*="helpful"]`},gitbook:{searchSelector:`[data-testid*="search"], button[aria-label*="search" i]`,copyButtonSelector:`[class*="copy"], button[aria-label*="copy" i]`,codeBlockSelector:`pre, code, [class*="code"]`,navigationSelector:`nav, [role="navigation"], [class*="nav"], [class*="sidebar"]`,footerSelector:`footer, [role="contentinfo"], [class*="footer"]`,contentSelector:`main, article, [role="main"], [class*="content"]`,tabContainerSelector:`[role="tablist"], [class*="tab"]`,tocSelector:`[class*="table-of-contents"], [class*="toc"], [class*="page-outline"]`,feedbackSelector:`[class*="feedback"], [class*="helpful"], [class*="rating"]`},"mkdocs-material":{searchSelector:`.md-search__input`,copyButtonSelector:`.md-clipboard, .md-code__button[title="Copy to clipboard"]`,codeBlockSelector:`pre, code, [class*="code"]`,navigationSelector:`nav, [role="navigation"], .md-nav, .md-sidebar`,footerSelector:`footer, [role="contentinfo"], .md-footer`,contentSelector:`main, article, [role="main"], .md-content`,tabContainerSelector:`.tabbed-labels, .md-typeset .tabbed-set`,tocSelector:`.md-sidebar--secondary .md-nav, [class*="toc"]`,feedbackSelector:`[class*="feedback"], [class*="helpful"]`},vitepress:{searchSelector:`.VPNavBarSearch button, .VPNavBarSearchButton, #local-search`,copyButtonSelector:`.vp-code-copy, button.copy[title*="Copy"]`,codeBlockSelector:`pre, [class*="code"]`,navigationSelector:`nav, [role="navigation"], .VPNav, .VPSidebar, [class*="nav"], [class*="sidebar"]`,footerSelector:`footer, [role="contentinfo"], .VPFooter, [class*="footer"]`,contentSelector:`main, article, [role="main"], .VPContent, [class*="content"]`,tabContainerSelector:`.vp-code-group .tabs, [role="tablist"]`,tocSelector:`.VPDocAsideOutline, [class*="toc"]`,feedbackSelector:`[class*="feedback"], [class*="helpful"]`}},i=[`searchSelector`,`copyButtonSelector`,`codeBlockSelector`,`navigationSelector`,`footerSelector`,`contentSelector`,`tabContainerSelector`,`tocSelector`,`feedbackSelector`];function a(){let e=r[n.framework];e?i.forEach(t=>{n[t]||(n[t]=e[t])}):n.framework!==`custom`&&n.debug&&console.warn(`[Do11y] Unknown framework "${n.framework}". Falling back to generic selectors. Supported: `+Object.keys(r).join(`, `)+`, custom`);let t=r.mintlify;t&&i.forEach(e=>{n[e]||(n[e]=t[e])})}function o(){if(n.respectDNT&&(navigator.doNotTrack===`1`||navigator.doNotTrack===`yes`||window.doNotTrack===`1`))return n.debug&&console.log(`[Do11y] Disabled: Do Not Track is enabled`),!0;if(n.allowedDomains&&n.allowedDomains.length>0){let e=window.location.hostname;if(!n.allowedDomains.some(t=>e===t||e.endsWith(`.`+t)))return n.debug&&console.log(`[Do11y] Disabled: Domain not allowed:`,e),!0}return!1}function s(e){if(!e||typeof e!=`string`)return null;try{return document.querySelector(e),e}catch{return n.debug&&console.warn(`[Do11y] Invalid CSS selector rejected:`,e),null}}function c(e,t){if(!e||typeof e!=`string`)return null;let n=t??100,r=e;return r=r.replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,`[email]`),r=r.replace(/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g,`[phone]`),r=r.replace(/\b\d{3}-\d{2}-\d{4}\b/g,`[redacted]`),r=r.replace(/\b(?:\d[ -]?){13,19}\b/g,`[card]`),r=r.replace(/eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,`[token]`),r=r.replace(/\bxa[a-z]{2}-[A-Za-z0-9_-]{20,}/g,`[token]`),r=r.replace(/\b[0-9a-fA-F]{32,}\b/g,`[redacted]`),r.trim().substring(0,n)}function l(){if(window.crypto&&typeof window.crypto.randomUUID==`function`)return window.crypto.randomUUID();if(window.crypto&&typeof window.crypto.getRandomValues==`function`){let e=new Uint8Array(16);window.crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``);return t.slice(0,8)+`-`+t.slice(8,12)+`-`+t.slice(12,16)+`-`+t.slice(16,20)+`-`+t.slice(20)}return`no-crypto-00-0000-0000-000000000000`}function u(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.id==`string`&&t.id.length>0&&typeof t.startTime==`string`&&Array.isArray(t.pageSequence)&&typeof t.pageCount==`number`}function d(){let e=null;try{let t=sessionStorage.getItem(`do11y_session`);if(t){let n=JSON.parse(t);u(n)&&(e=n)}}catch{}return e||(e={id:l(),startTime:new Date().toISOString(),pageSequence:[],pageCount:0,referrerCategory:null,aiPlatform:null},f(e)),e}function f(e){try{sessionStorage.setItem(`do11y_session`,JSON.stringify(e))}catch{}}function p(e){let t=d();return t.pageCount++,t.pageSequence.push({path:e,timestamp:new Date().toISOString(),index:t.pageCount}),t.pageSequence.length>50&&(t.pageSequence=t.pageSequence.slice(-50)),f(t),t}function m(){return{viewportCategory:h(),browserFamily:g(),deviceType:_(),language:(navigator.language||``).split(`-`)[0]||`unknown`,timezoneOffset:new Date().getTimezoneOffset()/60}}function h(){let e=window.innerWidth;return e<640?`mobile`:e<1024?`tablet`:e<1440?`desktop`:`large-desktop`}function g(){let e=navigator.userAgent;return e.includes(`Firefox`)?`Firefox`:e.includes(`Edg`)?`Edge`:e.includes(`Chrome`)?`Chrome`:e.includes(`Safari`)?`Safari`:`Other`}function _(){let e=navigator.userAgent;return/Mobile|Android|iPhone|iPad/.test(e)?/iPad|Tablet/.test(e)?`tablet`:`mobile`:`desktop`}let v=[{match:`chatgpt`,platform:`ChatGPT`},{match:`chat.com`,platform:`ChatGPT`},{match:`openai`,platform:`ChatGPT`},{match:`perplexity`,platform:`Perplexity`},{match:`claude.ai`,platform:`Claude`},{match:`anthropic`,platform:`Claude`},{match:`gemini`,platform:`Gemini`},{match:`copilot`,platform:`Copilot`},{match:`deepseek`,platform:`DeepSeek`},{match:`meta.ai`,platform:`Meta AI`},{match:`grok`,platform:`Grok`},{match:`x.ai`,platform:`Grok`},{match:`mistral`,platform:`Mistral`},{match:`you.com`,platform:`You.com`},{match:`phind`,platform:`Phind`}];function ee(e){if(!e||e===`direct`)return{referrerCategory:`direct`,aiPlatform:null};if(e===`internal`)return{referrerCategory:`internal`,aiPlatform:null};if(e===`unknown`)return{referrerCategory:`unknown`,aiPlatform:null};let t=e.toLowerCase();for(let e of v)if(t.indexOf(e.match)!==-1)return{referrerCategory:`ai`,aiPlatform:e.platform};return/google\.|bing\.|baidu\.|yandex\.|duckduckgo\.|yahoo\./.test(t)?{referrerCategory:`search-engine`,aiPlatform:null}:/github\.|gitlab\.|bitbucket\./.test(t)?{referrerCategory:`code-host`,aiPlatform:null}:/stackoverflow\.|stackexchange\.|reddit\.|news\.ycombinator\./.test(t)?{referrerCategory:`community`,aiPlatform:null}:/twitter\.|x\.com|linkedin\.|facebook\.|threads\.net/.test(t)?{referrerCategory:`social`,aiPlatform:null}:{referrerCategory:`other`,aiPlatform:null}}function te(){try{if(!document.referrer)return`direct`;let e=new URL(document.referrer);return e.hostname===window.location.hostname?`internal`:e.hostname}catch{return`unknown`}}function ne(){return{path:window.location.pathname,hash:window.location.hash||null,search:window.location.search?`has_params`:null,title:c(document.title,150)}}let y=[],b=null,x={},S=!1;function C(t,r){if(S)return;let i=Date.now();if(n.rateLimitMs>0&&x[t]&&i-x[t]<n.rateLimitMs){n.debug&&console.log(`[Do11y] Rate limited:`,t);return}x[t]=i;let a=d(),o={_time:new Date().toISOString(),eventType:t,do11y_version:e,sessionId:a.id,sessionPageCount:a.pageCount,...ne(),...m(),...r};n.debug&&console.log(`[Do11y] Event queued:`,o),y.push(o),y.length>100&&(y=y.slice(-100),n.debug&&console.warn(`[Do11y] Event queue capped at 100 events`)),y.length>=n.maxBatchSize?k():w()}function w(){b||=setTimeout(k,n.flushInterval)}function T(e){try{let t=new URL(e);return!(t.protocol!==`https:`||!t.hostname.endsWith(`.supabase.co`))}catch{return!1}}function E(e){try{let t=new URL(e);if(t.protocol!==`https:`)return!1;let n=t.hostname;return!(n===`localhost`||n===`127.0.0.1`||n===`::1`||/^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.)/.test(n))}catch{return!1}}function D(){return n.destination===`supabase`?n.supabaseUrl?T(n.supabaseUrl)?!n.supabaseKey||typeof n.supabaseKey!=`string`||n.supabaseKey.length<10?(n.debug&&console.warn(`[Do11y] Invalid or missing Supabase publishable key`),!1):/^[a-zA-Z0-9_-]+$/.test(n.supabaseTable)?!0:(n.debug&&console.warn(`[Do11y] Invalid table name`),!1):(n.debug&&console.warn(`[Do11y] Invalid Supabase URL. Must be https://<project>.supabase.co`),!1):(n.debug&&console.warn(`[Do11y] No Supabase URL configured`),!1):n.destination===`http`?n.httpEndpoint?E(n.httpEndpoint)?!0:(n.debug&&console.warn(`[Do11y] Invalid HTTP endpoint. Must be HTTPS and not a private address.`),!1):(n.debug&&console.warn(`[Do11y] No HTTP endpoint configured`),!1):(n.debug&&console.warn(`[Do11y] Unknown destination:`,n.destination),!1)}function O(e){return n.destination===`supabase`?{url:n.supabaseUrl.replace(/\/$/,``)+`/rest/v1/`+n.supabaseTable,headers:{apikey:n.supabaseKey,Authorization:`Bearer `+n.supabaseKey,"Content-Type":`application/json`,Prefer:`return=minimal`},body:JSON.stringify(e.map(e=>({payload:e})))}:{url:n.httpEndpoint,headers:{"Content-Type":`application/json`,...n.httpHeaders},body:JSON.stringify(e)}}function k(e){if(b&&=(clearTimeout(b),null),y.length===0||!D())return;let t=typeof e==`number`?e:n.maxRetries,r=y.slice();y=[],re(O(r),r,t)}function re(e,t,r){fetch(e.url,{method:`POST`,headers:e.headers,body:e.body,keepalive:!0}).then(e=>{if(e.ok){n.debug&&console.log(`[Do11y] Flushed`,t.length,`events`);return}if(r>0&&(e.status>=500||e.status===429)){n.debug&&console.log(`[Do11y] Retrying after error:`,e.status),y=t.concat(y),setTimeout(()=>{k(r-1)},n.retryDelay*(n.maxRetries-r+1));return}n.debug&&e.text().then(t=>{console.error(`[Do11y] Ingest failed:`,e.status,t)}).catch(()=>{})}).catch(e=>{r>0?(n.debug&&console.log(`[Do11y] Network error, retrying:`,e.message),y=t.concat(y),setTimeout(()=>{k(r-1)},n.retryDelay*(n.maxRetries-r+1))):n.debug&&console.error(`[Do11y] Failed to send events:`,e)})}function ie(){if(y.length===0||!D())return;let e=y;y=[];let t=O(e);try{fetch(t.url,{method:`POST`,headers:t.headers,body:t.body,keepalive:!0})}catch{}n.debug&&console.log(`[Do11y] Sync flushed`,e.length,`events`)}function A(){let e=p(window.location.pathname),t=te(),n=ee(t);e.pageCount===1&&(e.referrerCategory=n.referrerCategory,e.aiPlatform=n.aiPlatform,f(e)),C(`page_view`,{referrerDomain:t,referrerCategory:n.referrerCategory,aiPlatform:n.aiPlatform,isFirstPage:e.pageCount===1,previousPath:e.pageSequence.length>1?e.pageSequence[e.pageSequence.length-2].path:null})}function ae(){document.addEventListener(`click`,e=>{let t=e.target.closest(`a`);if(!t)return;let r=t.getAttribute(`href`);if(!r)return;let i=`other`,a=null;try{if(r.startsWith(`#`))i=`anchor`;else if(r.startsWith(`/`)||r.startsWith(`./`)||r.startsWith(`../`))i=`internal`;else if(r.startsWith(`http`)){let e=new URL(r);e.hostname===window.location.hostname?i=`internal`:(i=`external`,a=e.hostname)}else r.startsWith(`mailto:`)&&(i=`email`)}catch{}i===`internal`&&!n.trackInternalLinks||i===`external`&&!n.trackOutboundLinks||(C(`link_click`,{linkType:i,targetUrl:r,targetDomain:a,linkText:c(t.textContent,100),linkContext:oe(t),linkSection:c(j(t),100),linkIndex:M(t,r)}),k())},!0)}function oe(e){return e.closest(n.navigationSelector)?`navigation`:e.closest(n.footerSelector)?`footer`:e.closest(n.contentSelector)?`content`:`other`}function j(e){let t=e;for(;t&&t!==document.body;){let e=t.previousElementSibling;for(;e;){if(/^H[1-6]$/.test(e.tagName))return e.textContent?.trim().substring(0,100)??null;let t=e.querySelectorAll(`h1, h2, h3, h4, h5, h6`);if(t.length>0)return t[t.length-1].textContent?.trim().substring(0,100)??null;e=e.previousElementSibling}t=t.parentElement}return null}function M(e,t){if(typeof CSS>`u`||typeof CSS.escape!=`function`)return 1;try{let n=document.querySelectorAll(`a[href="`+CSS.escape(t)+`"]`);for(let t=0;t<n.length;t++)if(n[t]===e)return t+1}catch{}return 1}let N=new Set,P=null;function F(e){let t=e;for(;t&&t!==document.body&&t!==document.documentElement;){let e=window.getComputedStyle(t).overflowY;if((e===`auto`||e===`scroll`)&&t.scrollHeight>t.clientHeight)return t;t=t.parentElement}return null}function I(){if(!n.trackScrollDepth)return;if(n.contentSelector){let e=document.querySelector(n.contentSelector);e&&(P=F(e))}let e=!1;function t(){e||=(window.requestAnimationFrame(()=>{L(),e=!1}),!0)}if(window.addEventListener(`scroll`,t),P&&(P.addEventListener(`scroll`,t),n.debug)){let e=P;console.log(`[do11y] Using container-based scroll tracking:`,e.className||e.tagName)}L()}function L(){let e,t,r;P&&P.scrollHeight>P.clientHeight?(e=P.scrollTop,t=P.scrollHeight,r=P.clientHeight):(e=window.scrollY||document.documentElement.scrollTop,t=document.documentElement.scrollHeight,r=window.innerHeight);let i=t-r;if(i<=0){n.scrollThresholds.forEach(e=>{N.has(e)||(N.add(e),C(`scroll_depth`,{threshold:e,scrollPercent:100}))});return}let a=Math.round(e/i*100);n.scrollThresholds.forEach(e=>{a>=e&&!N.has(e)&&(N.add(e),C(`scroll_depth`,{threshold:e,scrollPercent:a}))})}let R=Date.now(),z=Date.now(),B=0,V=!0;function H(){V&&(B+=Date.now()-z);let e=Date.now()-R,t=e>0?B/e:0,n=0;N.forEach(e=>{e>n&&(n=e)}),X();let r=d();C(`page_exit`,{totalTimeSeconds:Math.round(e/1e3),activeTimeSeconds:Math.round(B/1e3),engagementRatio:Math.round(t*100)/100,maxScrollDepth:n,referrerCategory:r.referrerCategory,aiPlatform:r.aiPlatform})}function U(){document.addEventListener(`visibilitychange`,()=>{document.hidden?V&&=(B+=Date.now()-z,!1):(z=Date.now(),V=!0)}),window.addEventListener(`beforeunload`,()=>{H(),de()})}function W(){document.addEventListener(`click`,e=>{e.target.closest(n.searchSelector)&&C(`search_opened`,{})}),document.addEventListener(`keydown`,e=>{(e.metaKey||e.ctrlKey)&&e.key===`k`&&C(`search_opened`,{trigger:`keyboard`})})}function G(e){if(!e)return 1;try{let t=document.querySelectorAll(n.codeBlockSelector);for(let n=0;n<t.length;n++)if(t[n]===e)return n+1}catch{}return 1}function K(){document.addEventListener(`click`,e=>{let t=e.target.closest(n.copyButtonSelector);if(t){let e=t.closest(n.codeBlockSelector)??t.closest(`div, section`)?.querySelector(`pre`)??t.parentElement?.querySelector(`pre`)??null,r=e?e.tagName===`PRE`?e.querySelector(`code`):e.querySelector(`code[class*="language-"]`)??e.querySelector(`code`):null;C(`code_copied`,{language:e?.getAttribute(`language`)??e?.getAttribute(`data-language`)??e?.getAttribute(`data-lang`)??e?.className.match(/language-(\w+)/)?.[1]??r?.getAttribute(`language`)??r?.getAttribute(`data-language`)??r?.getAttribute(`data-lang`)??r?.className.match(/language-(\w+)/)?.[1]??`unknown`,codeSection:c(j(e??t),100),codeBlockIndex:G(e)})}},!0)}let q=null,J={};function se(){if(!n.trackSectionVisibility||typeof IntersectionObserver>`u`)return;let e=n.sectionVisibleThreshold*1e3;q=new IntersectionObserver(t=>{t.forEach(t=>{let n=t.target.getAttribute(`data-do11y-section-id`);if(n)if(t.isIntersecting)J[n]||(J[n]={start:Date.now(),reported:!1});else{if(J[n]&&!J[n].reported){let r=Date.now()-J[n].start;r>=e&&(C(`section_visible`,{heading:c(t.target.textContent?.trim()??``,100),headingLevel:parseInt(t.target.tagName.charAt(1),10),visibleSeconds:Math.round(r/1e3)}),J[n].reported=!0)}delete J[n]}})},{threshold:.5}),Y()}function Y(){q&&document.querySelectorAll(`h2, h3`).forEach((e,t)=>{e.setAttribute(`data-do11y-section-id`,`section-`+t),q.observe(e)})}function X(){if(!q)return;let e=Date.now(),t=n.sectionVisibleThreshold*1e3;Object.keys(J).forEach(n=>{let r=J[n];if(r&&!r.reported){let i=e-r.start;if(i>=t){let e=typeof CSS<`u`&&typeof CSS.escape==`function`?CSS.escape(n):n.replace(/["\\]/g,`\\$&`),t=document.querySelector(`[data-do11y-section-id="`+e+`"]`);t&&C(`section_visible`,{heading:c(t.textContent?.trim()??``,100),headingLevel:parseInt(t.tagName.charAt(1),10),visibleSeconds:Math.round(i/1e3)})}}}),J={}}function ce(){n.trackTabSwitches&&document.addEventListener(`click`,e=>{let t=`[role="tab"], .tabs button, .tabs a, .tabbed-labels label`,r=s(n.tabContainerSelector);r&&(t+=`, `+r+` button, `+r+` a, `+r+` label`);let i=e.target.closest(t);if(!i||i.getAttribute(`aria-selected`)===`true`||i.classList.contains(`active`)||i.classList.contains(`is-active`))return;let a=c(i.textContent,50);a&&C(`tab_switch`,{tabLabel:a,tabGroup:c(j(i),100),isDefault:!1})})}function Z(){n.trackTocClicks&&document.addEventListener(`click`,e=>{let t=e.target.closest(`a`);if(!t)return;let r=t.closest(s(n.tocSelector)??`.table-of-contents, [class*="toc"], [class*="outline"], [class*="TableOfContents"], [class*="page-outline"]`);if(!r)return;let i=t.getAttribute(`href`);if(!i||!i.startsWith(`#`))return;let a=c(t.textContent,100),o=null;try{let e=i.slice(1),t=document.getElementById(e);t&&/^H[1-6]$/.test(t.tagName)&&(o=parseInt(t.tagName.charAt(1),10))}catch{}let l=r.querySelectorAll(`a[href^="#"]`),u=1;for(let e=0;e<l.length;e++)if(l[e]===t){u=e+1;break}C(`toc_click`,{heading:a,headingLevel:o,tocPosition:u})},!0)}function le(){n.trackFeedback&&document.addEventListener(`click`,e=>{let t=e.target.closest(`button, [role="button"], a`);if(!t||!t.closest(s(n.feedbackSelector)??`[class*="feedback"], [class*="helpful"], [class*="rating"], [class*="was-this"], [data-feedback]`))return;let r=(t.textContent??``).trim().toLowerCase(),i=(t.getAttribute(`aria-label`)??``).toLowerCase(),a=(t.getAttribute(`title`)??``).toLowerCase(),o=t.getAttribute(`data-value`)??t.getAttribute(`data-md-value`)??t.getAttribute(`data-feedback`),c=o&&/^[\w\s.,!?-]{1,50}$/.test(o)?o:null,l=null;c?l=c:/\byes\b|👍|thumbs.?up|helpful/i.test(r+` `+i+` `+a)?l=`yes`:/\bno\b|👎|thumbs.?down|not.?helpful/i.test(r+` `+i+` `+a)&&(l=`no`),l&&C(`feedback`,{rating:l})})}function ue(){n.trackExpandCollapse&&(document.addEventListener(`toggle`,e=>{let t=e.target;if(t.tagName!==`DETAILS`)return;let n=t.querySelector(`summary`);C(`expand_collapse`,{summary:c(n?n.textContent:``,100),action:t.open?`expand`:`collapse`,section:c(j(t),100)})},!0),document.addEventListener(`click`,e=>{let t=e.target.closest(`[aria-expanded], [class*="accordion"] button, [class*="collapsible"] button`);if(!t||t.closest(`details`)||t.closest(`nav, [role="navigation"], header`))return;let n=t.getAttribute(`aria-expanded`)===`true`;C(`expand_collapse`,{summary:c(t.textContent,100),action:n?`collapse`:`expand`,section:c(j(t),100)})}))}let Q=null;function $(){if(window.Do11yConfig&&typeof window.Do11yConfig==`object`)for(let e in window.Do11yConfig)Object.prototype.hasOwnProperty.call(window.Do11yConfig,e)&&Object.prototype.hasOwnProperty.call(n,e)&&(n[e]=window.Do11yConfig[e]);let e=document.querySelector(`meta[name="do11y-destination"]`);if(e){let t=e.getAttribute(`content`);(t===`supabase`||t===`http`)&&(n.destination=t)}let t=document.querySelector(`meta[name="do11y-url"]`);t&&(n.supabaseUrl=t.getAttribute(`content`)??n.supabaseUrl);let r=document.querySelector(`meta[name="do11y-key"]`);r&&(n.supabaseKey=r.getAttribute(`content`)??n.supabaseKey);let i=document.querySelector(`meta[name="do11y-table"]`);i&&(n.supabaseTable=i.getAttribute(`content`)??n.supabaseTable);let s=document.querySelector(`meta[name="do11y-http-endpoint"]`);s&&(n.httpEndpoint=s.getAttribute(`content`)??n.httpEndpoint);let c=document.querySelector(`meta[name="do11y-debug"]`);c&&c.getAttribute(`content`)===`true`&&(n.debug=!0);let l=document.querySelector(`meta[name="do11y-domains"]`);if(l){let e=l.getAttribute(`content`);e&&(n.allowedDomains=e.split(`,`).map(e=>e.trim()))}let u=document.querySelector(`meta[name="do11y-framework"]`);if(u&&(n.framework=u.getAttribute(`content`)??n.framework),a(),n.debug&&console.log(`[Do11y] Initializing with config:`,{destination:n.destination,hasCredentials:n.destination===`supabase`?!!n.supabaseKey:!!n.httpEndpoint,framework:n.framework,allowedDomains:n.allowedDomains,respectDNT:n.respectDNT}),o()){S=!0,n.debug&&console.log(`[Do11y] Tracking disabled`);return}(n.destination===`supabase`?n.supabaseKey:n.httpEndpoint)||n.debug&&(console.warn(`[Do11y] No destination configured. Events will not be sent.`),console.warn(`[Do11y] Add <meta name="do11y-url"> and <meta name="do11y-key"> to enable.`)),A(),ae(),I(),U(),W(),K(),se(),ce(),Z(),le(),ue();let d=window.location.pathname;Q=new MutationObserver(()=>{window.location.pathname!==d&&(d=window.location.pathname,H(),N=new Set,R=Date.now(),z=Date.now(),B=0,V=!0,A(),Y(),L())}),Q.observe(document.body,{childList:!0,subtree:!0}),window.addEventListener(`popstate`,()=>{window.location.pathname!==d&&(d=window.location.pathname,H(),N=new Set,R=Date.now(),z=Date.now(),B=0,V=!0,A(),Y(),L())}),Object.freeze(n),n.debug&&console.log(`[Do11y] Initialized successfully`)}function de(){Q&&=(Q.disconnect(),null),q&&=(X(),q.disconnect(),null),b&&=(clearTimeout(b),null),ie()}t||(document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,$):$()),window.Do11y=window.Do11y??{getConfig:()=>({destination:n.destination,hasCredentials:n.destination===`supabase`?!!n.supabaseKey:!!n.httpEndpoint,isDisabled:S,allowedDomains:n.allowedDomains,respectDNT:n.respectDNT}),flush:k,isEnabled:()=>!S&&(n.destination===`supabase`?!!n.supabaseKey:!!n.httpEndpoint),getQueueSize:()=>y.length,version:e}})();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Do11y configuration example.
|
|
3
|
+
*
|
|
4
|
+
* Copy this file alongside do11y.js in your docs site and rename it to
|
|
5
|
+
* do11y-config.js. Set the values below to match your Supabase setup.
|
|
6
|
+
*
|
|
7
|
+
* This file must load before do11y.js. For frameworks that auto-include
|
|
8
|
+
* all .js files (like Mintlify), alphabetical ordering handles this
|
|
9
|
+
* automatically.
|
|
10
|
+
*
|
|
11
|
+
* Any option from the config object in do11y.js can be set here.
|
|
12
|
+
* See the README for the full list.
|
|
13
|
+
*/
|
|
14
|
+
window.Do11yConfig = {
|
|
15
|
+
// Destination: 'supabase' (default) or 'http'
|
|
16
|
+
destination: 'supabase',
|
|
17
|
+
|
|
18
|
+
// Required: Supabase project URL.
|
|
19
|
+
supabaseUrl: 'https://YOUR_PROJECT.supabase.co',
|
|
20
|
+
|
|
21
|
+
// Required: Supabase publishable key (starts with sb_publishable_).
|
|
22
|
+
supabaseKey: 'sb_publishable_YOUR_KEY',
|
|
23
|
+
|
|
24
|
+
// Optional: Table name (default: 'do11y_events').
|
|
25
|
+
supabaseTable: 'do11y_events',
|
|
26
|
+
|
|
27
|
+
// Documentation framework. Supported values:
|
|
28
|
+
// 'mintlify', 'docusaurus', 'nextra', 'gitbook', 'mkdocs-material',
|
|
29
|
+
// 'vitepress', 'custom'
|
|
30
|
+
framework: 'mintlify',
|
|
31
|
+
|
|
32
|
+
// Optional: restrict which domains may send data.
|
|
33
|
+
// Set to null to allow any domain.
|
|
34
|
+
// allowedDomains: ['docs.example.com'],
|
|
35
|
+
|
|
36
|
+
// --- Alternative: Generic HTTP destination ---
|
|
37
|
+
// destination: 'http',
|
|
38
|
+
// httpEndpoint: 'https://your-endpoint.com/events',
|
|
39
|
+
// httpHeaders: { 'Authorization': 'Bearer your-token' },
|
|
40
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
name: Update Do11y
|
|
2
|
+
|
|
3
|
+
# Periodically checks for new do11y releases and opens a PR when one is found.
|
|
4
|
+
# Copy this file to .github/workflows/ in your docs repo.
|
|
5
|
+
#
|
|
6
|
+
# Required setup (Settings > Secrets and variables > Actions):
|
|
7
|
+
#
|
|
8
|
+
# Variables:
|
|
9
|
+
# DO11Y_JS_PATH - Path to do11y.js in your docs repo (e.g. scripts/do11y.min.js).
|
|
10
|
+
# DO11Y_VER_PATH - Path to the version tracking file in your docs repo (e.g. scripts/do11y.version).
|
|
11
|
+
# Create this file with the current version tag (e.g. v0.1.0) to
|
|
12
|
+
# avoid triggering a PR on the first run.
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
schedule:
|
|
16
|
+
- cron: '0 9 * * 1' # Every Monday at 09:00 UTC
|
|
17
|
+
workflow_dispatch:
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
update:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
permissions:
|
|
23
|
+
contents: write
|
|
24
|
+
pull-requests: write
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout docs
|
|
27
|
+
uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Get latest do11y release
|
|
30
|
+
id: latest
|
|
31
|
+
run: |
|
|
32
|
+
VERSION=$(curl -sf https://api.github.com/repos/manototh/do11y/releases/latest | jq -r '.tag_name')
|
|
33
|
+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
34
|
+
|
|
35
|
+
- name: Get current do11y version
|
|
36
|
+
id: current
|
|
37
|
+
run: |
|
|
38
|
+
VERSION=$(cat "${{ vars.DO11Y_VER_PATH }}" 2>/dev/null | tr -d '[:space:]' || echo "none")
|
|
39
|
+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
40
|
+
|
|
41
|
+
- name: Check for update
|
|
42
|
+
id: check
|
|
43
|
+
run: |
|
|
44
|
+
LATEST="${{ steps.latest.outputs.version }}"
|
|
45
|
+
CURRENT="${{ steps.current.outputs.version }}"
|
|
46
|
+
if [ "$LATEST" = "$CURRENT" ]; then
|
|
47
|
+
echo "needed=false" >> "$GITHUB_OUTPUT"
|
|
48
|
+
echo "Already on ${LATEST}, nothing to do."
|
|
49
|
+
else
|
|
50
|
+
echo "needed=true" >> "$GITHUB_OUTPUT"
|
|
51
|
+
echo "Update available: ${CURRENT} → ${LATEST}"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
- name: Checkout do11y at release tag
|
|
55
|
+
if: steps.check.outputs.needed == 'true'
|
|
56
|
+
uses: actions/checkout@v4
|
|
57
|
+
with:
|
|
58
|
+
repository: manototh/do11y
|
|
59
|
+
ref: ${{ steps.latest.outputs.version }}
|
|
60
|
+
path: _do11y
|
|
61
|
+
|
|
62
|
+
- name: Set up Node.js
|
|
63
|
+
if: steps.check.outputs.needed == 'true'
|
|
64
|
+
uses: actions/setup-node@v4
|
|
65
|
+
with:
|
|
66
|
+
node-version: '22'
|
|
67
|
+
|
|
68
|
+
- name: Build do11y
|
|
69
|
+
if: steps.check.outputs.needed == 'true'
|
|
70
|
+
working-directory: _do11y
|
|
71
|
+
run: npm ci && npm run build
|
|
72
|
+
|
|
73
|
+
- name: Update files
|
|
74
|
+
if: steps.check.outputs.needed == 'true'
|
|
75
|
+
run: |
|
|
76
|
+
cp _do11y/dist/do11y.min.js "${{ vars.DO11Y_JS_PATH }}"
|
|
77
|
+
echo "${{ steps.latest.outputs.version }}" > "${{ vars.DO11Y_VER_PATH }}"
|
|
78
|
+
|
|
79
|
+
- name: Create PR
|
|
80
|
+
if: steps.check.outputs.needed == 'true'
|
|
81
|
+
env:
|
|
82
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
83
|
+
run: |
|
|
84
|
+
VERSION="${{ steps.latest.outputs.version }}"
|
|
85
|
+
BRANCH="do11y/${VERSION}"
|
|
86
|
+
|
|
87
|
+
git config user.name "github-actions[bot]"
|
|
88
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
89
|
+
git checkout -b "$BRANCH"
|
|
90
|
+
git add "${{ vars.DO11Y_JS_PATH }}" "${{ vars.DO11Y_VER_PATH }}"
|
|
91
|
+
git commit -m "Update do11y.js to ${VERSION}"
|
|
92
|
+
git push -fu origin "$BRANCH"
|
|
93
|
+
|
|
94
|
+
if gh pr view "$BRANCH" --json state -q '.state' 2>/dev/null | grep -q .; then
|
|
95
|
+
echo "PR already exists for ${BRANCH}, skipping creation."
|
|
96
|
+
else
|
|
97
|
+
gh pr create \
|
|
98
|
+
--title "Update do11y to ${VERSION}" \
|
|
99
|
+
--body "Automated update from [do11y ${VERSION}](https://github.com/manototh/do11y/releases/tag/${VERSION})."
|
|
100
|
+
fi
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@manototh/do11y",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Documentation observability",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/do11y.min.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./dist/do11y.min.js",
|
|
9
|
+
"./min": "./dist/do11y.min.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"examples"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "rolldown -c rolldown.config.ts",
|
|
17
|
+
"lint": "oxlint src",
|
|
18
|
+
"format": "oxfmt src",
|
|
19
|
+
"check": "tsc --noEmit"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"supabase",
|
|
23
|
+
"analytics",
|
|
24
|
+
"documentation",
|
|
25
|
+
"observability"
|
|
26
|
+
],
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"oxfmt": "latest",
|
|
30
|
+
"oxlint": "latest",
|
|
31
|
+
"rolldown": "latest",
|
|
32
|
+
"typescript": "latest"
|
|
33
|
+
}
|
|
34
|
+
}
|