@qe-libs/refi-qda 0.1.0 → 0.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1
4
+
5
+ - `require('@qe-libs/refi-qda')` works from CommonJS (an Electron main
6
+ process, for one): the UMD build is also `dist/refi-qda.umd.cjs`, which
7
+ `main` and the `require` export now point to. `"type": "module"` made
8
+ Node load `refi-qda.umd.js` as an ES module and refuse it. Browsers still
9
+ load `dist/refi-qda.umd.js`.
10
+
3
11
  ## 0.1.0
4
12
 
5
13
  - First release, from QE Studio's importer (`js/importers/refi-qda.js`):
package/README.md CHANGED
@@ -37,6 +37,8 @@ const { csv, report, coders, textColumn } = toCSV(bytes, { coder: 'any' });
37
37
  The browser's own `DOMParser` is used otherwise.
38
38
 
39
39
  In a page without a bundler, `dist/refi-qda.umd.js` defines `window.RefiQda`.
40
+ CommonJS code gets the same build through `require('@qe-libs/refi-qda')`
41
+ (`dist/refi-qda.umd.cjs`).
40
42
 
41
43
  | Function | Returns |
42
44
  |---|---|
@@ -0,0 +1,7 @@
1
+ (function(P,k){typeof exports=="object"&&typeof module<"u"?k(exports):typeof define=="function"&&define.amd?define(["exports"],k):(P=typeof globalThis<"u"?globalThis:P||self,k(P.RefiQda={}))})(this,(function(P){"use strict";var k=Uint8Array,G=Uint16Array,Ee=Int32Array,ue=new k([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),he=new k([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Fe=new k([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),pe=function(e,r){for(var n=new G(31),t=0;t<31;++t)n[t]=r+=1<<e[t-1];for(var o=new Ee(n[30]),t=1;t<30;++t)for(var f=n[t];f<n[t+1];++f)o[f]=f-n[t]<<5|t;return{b:n,r:o}},ve=pe(ue,2),ge=ve.b,Me=ve.r;ge[28]=258,Me[258]=28;for(var Ue=pe(he,0),Oe=Ue.b,ee=new G(32768),d=0;d<32768;++d){var q=(d&43690)>>1|(d&21845)<<1;q=(q&52428)>>2|(q&13107)<<2,q=(q&61680)>>4|(q&3855)<<4,ee[d]=((q&65280)>>8|(q&255)<<8)>>1}for(var K=(function(e,r,n){for(var t=e.length,o=0,f=new G(r);o<t;++o)e[o]&&++f[e[o]-1];var a=new G(r);for(o=1;o<r;++o)a[o]=a[o-1]+f[o-1]<<1;var s;if(n){s=new G(1<<r);var m=15-r;for(o=0;o<t;++o)if(e[o])for(var v=o<<4|e[o],w=r-e[o],i=a[e[o]-1]++<<w,p=i|(1<<w)-1;i<=p;++i)s[ee[i]>>m]=v}else for(s=new G(t),o=0;o<t;++o)e[o]&&(s[o]=ee[a[e[o]-1]++]>>15-e[o]);return s}),X=new k(288),d=0;d<144;++d)X[d]=8;for(var d=144;d<256;++d)X[d]=9;for(var d=256;d<280;++d)X[d]=7;for(var d=280;d<288;++d)X[d]=8;for(var me=new k(32),d=0;d<32;++d)me[d]=5;var Pe=K(X,9,1),Ve=K(me,5,1),re=function(e){for(var r=e[0],n=1;n<e.length;++n)e[n]>r&&(r=e[n]);return r},V=function(e,r,n){var t=r/8|0;return(e[t]|e[t+1]<<8)>>(r&7)&n},ne=function(e,r){var n=r/8|0;return(e[n]|e[n+1]<<8|e[n+2]<<16)>>(r&7)},De=function(e){return(e+7)/8|0},te=function(e,r,n){return(r==null||r<0)&&(r=0),(n==null||n>e.length)&&(n=e.length),new k(e.subarray(r,n))},Ne=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],F=function(e,r,n){var t=new Error(r||Ne[e]);if(t.code=e,Error.captureStackTrace&&Error.captureStackTrace(t,F),!n)throw t;return t},Re=function(e,r,n,t){var o=e.length,f=t?t.length:0;if(!o||r.f&&!r.l)return n||new k(0);var a=!n,s=a||r.i!=2,m=r.i;a&&(n=new k(o*3));var v=function(Se){var $e=n.length;if(Se>$e){var Te=new k(Math.max($e*2,Se));Te.set(n),n=Te}},w=r.f||0,i=r.p||0,p=r.b||0,u=r.l,y=r.d,b=r.m,g=r.n,C=o*8;do{if(!u){w=V(e,i,1);var c=V(e,i+1,3);if(i+=3,c)if(c==1)u=Pe,y=Ve,b=9,g=5;else if(c==2){var j=V(e,i,31)+257,I=V(e,i+10,15)+4,H=j+V(e,i+5,31)+1;i+=14;for(var B=new k(H),L=new k(19),S=0;S<I;++S)L[Fe[S]]=V(e,i+S*3,7);i+=I*3;for(var _=re(L),J=(1<<_)-1,l=K(L,_,1),S=0;S<H;){var A=l[V(e,i,J)];i+=A&15;var h=A>>4;if(h<16)B[S++]=h;else{var E=0,x=0;for(h==16?(x=3+V(e,i,3),i+=2,E=B[S-1]):h==17?(x=3+V(e,i,7),i+=3):h==18&&(x=11+V(e,i,127),i+=7);x--;)B[S++]=E}}var O=B.subarray(0,j),R=B.subarray(j);b=re(O),g=re(R),u=K(O,b,1),y=K(R,g,1)}else F(1);else{var h=De(i)+4,$=e[h-4]|e[h-3]<<8,T=h+$;if(T>o){m&&F(0);break}s&&v(p+$),n.set(e.subarray(h,T),p),r.b=p+=$,r.p=i=T*8,r.f=w;continue}if(i>C){m&&F(0);break}}s&&v(p+131072);for(var Ze=(1<<b)-1,_e=(1<<g)-1,fe=i;;fe=i){var E=u[ne(e,i)&Ze],W=E>>4;if(i+=E&15,i>C){m&&F(0);break}if(E||F(2),W<256)n[p++]=W;else if(W==256){fe=i,u=null;break}else{var Ae=W-254;if(W>264){var S=W-257,Y=ue[S];Ae=V(e,i,(1<<Y)-1)+ge[S],i+=Y}var ce=y[ne(e,i)&_e],le=ce>>4;ce||F(3),i+=ce&15;var R=Oe[le];if(le>3){var Y=he[le];R+=ne(e,i)&(1<<Y)-1,i+=Y}if(i>C){m&&F(0);break}s&&v(p+131072);var Ce=p+Ae;if(p<R){var ke=f-R,er=Math.min(R,Ce);for(ke+p<0&&F(3);p<er;++p)n[p]=t[ke+p]}for(;p<Ce;++p)n[p]=n[p-R]}}r.l=u,r.p=fe,r.b=p,r.f=w,u&&(w=1,r.m=b,r.d=y,r.n=g)}while(!w);return p!=n.length&&a?te(n,0,p):n.subarray(0,p)},je=new k(0),D=function(e,r){return e[r]|e[r+1]<<8},M=function(e,r){return(e[r]|e[r+1]<<8|e[r+2]<<16|e[r+3]<<24)>>>0},oe=function(e,r){return M(e,r)+M(e,r+4)*4294967296};function Be(e,r){return Re(e,{i:2},r&&r.out,r&&r.dictionary)}var ae=typeof TextDecoder<"u"&&new TextDecoder,qe=0;try{ae.decode(je,{stream:!0}),qe=1}catch{}var ze=function(e){for(var r="",n=0;;){var t=e[n++],o=(t>127)+(t>223)+(t>239);if(n+o>e.length)return{s:r,r:te(e,n-1)};o?o==3?(t=((t&15)<<18|(e[n++]&63)<<12|(e[n++]&63)<<6|e[n++]&63)-65536,r+=String.fromCharCode(55296|t>>10,56320|t&1023)):o&1?r+=String.fromCharCode((t&31)<<6|e[n++]&63):r+=String.fromCharCode((t&15)<<12|(e[n++]&63)<<6|e[n++]&63):r+=String.fromCharCode(t)}};function se(e,r){if(r){for(var n="",t=0;t<e.length;t+=16384)n+=String.fromCharCode.apply(null,e.subarray(t,t+16384));return n}else{if(ae)return ae.decode(e);var o=ze(e),f=o.s,n=o.r;return n.length&&F(8),f}}var Qe=function(e,r){return r+30+D(e,r+26)+D(e,r+28)},Ie=function(e,r,n){var t=D(e,r+28),o=D(e,r+30),f=se(e.subarray(r+46,r+46+t),!(D(e,r+8)&2048)),a=r+46+t,s=Le(e,a,o,n,M(e,r+20),M(e,r+24),M(e,r+42)),m=s[0],v=s[1],w=s[2];return[D(e,r+10),m,v,f,a+o+D(e,r+32),w]},Le=function(e,r,n,t,o,f,a){var s=o==4294967295,m=f==4294967295,v=a==4294967295,w=r+n,i=s+m+v;if(t&&i){for(;r+4<w;r+=4+D(e,r+2))if(D(e,r)==1)return[s?oe(e,r+4+8*m):o,m?oe(e,r+4):f,v?oe(e,r+4+8*(m+s)):a,1];t<2&&F(13)}return[o,f,a,0]};function Ge(e,r){for(var n={},t=e.length-22;M(e,t)!=101010256;--t)(!t||e.length-t>65558)&&F(13);var o=D(e,t+8);if(!o)return{};var f=M(e,t+16),a=M(e,t-20)==117853008;if(a){var s=M(e,t-12);a=M(e,s)==101075792,a&&(o=M(e,s+32),f=M(e,s+48))}for(var m=0;m<o;++m){var v=Ie(e,f,a),w=v[0],i=v[1],p=v[2],u=v[3],y=v[4],b=v[5],g=Qe(e,b);f=y,w?w==8?n[u]=Be(e.subarray(g,g+i),{out:new k(p)}):F(14,"unknown compression type "+w):n[u]=te(e,g,g+i)}return n}class z extends Error{constructor(r,n){super(r),this.name="QdaError",this.code=n}}const U=(e,r)=>e?Array.from(e.childNodes).filter(n=>n.nodeType===1&&(!r||n.localName===r)):[],N=(e,r)=>U(e,r)[0],Z=e=>e&&e.textContent||"";function We(e,r){const n=[];let t;try{t=new e({onError:(f,a)=>{f!=="warning"&&n.push(a)}}).parseFromString(r,"text/xml")}catch(f){n.push(f.message)}const o=t&&t.getElementsByTagName("parsererror")[0];return o&&n.push(Z(o).trim().split(`
2
+ `)[0]),{root:n.length?null:t&&t.documentElement,error:n[0]}}function de(e,r){const n=r.toLowerCase(),t=Object.keys(e).find(o=>o.toLowerCase()===n||o.toLowerCase().endsWith("/"+n));return t?e[t]:null}function we(e,{DOMParser:r=globalThis.DOMParser}={}){if(!r)throw new Error("readProject needs a DOMParser: pass { DOMParser } (in Node, from @xmldom/xmldom).");let n;try{n=Ge(e instanceof Uint8Array?e:new Uint8Array(e))}catch{throw new z("This file isn't a .qdpx project (it can't be opened as a zip archive).","not-zip")}const t=de(n,"project.qde");if(!t)throw new z("This .qdpx has no project.qde inside, so it isn't a REFI-QDA project.","no-project");const{root:o,error:f}=We(r,se(t));if(!o||o.localName!=="Project")throw new z(`project.qde couldn't be read as a REFI-QDA project${f?`: ${f}`:""}.`,"bad-xml");const a=new Map(U(N(o,"Users"),"User").map(u=>[u.getAttribute("guid"),u.getAttribute("name")||u.getAttribute("guid")])),s=[];(function u(y,b){for(const g of U(y,"Code")){const C=g.getAttribute("name")||"(unnamed code)";s.push({guid:g.getAttribute("guid"),name:C,parent:b,codable:g.getAttribute("isCodable")!=="false",description:Z(N(g,"Description")).trim()}),u(g,C)}})(N(N(o,"CodeBook"),"Codes"),null);const m=new Map(U(N(o,"Variables"),"Variable").map(u=>[u.getAttribute("guid"),u.getAttribute("name")])),v=u=>{var g;const y=(g=N(u,"VariableRef"))==null?void 0:g.getAttribute("targetGUID"),b=U(u).find(C=>C.localName!=="VariableRef");return[m.get(y)||y,Z(b).trim()]},w=new Map;for(const u of U(N(o,"Cases"),"Case")){const y=U(u,"SourceRef");if(u.getAttribute("name")||y.length!==1)continue;const b=y[0].getAttribute("targetGUID"),g=w.get(b)||{};for(const C of U(u,"VariableValue")){const[c,h]=v(C);g[c]=h}w.set(b,g)}const i=[],p=[];for(const u of U(N(o,"Sources"))){const y=u.getAttribute("name")||u.getAttribute("guid");if(u.localName!=="TextSource"){p.push(`${y} (${u.localName.replace(/Source$/,"").toLowerCase()})`);continue}let b=null;const g=N(u,"PlainTextContent");if(g)b=Z(g);else{const h=u.getAttribute("plainTextPath")||"",$=/^internal:\/\/(.+)$/.exec(h);if(!$){p.push(`${y} (its text is stored outside the project: ${h||"no path"})`);continue}const T=de(n,"Sources/"+$[1]);if(!T){p.push(`${y} (Sources/${$[1]} is missing)`);continue}b=se(T)}b=b.replace(/^/,"");const C={...w.get(u.getAttribute("guid"))||{}};for(const h of U(u,"VariableValue")){const[$,T]=v(h);C[$]=T}const c=U(u,"PlainTextSelection").map(h=>({start:+h.getAttribute("startPosition"),end:+h.getAttribute("endPosition"),name:h.getAttribute("name"),codings:U(h,"Coding").map($=>{var T;return{code:(T=N($,"CodeRef"))==null?void 0:T.getAttribute("targetGUID"),user:$.getAttribute("creatingUser")||h.getAttribute("creatingUser")}})}));i.push({guid:u.getAttribute("guid"),name:y,raw:b,vars:C,selections:c})}return{name:o.getAttribute("name")||"",users:a,codes:s,sources:i,skipped:p}}function Ke(e){const r=Array.from(e),n=[];let t=0;for(let s=0;s<r.length;s++)n.push(t),!(r[s]==="\r"&&r[s+1]===`
3
+ `)&&t++;n.push(t);const o=e.replace(/\r\n?/g,`
4
+ `),f=[];let a=0;for(const s of o)f.push(a),s.length===2&&f.push(a),a++;return f.push(a),{text:o,cps:Array.from(o),ways:{"code points":s=>s,"code points, CRLF as two":s=>n[s],"UTF-16 units":s=>f[s]}}}const ie=e=>String(e||"").replace(/\s+/g," ").trim();function Xe(e,r,n){let t=0;for(const o of r){const f=n(o.start),a=n(o.end);if(f===void 0||a===void 0||f>a)continue;const s=ie(e.slice(f,a).join("")),m=ie(o.name);s&&(s===m||m.length>=20&&s.startsWith(m))&&t++}return t}const He=new RegExp("^\\s*(\\p{L}[^:\\n]{0,39}?)\\s*:\\s+(\\S.*)$","u"),Q="(no coder)";function be(e){const r=new Set(e.codes.filter(a=>a.codable).map(a=>a.guid)),n=new Map;for(const a of e.sources)for(const s of a.selections)new Set(s.codings.filter(v=>r.has(v.code)).map(v=>v.user||Q)).forEach(v=>n.set(v,(n.get(v)||0)+1));const t=[...e.users].filter(([a])=>n.has(a)).map(([a,s])=>({guid:a,name:s,spans:n.get(a)})),o=[...n.keys()].filter(a=>a!==Q&&!e.users.has(a)).map(a=>({guid:a,name:a,spans:n.get(a)})),f=n.has(Q)?[{guid:Q,name:Q,spans:n.get(Q)}]:[];return[...t,...o,...f]}function xe(e,{coder:r="any"}={}){const n={sources:0,rows:0,codes:0,coders:[...new Set(e.users.values())],skippedSources:e.skipped,notes:[]},t=be(e);n.coder=r;let o=null;if(!["any","all","each","columns"].includes(r)&&(o=[...e.users].filter(([c,h])=>h===r||c===r).map(([c])=>c),!o.length&&t.some(c=>c.guid===r)&&(o=[r]),!o.length))throw new z(`There's no coder called “${r}” in this project.`,"no-coder");const f=r==="each",a=r==="columns",s=e.codes.filter(c=>c.codable),m={};s.forEach(c=>{m[c.name]=(m[c.name]||0)+1});const v=s.map(c=>m[c.name]>1&&c.parent?`${c.parent} / ${c.name}`:c.name);n.codes=v.length;const w=[];e.sources.forEach(c=>Object.keys(c.vars).forEach(h=>{w.includes(h)||w.push(h)}));const i=["Source","Line","UserName",...f?["Coder"]:[],...w,"Text"],p=a?v.flatMap(c=>t.map(h=>`${c} [${h.name}]`)):v.map(c=>i.includes(c)?`${c} (code)`:c),u=[...i,...p];n.columns=p.length;const y=new Map(s.map((c,h)=>[c.guid,h]));let b=0,g=0;const C=[];for(const c of e.sources){n.sources++;const{text:h,cps:$,ways:T}=Ke(c.raw),j=c.selections.filter(l=>ie(l.name));let I="code points";if(j.length){let l=-1;for(const[A,E]of Object.entries(T)){const x=Xe($,j,E);x>l&&(l=x,I=A)}if(b+=j.length,g+=l,l<j.length*.9)throw new z(`The coded spans in “${c.name}” don't line up with its text (${l} of ${j.length} match), so the codes can't be placed on lines. The file may have been changed after it was coded.`,"misaligned");I!=="code points"&&n.notes.push(`“${c.name}”: positions counted as ${I}.`)}const H=T[I],B=[];let L=0;for(const l of h.split(`
5
+ `)){const A=Array.from(l).length;B.push({text:l,start:L,end:L+A}),L+=A+1}let S=B.map((l,A)=>{const E=He.exec(l.text);return E&&{...l,i:A,speaker:E[1],said:E[2].trim()}}).filter(Boolean);S.length||(S=B.map((l,A)=>l.text.trim()&&{...l,i:A,speaker:"",said:l.text.trim()}).filter(Boolean),n.notes.push(`“${c.name}” has no “Name: text” lines, so each non-empty line is a row with no speaker.`));const _=c.selections.map(l=>({a:H(l.start),b:H(l.end),codings:l.codings.filter(A=>y.has(A.code)).map(A=>[y.get(A.code),A.user||Q])})).filter(l=>l.codings.length&&l.a!==void 0&&l.b!==void 0),J=w.map(l=>c.vars[l]??"");for(const l of S){const A=v.map(()=>new Set);for(const x of _)x.a<l.end&&x.b>l.start&&x.codings.forEach(([O,R])=>A[O].add(R));if(a){C.push([c.name,l.i+1,l.speaker,...J,l.said,...A.flatMap(x=>t.map(O=>+x.has(O.guid)))]);continue}if(f){for(const x of t)C.push([c.name,l.i+1,l.speaker,x.name,...J,l.said,...A.map(O=>+O.has(x.guid))]);continue}const E=r==="any"?x=>x.size>0:r==="all"?x=>t.length>0&&t.every(O=>x.has(O.guid)):x=>o.some(O=>x.has(O));C.push([c.name,l.i+1,l.speaker,...J,l.said,...A.map(x=>+E(x))])}}if(n.rows=C.length,n.positions=b?`${g} of ${b} coded spans checked against their text`:"no span text to check positions against",!n.sources)throw new z(`This project has no text sources to import${e.skipped.length?` (skipped: ${e.skipped.join("; ")})`:""}.`,"no-sources");return{fields:u,rows:C,report:n}}const Je=e=>{const r=e==null?"":String(e);return/[",\r\n]/.test(r)||r[0]===" "||r[r.length-1]===" "?`"${r.replace(/"/g,'""')}"`:r};function ye(e,r){return[e,...r].map(n=>n.map(Je).join(",")).join(`
6
+ `)}function Ye(e,{coder:r="any",DOMParser:n}={}){const{fields:t,rows:o,report:f}=xe(we(e,{DOMParser:n}),{coder:r});return{csv:ye(t,o),fields:t,rows:o,report:f,coders:f.coders,textColumn:"Text"}}P.QdaError=z,P.codersOf=be,P.readProject=we,P.toCSV=Ye,P.toTable=xe,P.writeCSV=ye,Object.defineProperty(P,Symbol.toStringTag,{value:"Module"})}));
7
+ //# sourceMappingURL=refi-qda.umd.js.map
package/package.json CHANGED
@@ -1,23 +1,38 @@
1
1
  {
2
2
  "name": "@qe-libs/refi-qda",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "REFI-QDA projects (.qdpx from NVivo, ATLAS.ti, MAXQDA, QualCoder) as utterance × code tables, in the browser and Node",
5
5
  "type": "module",
6
- "main": "./dist/refi-qda.umd.js",
6
+ "main": "./dist/refi-qda.umd.cjs",
7
7
  "module": "./dist/refi-qda.es.js",
8
8
  "exports": {
9
9
  ".": {
10
10
  "import": "./dist/refi-qda.es.js",
11
- "require": "./dist/refi-qda.umd.js"
12
- }
11
+ "require": "./dist/refi-qda.umd.cjs"
12
+ },
13
+ "./dist/*": "./dist/*"
13
14
  },
14
15
  "scripts": {
15
16
  "build": "vite build",
16
17
  "pretest": "npm run build",
17
- "test": "node --test tests/"
18
+ "test": "node --test tests/*.test.mjs tests/*.test.cjs",
19
+ "postbuild": "node -e \"require('fs').copyFileSync('dist/refi-qda.umd.js','dist/refi-qda.umd.cjs')\""
18
20
  },
19
- "files": ["dist/", "README.md", "CHANGELOG.md"],
20
- "keywords": ["refi-qda", "qdpx", "nvivo", "atlas.ti", "maxqda", "qualcoder", "qualitative", "ena"],
21
+ "files": [
22
+ "dist/",
23
+ "README.md",
24
+ "CHANGELOG.md"
25
+ ],
26
+ "keywords": [
27
+ "refi-qda",
28
+ "qdpx",
29
+ "nvivo",
30
+ "atlas.ti",
31
+ "maxqda",
32
+ "qualcoder",
33
+ "qualitative",
34
+ "ena"
35
+ ],
21
36
  "devDependencies": {
22
37
  "@xmldom/xmldom": "0.9.12",
23
38
  "papaparse": "^5.3.2",