diff --git a/.editorconfig b/.editorconfig index 5fbf207..9515fbb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,15 +1,15 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -insert_final_newline = false -trim_trailing_whitespace = false - -[*.{js,jsx,json,ts,tsx,yml,svelte,svg}] -indent_size = 2 -indent_style = space +root = true + +[*] +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false + +[*.{js,jsx,json,ts,tsx,yml,svelte,svg}] +indent_size = 2 +indent_style = space diff --git a/.eslintrc.js b/.eslintrc.js index 307c6d0..b0365e4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,42 +1,42 @@ -module.exports = { - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'simple-import-sort'], - env: { - node: true, - }, - overrides: [ - { - files: ['*.ts'], - extends: [ - 'plugin:@typescript-eslint/recommended-requiring-type-checking', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - ], - parserOptions: { - project: ['./tsconfig.json'], - tsconfigRootDir: __dirname, - }, - rules: { - 'simple-import-sort/imports': [ - 'error', - { - groups: [ - // Packages `react` related packages come first. - ['^react', '^@?\\w'], - // Internal packages. - ['^(@|~|components)(/.*|$)'], - // Side effect imports. - ['^\\u0000'], - // Parent imports. Put `..` last. - ['^\\.\\.(?!/?$)', '^\\.\\./?$'], - // Other relative imports. Put same-folder imports and `.` last. - ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'], - // Style imports. - ['^.+\\.?(css)$'], - ], - }, - ], - }, - }, - ], -}; +module.exports = { + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint', 'simple-import-sort'], + env: { + node: true, + }, + overrides: [ + { + files: ['*.ts'], + extends: [ + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + ], + parserOptions: { + project: ['./tsconfig.json'], + tsconfigRootDir: __dirname, + }, + rules: { + 'simple-import-sort/imports': [ + 'error', + { + groups: [ + // Packages `react` related packages come first. + ['^react', '^@?\\w'], + // Internal packages. + ['^(@|~|components)(/.*|$)'], + // Side effect imports. + ['^\\u0000'], + // Parent imports. Put `..` last. + ['^\\.\\.(?!/?$)', '^\\.\\./?$'], + // Other relative imports. Put same-folder imports and `.` last. + ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'], + // Style imports. + ['^.+\\.?(css)$'], + ], + }, + ], + }, + }, + ], +}; diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 06611cc..0c76120 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,2 @@ -github: [hadynz] -custom: ["https://buymeacoffee.com/hadynz"] +github: [hadynz] +custom: ["https://buymeacoffee.com/hadynz"] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 27c73ee..2fe209e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,32 +1,32 @@ ---- -name: Bug report -about: Create a report to help us improve -title: "[BUG] " -labels: bug -assignees: '' ---- - -### Describe the bug -A clear and concise description of what the bug is. - -### Method of syncing -- [ ] Amazon Kindle Reader -- [ ] My Clippings file (please **attach file** that can be used to recreate issue) - -### To Reproduce -Steps to reproduce the behaviour: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. Share error(s) from **Developer Tools console** - -### Expected behaviour -A clear and concise description of what you expected to happen. - -### Screenshots -If applicable, add screenshots to help explain your problem. - -### Metadata - - OS: [e.g. Mac, Windows, Linux] - - Plugin version [e.g. 1.5.2] - - Obsidian version [e.g. 0.12.19] +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG] " +labels: bug +assignees: '' +--- + +### Describe the bug +A clear and concise description of what the bug is. + +### Method of syncing +- [ ] Amazon Kindle Reader +- [ ] My Clippings file (please **attach file** that can be used to recreate issue) + +### To Reproduce +Steps to reproduce the behaviour: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. Share error(s) from **Developer Tools console** + +### Expected behaviour +A clear and concise description of what you expected to happen. + +### Screenshots +If applicable, add screenshots to help explain your problem. + +### Metadata + - OS: [e.g. Mac, Windows, Linux] + - Plugin version [e.g. 1.5.2] + - Obsidian version [e.g. 0.12.19] diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 11fc491..73987ed 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,20 +1,20 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: enhancement -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 84b57a8..08c573d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,24 +1,24 @@ -name: CI - -on: - pull_request: - branches: [master] - -jobs: - lint-and-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: '19.x' - - - name: Install modules - run: npm install - - - name: Lint - run: npm run lint - - - name: Run tests - run: npm run test-verbose +name: CI + +on: + pull_request: + branches: [master] + +jobs: + lint-and-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: '19.x' + + - name: Install modules + run: npm install + + - name: Lint + run: npm run lint + + - name: Run tests + run: npm run test-verbose diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index dc427b4..232439b 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -1,62 +1,62 @@ -name: Build obsidian plugin - -on: - release: - types: [published] - -env: - PLUGIN_NAME: obsidian-kindle-plugin - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Use Node.js - uses: actions/setup-node@v1 - with: - node-version: '15.x' - - - name: Build - id: build - run: | - npm install - npm run lint - npm run test-verbose - npm run build - zip -r -j ${{ env.PLUGIN_NAME }}.zip dist -x "*.map" - ls - echo "::set-output name=tag_name::$(git tag --sort version:refname | tail -n 1)" - - - name: Upload main.js - id: upload-main - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./dist/main.js - asset_name: main.js - asset_content_type: text/javascript - - - name: Upload manifest.json - id: upload-manifest - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./dist/manifest.json - asset_name: manifest.json - asset_content_type: application/json - - - name: Upload plugin zip package - id: upload-zip-package - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./${{ env.PLUGIN_NAME }}.zip - asset_name: ${{ env.PLUGIN_NAME }}-${{ steps.build.outputs.tag_name }}.zip - asset_content_type: application/zip +name: Build obsidian plugin + +on: + release: + types: [published] + +env: + PLUGIN_NAME: obsidian-kindle-plugin + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + with: + node-version: '15.x' + + - name: Build + id: build + run: | + npm install + npm run lint + npm run test-verbose + npm run build + zip -r -j ${{ env.PLUGIN_NAME }}.zip dist -x "*.map" + ls + echo "::set-output name=tag_name::$(git tag --sort version:refname | tail -n 1)" + + - name: Upload main.js + id: upload-main + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./dist/main.js + asset_name: main.js + asset_content_type: text/javascript + + - name: Upload manifest.json + id: upload-manifest + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./dist/manifest.json + asset_name: manifest.json + asset_content_type: application/json + + - name: Upload plugin zip package + id: upload-zip-package + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./${{ env.PLUGIN_NAME }}.zip + asset_name: ${{ env.PLUGIN_NAME }}-${{ steps.build.outputs.tag_name }}.zip + asset_content_type: application/zip diff --git a/.gitignore b/.gitignore index fa7ddb4..22565cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,25 @@ -# Intellij -*.iml -.idea - -# npm -node_modules - -# nunjucks file -main.js.LICENSE.txt - -# eslint -.eslintcache - -# obsidian plugin files -main.js -main.js.map -data.json - -coverage -dist -tsconfig.tsbuildinfo -.env - -# Mac -.DS_Store +# Intellij +*.iml +.idea + +# npm +node_modules + +# nunjucks file +main.js.LICENSE.txt + +# eslint +.eslintcache + +# obsidian plugin files +main.js +main.js.map +data.json + +coverage +dist +tsconfig.tsbuildinfo +.env + +# Mac +.DS_Store diff --git a/.husky/.gitignore b/.husky/.gitignore index 31354ec..7517305 100644 --- a/.husky/.gitignore +++ b/.husky/.gitignore @@ -1 +1 @@ -_ +_ diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 36af219..0000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx lint-staged diff --git a/.npmrc b/.npmrc index 43c97e7..094e384 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1 @@ -package-lock=false +package-lock=false diff --git a/.prettierignore b/.prettierignore index 381bc27..b30a828 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,4 @@ -dist -main.js -main.js.map -data.json +dist +main.js +main.js.map +data.json diff --git a/.prettierrc b/.prettierrc index d69bbf3..2b44b09 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,8 +1,8 @@ -{ - "printWidth": 95, - "svelteSortOrder": "scripts-markup-styles", - "svelteBracketNewLine": true, - "svelteAllowShorthand": true, - "svelteIndentScriptAndStyle": true, - "singleQuote": true -} +{ + "printWidth": 95, + "svelteSortOrder": "scripts-markup-styles", + "svelteBracketNewLine": true, + "svelteAllowShorthand": true, + "svelteIndentScriptAndStyle": true, + "singleQuote": true +} diff --git a/.vscode/launch.json b/.vscode/launch.json index 6a9ab27..7d685e1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,17 +1,17 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Debug Jest Tests", - "type": "node", - "request": "launch", - "runtimeArgs": [ - "--inspect-brk", - "${workspaceRoot}/node_modules/.bin/jest", - "--runInBand" - ], - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen" - } - ] -} +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Jest Tests", + "type": "node", + "request": "launch", + "runtimeArgs": [ + "--inspect-brk", + "${workspaceRoot}/node_modules/.bin/jest", + "--runInBand" + ], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + } + ] +} diff --git a/Amazon_sources/Kindle_ Your Notes and Highlights.html b/Amazon_sources/Kindle_ Your Notes and Highlights.html new file mode 100644 index 0000000..ed11df9 --- /dev/null +++ b/Amazon_sources/Kindle_ Your Notes and Highlights.html @@ -0,0 +1,906 @@ + + +
+ + + + + + + + + +Annotated books from your library

By: John Gribbin

By: Friedrich Nietzsche, Kuldeep Sharma, and Thomas Common
Would you like to take some notes?
+ + You haven’t created any notes for this book yet. You can add or remove bookmarks, highlights, and notes at any location in a Kindle book. + + ++ Once you delete this highlight, it will be removed from all of your devices. +
+ ++ Once you delete this note, it will be removed from all of your devices. +
+ +a&&(a=0);v.status=a;v.statusText=""+(b||m);F?h.resolveWith(f,[O,m,v]):h.rejectWith(f,[v,m,N]);v.statusCode(l);l=p;t&&g.trigger("ajax"+(F?"Success":"Error"),[v,e,F?O:N]);k.resolveWith(f,[v,m]);t&&(g.trigger("ajaxComplete",[v,e]),--c.active||c.event.trigger("ajaxStop"))}}"object"===typeof a&&(b=a,a=p);b=b||{};var e=c.ajaxSetup({},b),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof c)?c(f):c.event,h=c.Deferred(),k=c._Deferred(), +l=e.statusCode||{},m={},n={},q,r,B,w,E=0,z,v={readyState:0,setRequestHeader:function(a,b){if(!E){var c=a.toLowerCase();a=n[c]=n[c]||a;m[a]=b}return this},getAllResponseHeaders:function(){return 2===E?q:null},getResponseHeader:function(a){var b;if(2===E){if(!r)for(r={};b=Ub.exec(q);)r[b[1].toLowerCase()]=b[2];b=r[a.toLowerCase()]}return b===p?null:b},overrideMimeType:function(a){E||(e.mimeType=a);return this},abort:function(a){a=a||"abort";B&&B.abort(a);d(0,a);return this}};h.promise(v);v.success= +v.done;v.error=v.fail;v.complete=k.done;v.statusCode=function(a){if(a)if(2>E)for(b in a)l[b]=[l[b],a[b]];else{var b=a[v.status];v.then(b,b)}return this};e.url=((a||e.url)+"").replace(Tb,"").replace(Xb,N[1]+"//");e.dataTypes=c.trim(e.dataType||"*").toLowerCase().split(Ga);null==e.crossDomain&&(a=cb.exec(e.url.toLowerCase()),e.crossDomain=!(!a||a[1]==N[1]&&a[2]==N[2]&&(a[3]||("http:"===a[1]?80:443))==(N[3]||("http:"===N[1]?80:443))));e.data&&e.processData&&"string"!==typeof e.data&&(e.data=c.param(e.data, +e.traditional));aa(ka,e,b,v);if(2===E)return!1;var t=e.global;e.type=e.type.toUpperCase();e.hasContent=!Wb.test(e.type);t&&0===c.active++&&c.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(bb.test(e.url)?"\x26":"?")+e.data,delete e.data);var x=e.url;if(!1===e.cache){a=c.now();var D=e.url.replace($b,"$1_\x3d"+a);e.url=D+(D===e.url?(bb.test(e.url)?"\x26":"?")+"_\x3d"+a:"")}}(e.data&&e.hasContent&&!1!==e.contentType||b.contentType)&&v.setRequestHeader("Content-Type",e.contentType);e.ifModified&& +(x=x||e.url,c.lastModified[x]&&v.setRequestHeader("If-Modified-Since",c.lastModified[x]),c.etag[x]&&v.setRequestHeader("If-None-Match",c.etag[x]));v.setRequestHeader("Accept",e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+("*"!==e.dataTypes[0]?", */*; q\x3d0.01":""):e.accepts["*"]);for(z in e.headers)v.setRequestHeader(z,e.headers[z]);if(e.beforeSend&&(!1===e.beforeSend.call(f,v,e)||2===E))return v.abort(),!1;for(z in{success:1,error:1,complete:1})v[z](e[z]);if(B=aa(eb,e,b,v)){v.readyState= +1;t&&g.trigger("ajaxSend",[v,e]);e.async&&0E?d(-1,u):c.error(u)}}else d(-1,"No Transport");return v},param:function(a,b){var d=[],e=function(a,b){b=c.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"\x3d"+encodeURIComponent(b)};b===p&&(b=c.ajaxSettings.traditional);if(c.isArray(a)||a.jquery&&!c.isPlainObject(a))c.each(a,function(){e(this.name,this.value)});else for(var f in a)la(f,a[f],b,e);return d.join("\x26").replace(Sb, +"+")}});c.extend({active:0,lastModified:{},etag:{}});var bc=c.now(),fa=/(=)\?(&|$)|\?\?/i;c.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return c.expando+"_"+bc++}});c.ajaxPrefilter("json jsonp",function(a,b,d){b="application/x-www-form-urlencoded"===a.contentType&&"string"===typeof a.data;if("jsonp"===a.dataTypes[0]||!1!==a.jsonp&&(fa.test(a.url)||b&&fa.test(a.data))){var e,f=a.jsonpCallback=c.isFunction(a.jsonpCallback)?a.jsonpCallback():a.jsonpCallback,g=r[f],h=a.url,k=a.data,l="$1"+f+ +"$2";!1!==a.jsonp&&(h=h.replace(fa,l),a.url===h&&(b&&(k=k.replace(fa,l)),a.data===k&&(h+=(/\?/.test(h)?"\x26":"?")+a.jsonp+"\x3d"+f)));a.url=h;a.data=k;r[f]=function(a){e=[a]};d.always(function(){r[f]=g;if(e&&c.isFunction(g))r[f](e[0])});a.converters["script json"]=function(){e||c.error(f+" was not called");return e[0]};a.dataTypes[0]="json";return"script"}});c.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/}, +converters:{"text script":function(a){c.globalEval(a);return a}}});c.ajaxPrefilter("script",function(a){a.cache===p&&(a.cache=!1);a.crossDomain&&(a.type="GET",a.global=!1)});c.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=q.head||q.getElementsByTagName("head")[0]||q.documentElement;return{send:function(d,f){b=q.createElement("script");b.async="async";a.scriptCharset&&(b.charset=a.scriptCharset);b.src=a.url;b.onload=b.onreadystatechange=function(a,d){if(d||!b.readyState||/loaded|complete/.test(b.readyState))b.onload= +b.onreadystatechange=null,c&&b.parentNode&&c.removeChild(b),b=p,d||f(200,"success")};c.insertBefore(b,c.firstChild)},abort:function(){if(b)b.onload(0,1)}}}});var va=r.ActiveXObject?function(){for(var a in U)U[a](0,1)}:!1,cc=0,U;c.ajaxSettings.xhr=r.ActiveXObject?function(){var a;if(!(a=!this.isLocal&&Ia()))a:{try{a=new r.ActiveXObject("Microsoft.XMLHTTP");break a}catch(b){}a=void 0}return a}:Ia;(function(a){c.extend(c.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})})(c.ajaxSettings.xhr());c.support.ajax&& +c.ajaxTransport(function(a){if(!a.crossDomain||c.support.cors){var b;return{send:function(d,e){var f=a.xhr(),g;a.username?f.open(a.type,a.url,a.async,a.username,a.password):f.open(a.type,a.url,a.async);if(a.xhrFields)for(g in a.xhrFields)f[g]=a.xhrFields[g];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType);a.crossDomain||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest");try{for(g in d)f.setRequestHeader(g,d[g])}catch(k){}f.send(a.hasContent&&a.data||null);b=function(d,g){var k; +try{if(b&&(g||4===f.readyState))if(b=p,h&&(f.onreadystatechange=c.noop,va&&delete U[h]),g)4!==f.readyState&&f.abort();else{var l=f.status;var q=f.getAllResponseHeaders();var r={};(k=f.responseXML)&&k.documentElement&&(r.xml=k);r.text=f.responseText;try{var B=f.statusText}catch(w){B=""}l||!a.isLocal||a.crossDomain?1223===l&&(l=204):l=r.text?200:404}}catch(w){g||e(-1,w)}r&&e(l,B,r,q)};if(a.async&&4!==f.readyState){var h=++cc;va&&(U||(U={},c(r).unload(va)),U[h]=b);f.onreadystatechange=b}else b()},abort:function(){b&& +b(0,1)}}}});var ma={},G,M,dc=/^(?:toggle|show|hide)$/,ec=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,ha,Ka=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],ba;c.fn.extend({show:function(a,b,d){if(a||0===a)return this.animate(K("show",3),a,b,d);d=0;for(var e=this.length;d =f.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();f.animatedProperties[this.prop]=!0;for(g in f.animatedProperties)!0!==f.animatedProperties[g]&&(d=!1);if(d){null==f.overflow||c.support.shrinkWrapBlocks||c.each(["","X","Y"],function(a,b){e.style["overflow"+ +b]=f.overflow[a]});f.hide&&c(e).hide();if(f.hide||f.show)for(var h in f.animatedProperties)c.style(e,h,f.orig[h]);f.complete.call(e)}return!1}Infinity==f.duration?this.now=b:(a=b-this.startTime,this.state=a/f.duration,this.pos=c.easing[f.animatedProperties[this.prop]](this.state,a,0,1,f.duration),this.now=this.start+(this.end-this.start)*this.pos);this.update();return!0}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b =A?(clearTimeout(f),f=null,v=C,e=a.apply(k,q),k=q=null):f||!1===c.trailing||(f=setTimeout(x,A));return e}},sequence:function(){var a=[].slice,d=a.call(arguments).reverse(),c=this;return b.reduce(d,function(k,d){return function(){var b=a.call(arguments);b.push(k);d.apply(c,b)}},function(){})},debounce:function(a,d,c){var k,q,e,f,g,v=l.fn(this,a),x=function(){var a=b.now()- +f;a ?@\[\\\]^`{|}~])/g;return{trim:function(a){return String.prototype.trim?String.prototype.trim.call(a):a.replace(d,"").replace(c,"")},contains:function(a,c){return-1!==(""+a).indexOf(c)},escapeHtml:function(c){return(""+c).replace(k,function(c){return a[c]})},escapeJquerySelector:function(a){return(""+a).replace(e,"\\$1")},parseJSON:function(a){return JSON.parse(a)}}}, +function(b){function a(a){return b.map(d,function(c){var b=a.getAttribute(c);return b&&"["+c+"\x3d"+b+"]"}).join("")}var d=["id","cel_widget_id","data-feature-name","data-action","data-aui-build-date"];return{xpath:function(a){if(""!==a.id)return'//*[@id\x3d"'+a.id+'"]';if(a===document.documentElement)return"/html";var c=b.indexOfArray(b.filter(a.parentNode.childNodes,function(c){return c.tagName===a.tagName}),a);if(-1===c)throw Error("can not evaluate xpath of element `"+a.tagName+(a.id?"#"+a.id: +"")+"`");return b.xpath(a.parentNode)+"/"+a.tagName+"["+(c+1)+"]"},cssSelector:function(a){var c=[a.tagName||""];a.className&&a.className.trim&&c.push("."+a.className.trim().replace(/\s+/g,"."));a.id&&c.push("#"+a.id);return c.join("")},attributionChain:function(c){var d=[];do d.push(a(c)),c=c.parentElement;while(c);return b.filter(d,Boolean).reverse().join(" ")}}},function(b){return{hide:function(a){b.each(f(a),function(a){b.addClass(a,"aok-hidden")})},show:function(a){b.each(f(a),function(a){b.removeClass(a, +"aok-hidden")})}}},function(b){function a(){d={};for(var a=(document.cookie||"").split(";"),k=a.length-1;0<=k;k--){var e=a[k].split("\x3d"),f=b.trim(e[0]);if(f){var g=d;e=e.slice(1).join("\x3d");e=b.trim(e);/^"/.test(e)&&(e=e.slice(1,-1).replace(/\\(.)/g,"$1"));e=m.decodeURIComponent(e);g[f]=e}}}var d;return{cookies:{get:function(c){d||a();return d[c]},getAll:function(){d||a();return b.extend({},d)},refresh:function(){d=null}}}},function(b){return{onScreen:function(a,d){if(!a)return!1;a.jquery&&(a= +a[0]);if(!a)return!1;d="number"===typeof d&&!isNaN(d)&&isFinite(d)?d:100;if(1!==a.nodeType||!(a.offsetWidth||a.offsetHeight||a.getClientRects().length))return!1;var c=b.size(m),k=b.scroll(m),e=k.top,f=m.innerHeight?m.innerHeight:c.height,g=e+f;k=k.left;c=m.innerWidth?m.innerWidth:c.width;var h=k+c;e-=d;g+=d;k-=d;h+=d;var v=b.offset(a),t=b.size(a);a=v.top;d=t.height;var n=a+d;v=v.left;t=t.width;var A=v+t;return(a>=e&&a e&&n<=g||d>f&&a<=e&&n>=g)&&(v>=k&&v k&&A<=h||t>c&&v<=k&&A>=h)}}},function(b){return{isATF:function(a, +d){d="number"===typeof d&&!isNaN(d)&&isFinite(d)?d:100;d=b.size(m).height+d;a=b.offset(a).top;return 0<=a&&a e[1]);return e},isFirefox:function(){return/Firefox/.test(h.ua)}, +isIE:function(){return g},isIE10:function(){return g&&"onmspointerup"in document&&!("onpointerup"in document)},isIE10Plus:function(){return g&&("onpointerup"in document||"onmspointerup"in document)},isIE11Plus:function(){return g&&"onpointerup"in document},isiOS8:function(){return b.capabilities.ios&&/Version\/8\./.test(h.ua)},isIETouchCapable:function(){return f.isIE10Plus&&/Touch;/.test(h.ua)},isMetroIEGuess:function(){var e=!0;try{e=new ActiveXObject("htmlfile")}catch(n){e=!1}return f.isIE10Plus&& +!b.capabilities.mobile&&!e}},function(b,g){f[g]=h.safeFeatureTest(b)});return f});"use strict";p.when("p-detect","prv:a-capabilities","a-util","prv:a-private-util").register("a-detect",function(b,l,h,f){var g=h.copy(b),e=function(){var b=/(?:Android\s+|Windowshop.*Android\/|Android\/)(\d+(?:\.\d+)*)/.exec(f.ua);return b&&b[1]},n={};h.each({isAmazonApp:function(){return/(Windowshop|Amazon|AmazonBusiness|Amazon\.com)\//.test(h.cookies.get("amzn-app-id"))},isGen5App:function(){return/Windowshop.*(?:KFOT|KFTH|KFJWA|KFJWI|KFTT)/.test(f.ua)}, +isAndroid:function(){return g.capabilities.android},androidVersion:function(){return e()},isAndroidKitkatPlus:function(){var b=e();return b&&null!==b.match(/(^4\.[4-9]|^[5-9]|^\d\d)/)},isOldAndroid:function(){return/Android\s[12][^0-9]/.test(f.ua)},pointerPrefix:function(){return"onmspointerup"in document||"onpointerup"in document?"onpointerup"in document?"pointer":"MSPointer":!1},actionMode:function(){var b=g.capabilities.pointerPrefix;return b?b:g.capabilities.touch?"touch":"mouse"}},function(b, +e){g.capabilities[e]=f.safeFeatureTest(b)});h.extend(g.capabilities,l);h.each({start:{mouse:"down",touch:"start",pointer:"down",MSPointer:"Down"},end:{mouse:"up",touch:"end",pointer:"up",MSPointer:"Up"},move:{mouse:"move",touch:"move",pointer:"move",MSPointer:"Move"},enter:{mouse:"enter",touch:"enter",pointer:"enter"},leave:{mouse:"leave",touch:"leave",pointer:"leave"},cancel:{touch:"cancel",pointer:"cancel",MSPointer:"Cancel"},over:{mouse:"over",pointer:"over",MSPointer:"Over"},out:{mouse:"out", +pointer:"out",MSPointer:"Out"}},function(b,e){var f=g.capabilities.actionMode,a="string"===typeof b?b:b[f];n[e]=a?f+a:b.mouse===r?"":"mouse"+b.mouse});g.action=n;b={};"pointer"===g.capabilities.pointerPrefix?(b.touch="touch",b.pen="pen",b.mouse="mouse",b.unknown=""):"MSPointer"===g.capabilities.pointerPrefix&&(b.touch=2,b.pen=3,b.mouse=4);g.pointerType=b;return g});"use strict";p.when("prv:a-guard").register("a-defer",function(b){function l(b){var e=0,h=setTimeout(function(){l(b)},0);if(0===b.length)clearTimeout(h), +f=!1;else{var z=Date.now();b.shift().call();g+=Date.now()-z;50 b.now()-e;)if(f(d)===k){c=!1;return}b.delay(a,15)}var c=!1,d=[];return function(b){Array.prototype.push.apply(d,b);c||a()}}(),y=function(){var a=!1,c=[];return function(b){Array.prototype.push.apply(c,b);if(!a){for(a=!0;f(c)!==k;);a=!1}}}(),B=0,w=function(){var a=function(a,d,k){var f= +a.split(" "),h=[],v=d;!0===k&&(v=function(){d.apply(m,arguments);t(a,v)});var n=this?{logError:this._logError,guard:this._guard}:{};b.each(f,function(a){"unload"===a&&(a="pagehide");(c[a]||[]).occurred?(e(a,d,n),g(a)):h.push(e(a,v,n).event)});return{event:h.join(" "),callback:v}};b.each("ready load unload afterLoad scroll resize orientationchange zoom".split(" "),function(c){a[c]=function(b,d){a.call(this,c,b,d)}});return a}();a.prototype={isListening:z,on:w,one:function(a,c){var b=a.split(" ");if(1< +b.length)p.error("A.one only accepts a single event name, but was provided with: "+b.length+", ("+a+")","A.events","one");else return w(a,c,!0)},off:function(a,c){if("object"===typeof a){var b=a.event;a=a.callback}else b=a,a=c;return t(b,a)},trigger:function(a){for(var c=arguments.length,b=Array(c),d=0;d b._zimIndex&& +(d._zimIndex-=d._zimIndex>this._maxZIndex-1?2:1,d.css("zIndex",d._zimIndex))}b._zimIndex=this._maxZIndex}},e=function(e){var a=e.$event;b.contains("touchstart touchend touchmove",e.type)&&(a=a.originalEvent.touches[0]);return{x:a.clientX,y:a.clientY}},n=function(b){var a=b.data.$draggable,d=a.data("a-draggables"),c=e(b);d.isMouseDown&&(a.css({left:c.x-d.clickOffset.x,top:c.y-d.clickOffset.y}),b.$event.preventDefault())},t=function(b){var a=b.$event.target||b.$event.srcElement,d=b.data.$draggable, +c=d.data("a-draggables");g.acquireFocus(d);a=l(a).closest(c.$handle,d);c.isMouseDown=0 c?(a.send(),c++):(b.push(a),d++,b.length>e&&(e=b.length),(a=m.ue)&&a.count&&(a.count("aui:ajax:queued",d),a.count("aui:ajax:maxQueued",e)))},complete:a,abort:function(c){c=h.indexOfArray(b,c);-1!==c&&b.splice(c,1);a()}}}(),b=function(){},d=function(b){var c=b.http,d=!1,e=!1;switch(c.readyState){case 4:e=!0;break;case 3:d=!0}var k=200===c.status||304===c.status,g=b.responsePosition;if(d||e&&k){var n= +c.responseText;if(g b.http.readyState&&(clearInterval(b.pollTimer),b.callbacks.failure(b,"Request Timeout", +"Request Timeout"),a.complete())}function k(a,b,c){c=c||{};c=h.extend({},f.all,f[b],c);h.each(c,function(b,c){(b||""===b)&&a.setRequestHeader(c,b)});return a}function g(b,c,d,e,g,f,h,n,l,v){var q=b.http;q.open(c,d);k(q,c,l);b.timeout=e;b.callbacks.chunk=g||b.callbacks.chunk;b.callbacks.success=f||b.callbacks.success;b.callbacks.failure=h||b.callbacks.failure;b.callbacks.abort=n||b.callbacks.abort;v&&(q.withCredentials=!0);a.add(b);return{abort:function(){b.abort()}}}var f={all:{"X-Requested-With":"XMLHttpRequest"}, +get:{Accept:"text/html,*/*"},post:{Accept:"text/html,*/*","Content-Type":"application/x-www-form-urlencoded"}},n=function(){var a=new XMLHttpRequest;this.pollTimer=null;this.http=a;this.responsePosition=0;this.buffer="";this.callbacks={success:b,failure:b,chunk:b,abort:b}};n.prototype={send:function(){var a=this;a.http.send(a.params);a.pollTimer=setInterval(function(){if(2<=a.http.readyState&&"unknown"!==typeof a.http.responseText){var b=a.http.getResponseHeader("Content-Type");b=b?b.toLowerCase(): +"";(-1!==b.indexOf("application/json-amazonui-streaming")||-1!==b.indexOf("application/amazonui-streaming-json")?d:e)(a)}},25);a.timeout="undefined"===typeof a.timeout?2E4:a.timeout;a.timeoutTimer=h.delay(c,a.timeout,a)},get:function(a,b,c,d,e,k,f,h,n){if(b){var l=a.indexOf("?"),v=a.charAt(a.length-1);-1 c?"all 0ms":"all "+c+"ms "+h);4 +a.css("opacity")?this.fadeIn:this.fadeOut).call(this,a,b,c,e)},slideUp:function(a,d,c,e){var g=this.animate;a.css({height:a.innerHeight(),overflow:"hidden"}); +b.delay(function(){g(a,{height:0},d,c,function(){a.hide();a.css({height:"",overflow:""});e&&e()})},0)},slideDown:function(a,d,c,e){var g=a.innerHeight(),f=this.animate;a.css({height:0,overflow:"hidden"});a.show();b.delay(function(){f(a,{height:g},d,c,function(){e&&e();a.css({height:"",overflow:""})})},0)},slideToggle:function(a,b,c,e){(a.is(":visible")?this.slideUp:this.slideDown).call(this,a,b,c,e)},isAnimated:function(a){a=a.jquery?a[0]:a;return a._a&&0 =f&&b f&&d<=h||a>g&&b<=f&&d>=h}var e=function(){var b={},e=0;return{get:function(e){return b[e.data("cacheKey")]},set:function(g){g.data("cacheKey")||(g.data("cacheKey",e),e++);b[g.data("cacheKey")]={top:g.offset().top, +height:g.height()}},remove:function(e){e.data("cacheKey")&&delete b[e.data("cacheKey")]}}}();h();f();b.on("scroll",function(){f()});b.on("scroll",b.debounce(function(){h();f()},250));b.on("resize",f);b.on("a:image:lazyLoad",f);b.on.ready(f)});"use strict";p.register("a-image-url-key-handler",function(){return{generate:function(b,l){return b},parse:function(b){return{url:b}}}});"use strict";p.when("jQuery","a-util","a-events","a-defer","p-detect","a-image-url-key-handler").register("a-image",function(b, +l,h,f,g,e){function n(a){a=b(a);var d=a.data("a-dynamic-image");if(d&&"object"===typeof d){var e=a.data("a-dynamic-image-container");"undefined"===typeof e&&(e=a.closest(".a-dynamic-image-container"),0===e.length&&(e=a.parent()),a.data("a-dynamic-image-container",e));var f=g.capabilities.hires&&m.devicePixelRatio?m.devicePixelRatio:1,k=e.width()*f,n=e.height()*f,t=Number.MAX_VALUE,p=Number.MAX_VALUE,u=a.attr("src")||"",q,r=k/n;l.each(d,function(a,b){var c="string"===typeof a?JSON.parse(a):a;a=parseInt(c[0], +10);c=parseInt(c[1],10);a-=n;c-=k;a=1<=r?c:a;Math.abs(a) e()?90:0:m.orientation:"height"===f?k[f]=e():"width"=== +f?k[f]=n():"scrollTop"===f?k[f]=m.scrollY?m.scrollY:d.scrollTop():"scrollLeft"===f?k[f]=m.scrollX?m.scrollX:d.scrollLeft():"zoom"===f&&(k[f]=t()),k[f]!==g&&(b[f]=g);return b}function u(a){if(a=w[a])a.pollCounter=a.maxPollCount,a.intervalId||(a.intervalId=setInterval(a.handler,a.pollInterval))}function a(a){(a=w[a])&&a.intervalId&&(clearInterval(a.intervalId),a.intervalId=0)}var d=b(m),c={ORIENTATION_CHANGE:"orientationchange",SCROLL:"scroll",RESIZE:"resize",ZOOM:"zoom",ALL:"all"},k={scrollLeft:0, +scrollTop:0,height:e(),width:n(),orientation:m.orientation===r?n()>e()?90:0:m.orientation,zoom:t()};h.on("beforeReady",function(){p(c.ALL)});var q={speed:0,degree:0,direction:"",positionX:0,positionY:0},y=[],B;d.bind("mousemove",f.throttle(function(a){a={x:a.clientX,y:a.clientY};if(B){var b=B,c=0,e=0;y.push({speed:Math.sqrt(Math.pow(a.x-b.x,2)+Math.pow(a.y-b.y,2))/50*10,degree:Math.atan2(a.y-b.y,a.x-b.x)/(Math.PI/180)});4
e?"W":-112.5>e?"NW":-67.5>e?"N":-22.5>e?"NE":"E",positionX:a.x,positionY:a.y};B=a}else a&&(B=a)},50));d.bind(c.SCROLL,f.throttle(function(){var a=p(c.SCROLL);h.trigger(c.SCROLL,k,a)},100));var w={};f.each([c.RESIZE,c.ZOOM],function(a){w[a]={handler:function(){},lastViewport:f.copy(k),maxPollCount:5,pollCounter:5,pollInterval:100,intervalId:0}});w.resize.handler= +function(){var b=[],e=w.resize;p("resize");var d=f.diff(k,e.lastViewport);d.orientation&&b.push(c.ORIENTATION_CHANGE);d.width||d.height?b.push(c.RESIZE):l.capabilities.isIETouchCapable&&d.scrollTop&&b.push(c.RESIZE);b.length&&(e.lastViewport=f.copy(k),f.each(b,function(a){h.trigger(a,k,d)}));0===--e.pollCounter&&a(c.RESIZE)};w.resize.pollInterval=100;w.resize.maxPollCount=10;d.bind(c.RESIZE,function(a){u(c.RESIZE)});w.zoom.handler=function(){p(c.ZOOM);var b=w.zoom,e=f.diff(k,b.lastViewport);e.zoom&& +(b.lastViewport=f.copy(k),h.trigger(c.ZOOM,k,e));0===--b.pollCounter&&a(c.ZOOM)};w.zoom.pollInterval=200;l.capabilities.android&&d.bind("touchcancel",function(a){2===a.originalEvent.changedTouches.length&&(w.zoom.maxPollCount=15,u(c.ZOOM))});l.capabilities.ios&&d.bind("touchend",function(a){1===a.originalEvent.touches.length&&(w.zoom.maxPollCount=1,u(c.ZOOM))});l.capabilities.ios||l.capabilities.android||d.bind("resize",function(a){w.zoom.maxPollCount=5;u(c.ZOOM)});return{viewport:function(a){a&& +p(c.ALL);return f.copy(k)},cursor:function(){return f.copy(q)},scrollBarWidth:function(a){if(a||(document&&document.body&&document.body.scrollHeight?document.body.scrollHeight:0)>e()){a=document.createElement("div");a.style.visibility="hidden";a.style.width="100%";a.style.overflowX="scroll";document.body.appendChild(a);var b=a.offsetHeight;document.body.removeChild(a);return b}return 0}}});"use strict";p.when("a-util").register("a-request-animation-frame",function(b){for(var l=0,h=["ms","moz","webkit", +"o"],f=0;f b.indexOfArray(f,g[e]))return!1;return!0}var h=0,f=b.constants.declarativeEvents.split(" ");return{show:function(){this._$element.removeClass("a-hidden aok-hidden").show();return this},hide:function(){this._$element.addClass("aok-hidden");return this},toggle:function(){return this._$element.hasClass("aok-hidden")?this.show():this.hide()},size:function(){return this._$element.size()},isEmpty:function(){return 0=== +this._$element.size()},on:function(f,e){var g=b.parseFunctionName(e);g||p.error.call({},"Please name all asynchronous event callbacks");if(f=f?f.split(" "):r){this.fnMap=this.fnMap||{};l(f)||p.error.call({},"That event is not supported!");var m=this;b.each(f,function(f){this.fnMap[f]=this.fnMap[f]||[];var l=this.fnMap[f][e]="a-component-event-"+h++;b.declarative(l,f,function(){try{e.apply(m,m.callbackArgs||[])}catch(a){p.logError.call({},a,"Error occurred in an asynchronous event callback","FATAL", +(e.caller||"")+f+"handler:"+(g||"anonymous"))}});b.declarative.create(m._$element,l)},m)}},off:function(f,e){f=f?f.split(" "):r;this.fnMap||p.error.call({},"There are no callbacks assigned to this component");f&&e?b.each(f,function(f){try{b.declarative.remove(this._$element,this.fnMap[f][e]),delete this.fnMap[f][e]}catch(t){p.error.call({},"The component is not bound to a callback with name "+b.parseFunctionName(e)||"anonymous for event "+f)}},this):e||f?!e&&f?b.each(f,function(b){for(var e in this.fnMap[b])this.fnMap[b].hasOwnProperty(e)&& +this.off(b,e);delete this.fnMap[b]},this):p.error.call({},"Please provide an event associated with the callback"):(b.declarative.remove(this._$element),delete this.fnMap)},trigger:function(f,e){this.callbackArgs=e||[];b.$.fn.trigger.call(this._$element,f)}}});"use strict";p.when("A","jQuery","a-component-mixins","a-analytics","prv:a-sampler").register("a-component",function(b,l,h,f,g){var e=b.createClass({init:function(e,f){b.contains(e,".a-")&&p.error("{API} Cannot create components using 'a-' selectors. Apply your own CSS class or ID to select this element.", +"API","component");this._$element=l(e,f);this._trackApi()},_trackApi:function(){this._componentName&&g("AUI API Analytics")&&f.increment("api:"+this._componentName)}});return{create:function(f){var g=f.mixin;g&&delete f.mixin;f=e.extend(f);g&&b.mixin(f.prototype,h,g);return f}}});"use strict";p.when("A","jQuery","a-component").register("a-alert",function(b,l,h){var f=["error","success","warning","info"],g=b.map(f,function(b){return"a-alert-"+b}).join(" "),e=b.map(f,function(b){return"a-alert-inline-"+ +b}).join(" "),n=document.createElement("h4");n.className="a-alert-heading";var m=l(n),r=h.create({_componentName:"alert",init:function(b,a){this._super(b,a);this._$element=this._$element.filter(".a-alert, .a-alert-inline");this._$heading=this._$element.find(".a-alert-heading");this._$content=this._$element.find(".a-alert-content")},mixin:["show","hide","size","isEmpty"],heading:function(b){if("undefined"===typeof b)return this._$heading.text();this._$heading.length?this._$heading.text(b):this._$heading= +m.clone().text(b).insertBefore(this._$content);return this},removeHeading:function(){this._$heading.remove();this._$heading=l();return this},text:function(b){if("undefined"===typeof b)return this._$content.text();this._$content.text(b);return this},html:function(b){if("undefined"===typeof b)return this._$content.html();this._$content.html(b);return this},type:function(h){-1===b.indexOfArray(f,h)&&p.error("{API} Alert type must be one of [error, success, warning, info].","API","alert");this._$element.each(function(a, +b){a=l(b);b="a-alert-";a.hasClass("a-alert-inline")?(b+="inline-",a.removeClass(e)):a.removeClass(g);a.addClass(b+h)});return this}});return function(b,a){return new r(b,a)}});"use strict";p.when("jQuery","a-component","a-form-controls-api").register("a-checkbox",function(b,l,h){var f=h.setCheckboxState,g=l.create({_componentName:"checkbox",init:function(b,f){this._super(b,f);this._$element=this._$element.closest(".a-checkbox");this._$input=this._$element.find("[type\x3dcheckbox]")},mixin:["show", +"hide","size","isEmpty"],check:function(b){b=void 0===b?!0:b;this._$element.each(function(){f(this,b)});return this},uncheck:function(){return this.check(!1)},toggleChecked:function(){this._$element.each(function(){h.toggleCheckboxState(this)});return this},isChecked:function(){for(var b=0,f=this._$input.length;b m)return 1}return 0}}});"use strict";p.when("A","3p-promise","load").register("a-pcv",function(b,l){var h;return{getData:function(){h||(h=new l(function(b,g){var e=m.pcv.AmazonUI;e?(document.documentElement.setAttribute("data-aui-version",e),b(e)):g(Error("Package closure version of AmazonUI is not found on the page"))})); +return h}}})}); +/* ******** */ +(function(h){var f=window.AmazonUIPageJS||window.P,m=f._namespace||f.attributeErrors,d=m?m("AmazonUIBaseJS@declarative","AmazonUI"):f;d.guardFatal?d.guardFatal(h)(d,window):d.execute(function(){h(d,window)})})(function(h,f,m){"use strict";h.when("jQuery","a-util","a-events","a-constants","prv:a-guard","prv:csa-logger").register("a-declarative",function(d,l,h,n,f,m){function q(a){var c=d(a.currentTarget),b=d(a.target);if("submit"===a.type){var e=b.closest("form");e.length&&(b=e)}if(e=c.data("action"))a= +{$target:b,$currentTarget:c,targetTag:b.prop("tagName").toLowerCase(),type:a.type,$event:a,$declarativeParent:c},t(e,a)}function t(a,c){var b=c.$event,e=c.$target,g=c.$currentTarget,d=c.type;a=a.split(" ");l.each(a,function(a){var k=r[a]||{},p=g.data(a),f=l.extend({},c,{action:a,data:p});a="a:declarative:"+a;var m=a+":"+d;h.trigger(a,f);h.trigger(m,f);f=!1;p?f=!!p.allowLinkDefault:k&&(f=!!k.allowLinkDefault);"click"!==b.type||f?k=!1:(k=e.closest("a"),k=k.length&&("#"===k[0].href||b.currentTarget=== +k[0]||k.parent(".a-declarative").length));k&&b.preventDefault()})}var r={};d(document).delegate(".a-declarative",n.constants.declarativeEvents,q);d(document).delegate(".a-gesture","tap swipe swipe-horizontal swipe-vertical pan-horizontal pan-vertical doubleTap",q);n=function(){switch(arguments.length){case 2:var a=arguments[0];var c=arguments[1];break;case 3:a=arguments[0];var b=arguments[1];c=arguments[2];break;case 4:a=arguments[0];b=arguments[1];var d=arguments[2];c=arguments[3]}if(a){"string"=== +typeof a&&(a=l.trim(a).split(" "));var g=this;l.each(a,function(a){var e="a:declarative:"+a;r[a]=d||{};b?(b="string"===typeof b?l.trim(b).split(" "):b,l.each(b,function(b){h.on.call(g,e+":"+b,function(){return f.guardTimeFn(g,c).apply(this,arguments)});"click"!=b&&"swipe"!=b||m.declarative(a,b)})):h.on.call(g,e,c)})}};n.create=function(a,c,b){var e=a.jquery&&a.length?a:d(a);if(e.length&&c){var g=e.data("action");e.data("action",g?g+" "+c:c).data(c,b?b:{});e.addClass("a-declarative")}return a};n.remove= +function(a,c){var b=a.jquery&&a.length?a:d(a);if(!b.length)return a;var e=b.data("action");if(!e)return a;var g=e.split(" ");c?(c=c.split(" "),l.each(c,function(a){var c=l.indexOfArray(g,a);0<=c&&(g.splice(c,1),b.data(a,null))})):(l.each(g,function(a){b.data(a,null)}),g=[]);g.length?b.data("action",g.join(" ")):b.data("action",null).removeClass("a-declarative");return a};return{declarative:n}});h.register("prv:csa-logger",function(){return{declarative:function(d,f){},element:function(d,f){}}})}); +/* ******** */ +(function(f){var e=window.AmazonUIPageJS||window.P,n=e._namespace||e.attributeErrors,a=n?n("AmazonUIBaseJS@preload","AmazonUI"):e;a.guardFatal?a.guardFatal(f)(a,window):a.execute(function(){f(a,window)})})(function(f,e,n){"use strict";f.when("3p-promise","a-analytics","a-util","prv:a-preload-queue","prv:a-preload-strategies").register("a-preload",function(a,e,h,k,f){function m(){return new a(function(a){setTimeout(a,2500)})}function p(d,b){var p=Date.now();b=f.getStrategy(d,b)(d,b);var g=a.race([b.promise, +m()]).then(function(){e.increment("preload_fulfilled");return{url:d,success:!0,duration:Date.now()-p}},function(g){e.increment("preload_failed");return{url:d,success:!1,reason:g}});b.teardown&&g.then(b.teardown);return g}function l(d,b){if("string"===typeof d){if(!d.trim())return a.resolve();e.increment("preload_asks");return k(b).then(function(a){return p(d,b).then(a)})}return h.isArray(d)?a.all(d.map(function(a){return l(a,b)})):a.reject("not an URL or URL list")}return{preload:l}});f.when("3p-promise").register("prv:a-preload-queue", +function(a){function e(){if(h){var a=(k.length?k:m?q:[]).pop();a&&(h--,a())}}var h=5,k=[],q=[],m=!1;f.when("afterLoad").execute(function(){m=!0;for(var a=h;0=this._$accessibleElement.length&&(this._$accessibleElement=this._$element.filter("[role\x3d'radio']"))},mixin:"show hide toggle isEmpty size on off trigger".split(" "),enable:function(){this._$element.removeClass("a-button-disabled");this._$coreFormElement.prop("disabled", +!1);this._$coreLinkElement.unbind("click",e);this._$coreLinkElement.removeAttr("aria-disabled");return this},disable:function(){this._$element.addClass("a-button-disabled").removeClass("a-button-focus");this._$coreFormElement.prop("disabled",!0);this._$coreLinkElement.click(e);this._$coreLinkElement.attr("aria-disabled","true");return this},isEnabled:function(){return!this._$element.hasClass("a-button-disabled")},setStatus:function(a){var b=this._$element,e=[null,"normal","selected","disabled","error", +"inactive"],k=0>d.indexOfArray(e,a),m="radio"===this._$accessibleElement.attr("role");if(k)return c.error(a+" is not a valid status"),!1;d.each(e,function(a){b.removeClass("a-button-"+a)});this._$coreFormElement.prop("disabled","disabled"===a);this._$accessibleElement.attr("aria-checked",function(k,b){return m?"selected"===a:b});null!==a&&b.addClass("a-button-"+a);return this},text:function(a){if(!(1>this._$contentElement.length)){if("undefined"===typeof a)return this._$contentElement.text();this._$contentElement.text(a); +return this}}});return function(a,b){return new h(a,b)}});"use strict";c.when("A","a-component").register("a-toggle-button",function(d,c){function e(a){a.preventDefault()}function h(a){d.each(b,function(b){a._$element.removeClass(b)},a)}function a(a){return 0===a._$element.length||0===a._$coreFormElement.length}var b=["a-button-selected","a-button-focus"],f=c.create({_componentName:"toggleButton",init:function(a,b){this._super(a,b);this._$element=this._$element.filter(".a-button");this._$coreFormElement= +this._$element.find(".a-button-inner").find("button,input");this._$coreLinkElement=this._$element.find(".a-button-inner a");this._$accessibleElement=this._$element.children(".a-button-inner").find('[role\x3d"radio"]');0>=this._$accessibleElement.length&&(this._$accessibleElement=this._$element.filter("[role\x3d'radio']"))},name:function(){return this._$coreFormElement.attr("name")},enable:function(){this._$element.removeClass("a-button-disabled");this._$coreFormElement.prop("disabled",!1);this._$coreLinkElement.unbind("click", +e);return this},disable:function(){h(this);this._$element.addClass("a-button-disabled");this._$coreFormElement.prop("disabled",!0);this._$coreLinkElement.click(e);return this},setAvailable:function(){this._$element.removeClass("a-button-unavailable");return this},setUnavailable:function(){this._$element.addClass("a-button-unavailable");return this},isEnabled:function(){return!a(this)&&!this._$element.hasClass("a-button-disabled")},setSelected:function(){!a(this)&&this.isEnabled()&&(this._$element.addClass("a-button-selected a-button-focus"), +this._$accessibleElement.attr("aria-checked","true"));return this},setUnselected:function(){h(this);this._$accessibleElement.attr("aria-checked","false");return this},isSelected:function(){return!a(this)&&this._$element.hasClass("a-button-selected")},isAvailable:function(){return!a(this)&&!this._$element.hasClass("a-button-unavailable")}});return function(a,b){return new f(a,b)}});"use strict";c.when("A","a-component","a-toggle-button").register("a-toggle-button-group",function(d,c,e){var f=c.create({_componentName:"toggleButtonGroup", +init:function(a,b){this._super(a,b);this._$toggleGroupElement=this._$element.filter(".a-button-group, .a-button-toggle-group").eq(0);this._$toggleGroupName=(a=this._$toggleGroupElement.data("a-button-group"))?a.name:g},name:function(){return this._$toggleGroupName},getToggleButtonByName:function(a){return this.getToggleButtonBySelector(".a-button:has([name\x3d"+a+"])")},setSelected:function(a){a=this.getToggleButtonBySelector(a);a.isEnabled()&&(this.getSelected().setUnselected(),a.setSelected()); +return this},getSelected:function(){return this.getToggleButtonBySelector(".a-button.a-button-selected")},getToggleButtonBySelector:function(a){return e(this._$toggleGroupElement.find(a))}});return function(a,b){return new f(a,b)}})}); +/* ******** */ +(function(c){var e=window.AmazonUIPageJS||window.P,f=e._namespace||e.attributeErrors,a=f?f("AmazonUIMeter","AmazonUI"):e;a.guardFatal?a.guardFatal(c)(a,window):a.execute(function(){c(a,window)})})(function(c,e,f){c.when("A","ready").register("a-meters",function(a){var b=a.$;if(document.getElementsByClassName){var c=function(a){a.removeClass("a-meter-unfilled").addClass("a-meter-filled")};b(".a-meter-bar").not(".a-manual-animation").each(function(){var d=b(this);a.onScreen(d,0)||d.addClass("a-meter-unfilled")}); +b("body").addClass("a-meter-animate");a.on("resize orientationchange scroll",function(d){b(".a-meter-unfilled").each(function(){var d=b(this);a.onScreen(d,0)&&c(d)})});a.on("a:popover:afterShow",function(a){"ajax"!==a.popover.currentDataStrategy&&(a=a.popover.$popover.find(".a-meter-unfilled"),a.length&&c(a))});a.on("a:popover:ajaxContentLoaded",function(d){var b=d.popover.$popover.find(".a-meter-bar").not(".a-manual-animation");b.length&&(b.addClass("a-meter-unfilled"),a.delay(function(){c(b)},17))})}})}); +/* ******** */ +(function(c){var d=window.AmazonUIPageJS||window.P,e=d._namespace||d.attributeErrors,b=e?e("AmazonUIFilter","AmazonUI"):d;b.guardFatal?b.guardFatal(c)(b,window):b.execute(function(){c(b,window)})})(function(c,d,e){c.when("A").register("a-filter",function(b){function c(a){a.attr("data-a-selected","true").attr("aria-pressed","true")}function d(a){a.attr("data-a-selected","false").attr("aria-pressed","false")}function e(a){return{$filters:a,filter:function(a){return e(this.$filters.filter(a))},pills:function(){return this.filter("[data-a-type\x3d'pill']")}, +dropdowns:function(){return this.filter("[data-a-type\x3d'dropdown']")},buttons:function(){return this.filter("[data-a-type\x3d'button']")},selected:function(){return this.filter("[data-a-selected\x3d'true']")},deselected:function(){return this.filter("[data-a-selected\x3d'false']")},enabled:function(){return this.filter(":not([disabled])")},disabled:function(){return this.filter("[disabled]")},select:function(){var a=this.$filters.filter("[data-a-selected\x3d'false']");c(a);g(a);return this},deselect:function(){var a= +this.$filters.filter("[data-a-selected\x3d'true']");d(a);g(a);return this},toggle:function(){var a=this.$filters.filter("[data-a-selected\x3d'false']"),b=this.$filters.filter("[data-a-selected\x3d'true']");c(a);d(b);g(this.$filters);return this},enable:function(){this.$filters.prop("disabled",!1);return this},disable:function(){this.$filters.prop("disabled",!0);return this},show:function(){this.$filters.attr("data-a-hidden","false");return this},hide:function(){this.$filters.attr("data-a-hidden", +"true");return this},setText:function(a){this.$filters.find("[data-a-selector\x3d'user-content']").text(a);return this},getSize:function(){return this.$filters.size()},isEmpty:function(){return 0===this.getSize()},allSelected:function(){var a=!0;this.$filters.each(function(){if("true"!==f(this).attr("data-a-selected"))return a=!1});return a},anySelected:function(){var a=!1;this.$filters.each(function(){if("true"===f(this).attr("data-a-selected"))return a=!0,!1});return a},getName:function(){return this.$filters.attr("name")}, +getValue:function(){return this.$filters.attr("value")}}}function g(a){var c={};a.each(function(){var a=f(this),b=a.closest("[data-a-component\x3d'filter-group']").attr("data-a-name");b&&(c[b]=f.merge(c[b]||[],a))});b.each(c,function(a,c){b.trigger("a:filter:group:"+c+":change",h(a))})}function k(a){a=f(a).find("[data-a-component\x3d'filter']");return e(a)}function h(a){a=f(a).filter("[data-a-component\x3d'filter']");return e(a)}var f=b.$;b.declarative("a-filter-pill-toggle","click",function(a){a= +a.$target.closest("[data-a-component\x3d'filter']");h(a).toggle()});return{within:k,inGroup:function(a){return k("[data-a-component\x3d'filter-group'][data-a-name\x3d'"+a+"']")},get:h}})}); +/* ******** */ +(function(d){var g=window.AmazonUIPageJS||window.P,f=g._namespace||g.attributeErrors,a=f?f("AmazonUIFont","AmazonUI"):g;a.guardFatal?a.guardFatal(d)(a,window):a.execute(function(){d(a,window)})})(function(d,g,f){d.when("jQuery","A","3p-promise").register("a-fonts",function(a,d,l){function m(a,d){var b=e&&e[a]?e:d;return function(){return b[a].apply(b,arguments)}}var h=[],b=a("body"),f=function(){return new l(function(a,b){var e=g.setInterval(function(){d.reduce(h,function(a,b){return a&&"loaded"=== +b.status},!0)&&(a(),clearInterval(e))},50)})}(),k={load:function(d){return new l(function(e,f){var c={variant:d,status:"unloaded"};h.push(c);c.$loader=a("\x3cspan\x3e.\x3c/span\x3e",{"class":"aok-hidden"}).css("font",c.variant).appendTo(b);c.status="loading";c.$checker=a("\x3cspan\x3e.\x3c/span\x3e",{"class":"aok-hidden"}).appendTo(b);c.intervalId=g.setInterval(function(){c.$checker.css("font",c.variant+', Consolas, "Courier New", Courier, monospace');var a=c.$checker.width(),b=c.$checker.height(); +c.$checker.css("fontFamily",'Consolas, "Courier New", Courier, monospace');if(c.$checker.width()!==a||c.$checker.height()!==b)e(c.variant),c.status="loaded",c.$loader.remove(),c.$checker.remove(),clearInterval(c.intervalId)},50)})},check:function(a){d.each(h,function(b){if(b.variant===a)return"loaded"===b.status});return!1},ready:f},e=document.fonts;e&&e.ready&&(f=e.ready.then?e.ready:e.ready.apply(e));return{load:m("load",k),check:m("check",k),ready:f}});"use strict";d.when("A","a-fonts","prv:a-capabilities", +"load").register("prv:a-custom-font-loader",function(a,d,f){return function(g,h){!f.isUCBrowser&&a.localStorage&&-1===a.indexOfArray((a.localStorage.getItem("a-font-class")||"").split(" "),g)&&(d.ready.then(function(b){b=a.localStorage.getItem("a-font-class")||"";b+=(b.length?" ":"")+g;a.localStorage.setItem("a-font-class",b)}),a.each(h,function(a){d.load(a)}))}});"use strict";d.when("prv:a-custom-font-loader").execute("a-ember-loader",function(a){a("a-ember","1em Amazon Ember;bold 1em Amazon Ember;200 1em Amazon Ember;500 1em Amazon Ember;italic 1em Amazon Ember;italic bold 1em Amazon Ember;italic 200 1em Amazon Ember;italic 500 1em Amazon Ember".split(";"))})}); +/* ******** */ +(function(n){var E=window.AmazonUIPageJS||window.P,z=E._namespace||E.attributeErrors,e=z?z("AmazonUICarousel","AmazonUI"):E;e.guardFatal?e.guardFatal(n)(e,window):e.execute(function(){n(e,window)})})(function(n,E,z){n.declare("a-carousel-constants",{ANIMATING:"animating",ANIMATION_SPEED:"animation_speed",AUTO_ADJUST_HEIGHT:"auto_adjust_height",CIRCULAR:"circular",CURRENT_PIXEL:"px",CURRENTLY_WRAPPING:"currentlyWrapping",DELAY_TIME:"delay_time",ELEMENT_CSS_CLASS:"elementCssClass",FETCHED_ITEMS:"fetchedItems", +FIRST_VISIBLE_ITEM:"firstVisibleItem",HEIGHT_ANIMATION_SPEED:"height_animation_speed",HIDE_OFF_SCREEN:"hide_off_screen",INIT_EVENTS:"a:pageUpdate beforeReady",LOADING:"loading",MIN_GUTTER:"minimum_gutter_width",NAME:"name",NO_TRANSITION:"no_transition",PAGE_NUMBER:"pageNumber",PAGE_SIZE:"pageSize",PEEK_GRADIENT:"peek_gradient",PEEK_PERCENTAGE:"peek_percentage",PEEK_WIDTH:"peek_width",SET_SIZE:"set_size",SHOW_PARTIAL_NEXT:"show_partial_next",SPRINGINESS:"springiness",STATIC_LOADER_CSS_CLASS:"staticLoaderCssClass", +TOTAL_PAGES:"totalPages",TOUCH_EASING:"touch_easing",TRANSITION_STRATEGY:"transitionStrategy",DISPLAY_STRATEGY:"displayStrategy",WRAP_EASING:"wrap_easing",TRANSITION_SLIDE_CIRCULAR_FIRST_CARD_IDX:"transitionSlideCircularFirstCardIndex",NEXT_REQUEST_SIZE:"next_request_size",LOADING_THRESHOLD_PIXELS:"loading_threshold_pixels"});"use strict";n.when("jQuery").register("a-carousel-utils",function(e){function m(f){return"string"===typeof f}function g(f){return f&&f.nodeType!==z}function d(f){return""=== +f?"\x3cdiv\x3e\x3c/div\x3e":f?m(f)||g(f)?f:d(f.content):null}function k(f){f&&(m(f)||g(f)?f=!0:f.content=k(f.content));return f}return{addElementToDom:function(f,d){if(d){if(m(d))f.html(d);else if(g(d))if(e(d).hasClass("a-carousel-card-fragment")){var c=e(d).clone();f.empty().append(c.contents())}else f.empty().append(d);!0!==d&&f.removeClass("a-carousel-card-empty")}},clearElementFromItem:k,getElementFromItem:d,isElement:g,isString:m}});"use strict";n.register("a-carousel-circular-utils",function(){function e(e){var d= +0 e&&(e=k+e);return e},relativeIndexFromIndex:function(e, +d,k){var f=1;if(0 d?f=e-d+1:e =this.items[0].width?160:this.items[0].width}};g.measure=function(f){var h=this.dom.$carousel,c=this.dom.$viewport,b={};f&&(f=f.split(" "));if(!f||-1 e&&(e=1);a.setAttr("pageNumber",e);a.setAttr("totalPages",Math.ceil(a.getAttr("set_size")/b));l=a.getAttr("ajax");b>c&&(l&&l.prefetch_next_page?a.strategies.ajax.wantNextPage(a):a.strategies.ajax.wantCurrentPage(a))});a.onChange("set_size", +function(b,e){var l=a.getAttr("pageSize"),c=a.getAttr("fetchedItems");a.setAttr("totalPages",Math.ceil(b/l));b a.getAttr("set_size"))return c.ajax.init(a),!1;a.measure();e.each(a.strategies,function(b){b.init(a)});c=a.getAttr("pageSize");d=a.getAttr("set_size");a.setAttr("totalPages",Math.ceil(d/c));p(a);a.setAttr("isInTab",0 a.getAttr("pageNumber")&&a.dom.$container.find(".a-carousel-restart-container").hide(), +a.getAttr(d.NO_TRANSITION)||a.initTouchHandling(),!0):!1};return e}}var h;f.prototype=new g;return f.prototype.constructor=f});"use strict";n.when("A","a-carousel-desktop","a-carousel-mobile").register("a-carousel-classes",function(e,m,g){return{desktop:m,mobile:g,"default":e.capabilities.mobile||e.capabilities.tablet?"mobile":"desktop"}});"use strict";n.when("A","jQuery","p-detect","a-carousel-constants").register("a-carousel-stretchygoodness",function(e,m,g,d){function k(a,b,c,d){a.getAttr("show_partial_next")&& +!a.getAttr("force_minimum_gutter_width")&&(b-=c/10);a=a.getAttr("minimum_gutter_width");var l=0,p=!0;for(b-=a;0b&&l--;return e.isFiniteNumber(l)&&0 f&&(d=f);b-=c*d;a.getAttr("show_partial_next")?(a=b-l*(d+1),h&&(a+=l),a/=c,b-=c*(.5d&&(d=c[f].outerHeight||c[f].height);d>b&&(a.updateDimensionsCache({viewport:{height:d,outerHeight:d}}),a.setAttr("maxHeight", +d),1===b?a.dom.$viewport.height(d):e.animate(a.dom.$viewport,{height:d},a.getAttr("height_animation_speed"),"linear"))}else a.dom.$viewport.css("height","")}function c(a){a.onChange("pageNumber",function(){a.getAttr("hide_off_screen")&&a.dom.$carousel.children("li").css("visibility","")});a.onChange("pageSize",function(b,c){b>c&&h(a)});a.onChange("loading",function(b){b||h(a)});a.onChange("firstVisibleItem",function(){h(a)});a.onChange("animating",function(b){if(!b&&a.getAttr("hide_off_screen")){var c= +a.getAttr("firstVisibleItem")-1,d=c+a.getAttr("pageSize")-1;a.getAttr("show_partial_next")&&d++;a.dom.$carousel.children("li").each(function(a,b){a=a>=c&&a<=d;m(b).css("visibility",a?"":"hidden")})}});a.onChange("single_page_align minimum_gutter_width",function(){b(a)});a.onChange("minimum_gutter_width",function(){b(a)})}function b(a){var b=a.getDimensions(),c=b.viewport.width;b=b.getFirstCardWidth();var d=a.getAttr("minimum_gutter_width"),l=a.getAttr("set_size"),h=a.getAttr("first_item_flush_left"), +g=k(a,c,b,h),m=f(a,c,b,g,d,l,h);a.setAttr("currentGutter",m);a.setAttr("pageSize",g);var w=a.dom.$carousel,n=w.children("li");d=n.length;var t=a.getAttr("totalPages"),A=a.getAttr("pageNumber"),C=a.getAttr("firstVisibleItem"),B=(A-1)*g+1;A>t?(C=(t-1)*g+1,a.setAttr("pageNumber",t),a.setAttr("firstVisibleItem",C)):C!==B&&(t=Math.ceil(C/g),C=(t-1)*g+1,a.setAttr("pageNumber",t),a.setAttr("firstVisibleItem",C));var F=C-1,G=F+g-1;a.getAttr("show_partial_next")&&G++;var H=a.getAttr("hide_off_screen"),I=m+ +"px",J=b+"px",z;n.each(function(a,b){z=!H||a>=F&&a<=G;b.style[e.capabilities.rtl?"marginRight":"marginLeft"]=h&&0===a?0:I;b.style.visibility=z?"":"hidden";b.style.width=J});var D;a.getAttr("first_item_flush_left")?(m=n.first().outerWidth(!0),1 =l?(t=c,A=a.getAttr("single_page_align"),w.toggleClass("a-text-right","right"===A),w.toggleClass("a-text-center","center"===A),"center"===A&&n.first().css("margin-left", +0)):w.removeClass("a-text-right a-text-center");t=g>=l?c:t;w.css("width",t+"px");c={carousel:{width:t,outerWidth:w.outerWidth()},items:[]};for(l=0;l b&&(c.setAttr("maxHeight",a),g.capabilities.transition?1=== +b?c.dom.$viewport.height(a):e.animate(c.dom.$viewport,{height:a},c.getAttr("height_animation_speed"),"linear"):c.dom.$viewport.height(a),c.updateDimensionsCache({viewport:{height:a,outerHeight:a}}))}else c.dom.$viewport.css("height","")}function f(c){c.onChange("animating",function(b){b||k(c)});c.onChange("loading",function(b){b||k(c)});c.onChange("pageSize",function(b,a){c.dom.$carousel.children("li").slice(b).remove();if(b>a){a=c.getAttr("set_size");var e=c.getDimensions().getFirstCardWidth(),f= +c.getAttr("currentGutter"),h=c.getAttr("fetchedItems"),l=c.getAttr("firstVisibleItem")-1,g=c.dom.$carousel.children("li"),v=document.createDocumentFragment();if(m.isArray(h)){for(var q=g.length;q=a&&g.removeClass("a-carousel-card-empty"); +v.appendChild(g[0])}c.dom.$carousel.append(v)}k(c)}});c.onChange("set_size",function(b,a){var d=c.getAttr("pageNumber"),f=c.getAttr("totalPages"),g=c.dom.$carousel.children("li");d===f&&b>a&&(g.length&&c.dom.$carousel.children("li").each(function(a,b){e.trim(b.innerHTML)||(b.className+=" a-carousel-card-empty",b.innerHTML=c.getStaticLoader())}),0===a&&h(c))});c.onChange("single_page_align minimum_gutter_width",function(){h(c)});c.onChange("minimum_gutter_width",function(){h(c)})}function h(c){var b= +c.getDimensions(),a=b.viewport.width,d=b.getFirstCardWidth(),f=c.getAttr("minimum_gutter_width");b=c.getAttr("set_size");var h=c.getAttr("minimum_gutter_width");c.getAttr("set_size");h=Math.max(Math.floor(a/(d+h)),1);h=e.isFiniteNumber(h)?h:1;var l=h;"stretch"===c.getAttr("single_page_align")&&l>b&&(l=b);l=Math.ceil((a-d*l)/(l+1));e.isFiniteNumber(l)||(l=f);var g=l;c.setAttr("currentGutter",g);c.setAttr("pageSize",h);l=c.dom.$carousel;var k=l.children("li");f=k.length;d+=g;var m=f*d,w=Math.min(h, +b);c.dom.$carousel.children("li").slice(w).remove();k.css("margin-left",g+"px");h>=b?(m=a,a=c.getAttr("single_page_align"),l.toggleClass("a-text-right","right"===a),l.toggleClass("a-text-center","center"===a),"center"===a&&k.first().css("margin-left",0)):l.removeClass("a-text-right a-text-center");for(a={carousel:{width:m,outerWidth:l.outerWidth()},items:[]};f--;)a.items.push({outerWidth:d});c.updateDimensionsCache(a);c.triggerEvent("repaint")}return{repaint:h,init:function(c){var b=c.getAttr("minimum_gutter_width"); +b||(b=15,c.setAttr("minimum_gutter_width",b));c.setAttr("currentGutter",b);b=c.getAttr("height_animation_speed");e.isFiniteNumber(b)||c.setAttr("height_animation_speed",200);f(c);h(c);b=c.getDimensions();c.dom.$container.find(".a-carousel-left, .a-carousel-right, .a-carousel-viewport").css("height",Math.max(b.viewport.height,b.items[0]?b.items[0].height:0)+"px");b=c.getAttr("firstVisibleItem");1d?-1:1:isNaN(d)?NaN:0:NaN}function f(d,b){d.getAttr("pageNumber");d.getAttr("pageSize");var a=d.getAttr("firstVisibleItem"),c=d.getAttr("delay_time"),f=d.dom.$carousel.children("li"),h=f.filter(".a-carousel-card-empty"); +h.length&&d.setAttr("loading",!0);h.each(function(l,p){var r=m(p);p=f.index(p)+a-1;var k=b[p];k&&e.delay(function(){g.addElementToDom(r,g.getElementFromItem(k));l===h.length-1&&d.setAttr("loading",!1)},0+c)})}function h(d,b,a){a=a||{};var c=d.getAttr("pageNumber");if(b!==c){var f=d.getAttr("set_size"),h=d.getAttr("totalPages"),l=d.getAttr("circular"),r=d.getAttr("pageSize"),m=a.delayTime||d.getAttr("delay_time"),q=k(a.direction)||NaN;!l&&1>b?b=1:!l&&b>h?b=h:l&&1>b?b=h:l&&b>h&&(b=1);q||(q=cn||1===q&&n>=r)d.setAttr("responsiveTimerId",z),d.setAttr("animating",!1);else{var b=d.dom.$carousel.children("li").eq(n),c=d.getAttr("fetchedItems")[a];c?g.addElementToDom(b,g.getElementFromItem(c)):a =c.length){b.setAttr(d.LOADING,!0);for(var l=b.dom.$carousel.children("li"),r,k,m= +a.length;m--;)if(k=a[m],null===k&&p.push(m),k&&!e.equals(k,c[m])&&!0!==k&&!0!==k.content){var n=g.getElementFromItem(k);r=l.eq(m);r.length&&(g.addElementToDom(r,n),h[m]={width:r.outerWidth(),outerWidth:r.outerWidth(!0),height:r.outerHeight(),outerHeight:r.outerHeight(!0)},a[m]=g.clearElementFromItem(k))}p.length&&(e.each(p,function(b){l.eq(b).remove();a.splice(b,1)}),b.setAttr(d.SET_SIZE,b.getAttr(d.SET_SIZE)-p.length),b.triggerEvent("repaint"))}b.setAttr(d.FETCHED_ITEMS,a);b.updateDimensionsCache({items:h}); +b.setAttr(d.LOADING,!1)}}var h=e.capabilities.touch?2E3:3E3,c=e.capabilities.rtl?-1:1;return{wrapToFirst:function(b){var a=b.getAttr(d.PAGE_SIZE),e=b.getDimensions().getFirstCardWidth(),c=this;b.gotoPixel(a*e*-1,{animationDuration:0,callback:function(){b.setAttr(d.CURRENTLY_WRAPPING,!1);c.gotoPage(b,1)}})},wrapToLast:function(b){b.getAttr(d.PAGE_SIZE);var a=b.getAttr(d.TOTAL_PAGES),e=this,c=b.getDimensions().carousel.width;b.gotoPixel(c,{animationDuration:0,callback:function(){b.setAttr(d.CURRENTLY_WRAPPING, +!1);e.gotoPage(b,a)}})},gotoPage:function(b,a,e){e=e||{};(void 0===e.animationDuration||0 a?(a=1,e.animationDuration=Math.pow(b.getAttr(d.ANIMATION_SPEED)*b.getAttr(d.SPRINGINESS))):!f&&a>c&&(a=c,e.animationDuration=Math.pow(b.getAttr(d.ANIMATION_SPEED),b.getAttr(d.SPRINGINESS)));this.gotoIndex(b,b.getAttr(d.PAGE_SIZE)*(a-1)+1,e)},gotoIndex:function(b, +a,c){c=c||{};(void 0===c.animationDuration||0 a){if(f){h=-1*k;var p=function(){g&&g();l.wrapToLast(b)}}}else a>b.getAttr(d.SET_SIZE)?f&&(h=b.getAttr(d.CURRENT_PIXEL)+ +k,p=function(){g&&g();l.wrapToFirst(b)}):h=b.getItemOffset(a);p?(b.setAttr(d.CURRENTLY_WRAPPING,!0),c.callback=p,c.easingFunction=c.easingFunction||b.getAttr(d.WRAP_EASING),c.animationSpeed=1.3*(e.isFiniteNumber(c.animationSpeed)?c.animationSpeed:b.getAttr(d.ANIMATION_SPEED))):c.callback=g;!1!==h&&this.gotoPixel(b,h,c)},gotoPixel:function(b,a,c){var f=b.getAttr(d.CURRENT_PIXEL);if(a!==f){c=c||{};var g=c.easingFunction||"ease-out",l=c.callback;b.getViewportWidth();if(void 0!==c.animationDuration)var h= +c.animationDuration;else h=e.isFiniteNumber(c.animationSpeed)?c.animationSpeed:b.getAttr(d.ANIMATION_SPEED),f=Math.abs(a-f),h=0===h?0:Math.floor(f/h*1E3);0 c*a.velocityX,k=f;l&&h a&&k===l||0a?b.gotoNextPage(f):b.gotoPrevPage(f)):(!h&&(h=b.getAttr(d.SPRINGINESS),0>g&&0 a.touchDeltaX)&&(l=Math.pow(Math.abs(a.touchDeltaX),h),g=0>=g?-1*l:f+l),b.gotoPixel(g,{easingFunction:b.getAttr(d.TOUCH_EASING),animationDuration:0,silent:!0}))}},init:function(b){var a=b.getAttr(d.ANIMATION_SPEED); +e.isFiniteNumber(a)||b.setAttr(d.ANIMATION_SPEED,h);void 0===b.getAttr(d.WRAP_EASING)&&b.setAttr(d.WRAP_EASING,"linear");k(b);b.onChange(d.FETCHED_ITEMS,function(a,d){f(b,a,d)});b.onChange(d.SET_SIZE,function(a,d){a>d&&k(b)})}}});"use strict";n.when("A","a-carousel-utils","a-carousel-circular-utils","a-carousel-constants").register("a-carousel-transition-slidecircular",function(e,m,g,d){function k(a){var b=a.dom.$carousel.children("li").length,f=a.getAttr(d.SET_SIZE),l=f-b,g=c(a,b);0 b?(b=a-b,a=d-b):(a=b-a,b=d-a);c.direction=a<=b?v.CLOCKWISE:v.COUNTER_CLOCKWISE; +c.quantity=Math.min(a,b);return c}function c(b,d){return b.dom.$carousel.children("li").eq(a(b,d)-1)}function b(a,b){var c=Math.floor(a.getAttr(d.PEEK_WIDTH)||0);return a.getItemOffset(b)-c}function a(a,b){b=b||1;var c=a.getAttr(d.TRANSITION_SLIDE_CIRCULAR_FIRST_CARD_IDX);a=a.getAttr(d.SET_SIZE);return g.relativeIndexFromIndex(b,c,a)}function p(b,f,l){if(b.getAttr(d.ANIMATING))b.once(d.ANIMATING,function(){p(b,f,l)});else{var g=b.getDimensions().items,h=Math.min(f.length,b.getAttr(d.SET_SIZE));if(!l|| +f.length>=l.length)b.setAttr(d.LOADING,!0),e.each(e.range(h),function(d){var h=d+1,k=f[d],B=c(b,h),t=k&&!(!0===k||!0===k.content);k&&!e.equals(k,l[d])&&B.length&&t&&(h=a(b,h),g[h]={width:B.outerWidth(),outerWidth:B.outerWidth(!0),height:B.outerHeight(),outerHeight:B.outerHeight(!0)},m.addElementToDom(B,m.getElementFromItem(k)),f[d]=m.clearElementFromItem(k))}),b.setAttr(d.LOADING,!1);b.setAttr(d.FETCHED_ITEMS,f);b.updateDimensionsCache({items:g})}}function u(a){var b={reached:!1,left:!1,right:!1}; +if(!(2 d&&k(a)});a.onChange(d.PEEK_WIDTH,function(b,c){b!==c&&(b=a.getAttr(d.FIRST_VISIBLE_ITEM),a.gotoIndex(b))})},afterInit:function(a){f(a,this);a.strategies.display.repaint(a);a.gotoPage(a.getAttr(d.PAGE_NUMBER))},gotoPage:function(a,b,c){c=c||{};var e=a.getAttr(d.TOTAL_PAGES);0q*f.velocityX;g=b(c,k?h+g:h-g);l=Math.abs(1E3*(k?l-g:l+g)/f.velocityX);k=1.2*e.viewport().width;x(c,0>q*f.touchDeltaX?"right":"left", +{animationDuration:Math.min(Math.max(l,300),k),easingFunction:c.getAttr(d.TOUCH_EASING)})},onPan:function(c,f){c.setAttr(d.ANIMATING,!0);var l=c.getAttr(d.PAGE_NUMBER),g=a(c,c.getAttr(d.FIRST_VISIBLE_ITEM));g=b(c,g);g=u(c).reached?g-q*f.touchDeltaX*.4:g-q*f.touchDeltaX;f.ended?(g={easingFunction:c.getAttr(d.TOUCH_EASING),animationSpeed:.95*e.viewport().width,silent:!0},Math.abs(f.touchDeltaX)>=.4*c.getViewportWidth()?x(c,0>q*f.touchDeltaX?"right":"left",g):c.gotoPage(l,g)):c.gotoPixel(g,{easingFunction:c.getAttr(d.TOUCH_EASING), +animationDuration:0,silent:!0})}}});"use strict";n.when("A","a-carousel-utils","a-carousel-constants").register("a-carousel-transition-freescroll",function(e,m,g){function d(a){p[a.__id]||(p[a.__id]=new u(a));return p[a.__id]}function k(b){for(var c=b.countItems(),d=[],f=0;f b){for(var e=0;e =d.length)for(var f=b.getItems(),l=c.length,h;l--;)(h=c[l])&&!e.equals(h,d[l])&&!0!==h&&!0!==h.content&&b.hasItem(f,l)&&(c[l]=b.insertFetchedItem(h,f,l));b.setAttr(g.FETCHED_ITEMS,c);a(b)}function c(a){a.attachScrollListener(function(){var c=a.hasEmptyCard();var d=a.getAttr("auto_adjust_height_freescroll"),e=a.getAttr("startIndexForHeightCheck"), +f=a.countItems();c||d&&e c.right&&(b.scrollLeft+=a.right-c.right)})}});var n={ajaxLock:!0,startIndexForHeightCheck:0,lastScrollPosition:-1,currentScrollPosition:-1,maxHeight:1};n[g.NO_TRANSITION]=!0;n[g.HIDE_OFF_SCREEN]=!1;n[g.AUTO_ADJUST_HEIGHT]=!1;n[g.HEIGHT_ANIMATION_SPEED]=200;return{gotoIndex:e.constants.NOOP,gotoNextpage:e.constants.NOOP,gotoPrevPage:e.constants.NOOP, +gotoPage:e.constants.NOOP,initAttrs:n,init:function(a){var l=d(a);l.showItems();l.autorotate();k(l);f(l);c(l);l.onChange(g.FETCHED_ITEMS,function(a,c){h(l,a,c);b(l)});e.on.resize(function(){b(l)})},afterInit:function(a){var c=d(a);e.delay(function(){c.setAttr("ajaxLock",!1);b(c)})},prepareFetchedItems:k,addEmptyCards:f,handleItemChanges:h,detectEmptyCardsLoadingThreshold:b,ATTR:{NEXT_REQUEST_SIZE:g.NEXT_REQUEST_SIZE,LOADING_THRESHOLD_PIXELS:g.LOADING_THRESHOLD_PIXELS,CURRENT_SCROLL_POSITION:"currentScrollPosition"}}}); +"use strict";n.when("A","jQuery","a-carousel-transition-slide","a-carousel-transition-swap","a-carousel-transition-freescroll","a-carousel-transition-slidecircular","a-carousel-constants").register("a-carousel-strategies-transition",function(e,m,g,d,k,f,h){m={};m[h.NO_TRANSITION]=!0;m[h.HIDE_OFF_SCREEN]=!1;m[h.AUTO_ADJUST_HEIGHT]=!1;return{slideHorizontal:g,swap:d,freeScroll:k,slideCircular:f,none:{gotoIndex:e.constants.NOOP,gotoNextPage:e.constants.NOOP,gotoPrevPage:e.constants.NOOP,gotoPage:e.constants.NOOP, +initAttrs:m,init:function(c){c.dom.$carousel.children("li").css("visibility","").attr("aria-hidden","false")}},"default":"slideHorizontal"}});"use strict";n.when("A").register("a-carousel-ajax-standard",function(e){function m(f,g,c,b){f.triggerEvent("beforeAjax",{url:g,params:c});e.get(g,{cache:!1,success:function(a){a=d(a,g);if(null===a)n.error("Invalid JSON returned to carousel from "+g+" - see http://tiny/c1mr5h0u for details.","a-carousel-ajax-standard","sendRequest");else{c.needSetSize&&(a&& +a.length||n.error("Carousel requires a set_size and none was returned by the fallback AJAX request at: "+g,"a-carousel-ajax-standard","sendRequest"),f.setAttr("set_size",a[0].setSize?a[0].setSize:a.length));for(var b=f.getAttr("fetchedItems"),h=f.getAttr("ajax"),k=[],l,m=a.length;m--;)l=a[m],null===l&&k.push(m),l&&(l.content||""===l.content?l.content=e.trim(l.content):l=e.trim(l)),b[c.offset+m]=l;h.remove_nulls&&h.id_list&&k.length&&(e.each(k,function(a){h.id_list.splice(c.offset+a,1)}),f.setAttr("ajax", +h));c.needSetSize&&f.init();f.setAttr("fetchedItems",b);f.setAttr("ajaxLock",!1);c.needSetSize&&f.getAttr("pageSize")>=b.length&&f.strategies.ajax.wantCurrentPage(f);f.triggerEvent("ajaxSuccess",{url:g,params:c})}},params:c,headers:b})}function g(d){var e=d.getAttr("requestTimer");e&&(clearTimeout(e),d.setAttr("requestTimer",null))}function d(d,g){return e.isArray(d)?d:d!==k&&null!==d&&!e.objectIsEmpty(d)&&d.hasOwnProperty("data")&&e.isArray(d.data)?d.data:null}var k;return{getItems:function(d,g, +c,b){var a=d.getAttr("ajax");d.setAttr("requestTimer",e.delay(m,a.fetch_delay,d,g,c,b))},wantNextPage:function(d){g(d);if(d.getAttr("ajax").prefetch_next_page){var e=d.getAttr("pageSize"),c=2*e;d.getAttr("show_partial_next")&&c++;this.want(d,(d.getAttr("pageNumber")-1)*e,c)}else this.wantCurrentPage(d)},wantPrevPage:function(d){g(d);if(d.getAttr("ajax").prefetch_next_page){var e=d.getAttr("pageSize"),c=2*e;d.getAttr("show_partial_next")&&c++;this.want(d,(d.getAttr("pageNumber")-2)*e,c)}else this.wantCurrentPage(d)}, +wantCurrentPage:function(d){g(d);var e=d.getAttr("pageSize"),c=d.getAttr("show_partial_next")?e+1:e;this.want(d,(d.getAttr("pageNumber")-1)*e,c)},want:function(d,e,c){if(!d.getAttr("ajaxLock")){g(d);var b=d.getAttr("ajax"),a=d.getAttr("set_size");if(b.url){var f=d.getAttr("fetchedItems"),h=b.id_list;h||(h=[]);var k=-1 c?d.strategies.ajax.wantNextPage(d):d.strategies.ajax.wantPrevPage(d)});d.onChange("loading",function(e){e||d.strategies.ajax.wantCurrentPage(d)})}}});"use strict";n.when("a-util").register("a-carousel-ajax-promise",function(e){function m(g,d){var k=g.getAttr("requestTimer");k&&clearTimeout(k);g.setAttr("requestTimer",e.delay(d,500))}return{getItems:function(g,d,k){m(g,function(){var f=g.getAttr("async_provider");f&&f(d,k).then(function(f){var c=g.getAttr("fetchedItems"); +e.each(f,function(b,a){c[d[a]]=b});g.setAttr("fetchedItems",c)})})},wantNextPage:function(e){var d=e.getAttr("pageSize"),g=(e.getAttr("pageNumber")-1)*d;this.want(e,g,2*d)},wantPrevPage:function(e){var d=e.getAttr("pageSize"),g=(e.getAttr("pageNumber")-2)*d;this.want(e,g,2*d)},wantCurrentPage:function(e){var d=e.getAttr("pageSize"),g=(e.getAttr("pageNumber")-1)*d;this.want(e,g,d)},want:function(g,d,k){d=Math.max(0,d);k=Math.min(d+k,g.getAttr("set_size"));for(var f=g.getAttr("fetchedItems"),h=[];d< +k;d++)f[d]||(h.push(d),f[d]=!1);if(h.length){var c,b=g.getAttr("ajax").id_list;b&&(c=e.map(h,function(a){return b[a]}));g.setAttr("fetchedItems",f,{silent:!0});this.getItems(g,h,c)}},init:function(e){},afterInit:function(g){g.strategies.ajax.wantCurrentPage(g);g.onChange("async_provider",e.once(function(){g.strategies.ajax.wantCurrentPage(g)}));g.onChange("pageNumber",function(d,e){d>e?g.strategies.ajax.wantNextPage(g):g.strategies.ajax.wantPrevPage(g)})}}});"use strict";n.when("A","a-carousel-ajax-standard", +"a-carousel-ajax-promise").register("a-carousel-strategies-ajax",function(e,m,g){return{standard:m,promise:g,none:{wantNextPage:e.constants.NOOP,wantPrevPage:e.constants.NOOP,wantCurrentPage:e.constants.NOOP,want:e.constants.NOOP,init:e.constants.NOOP},"default":"standard"}});"use strict";n.when("A","a-carousel-constants").register("a-carousel-accessibility-standard-desktop",function(e,m){function g(a){var b=a.dom.$carousel,c=b.children("li"),d=a.getAttr(m.PAGE_SIZE),e=a.getAttr(m.FIRST_VISIBLE_ITEM), +f=e-1,g=a.getAttr(m.TRANSITION_SLIDE_CIRCULAR_FIRST_CARD_IDX);if(a.getAttr(m.NO_TRANSITION))return c;if(c.length<=d)return b.children("li:not(:empty), li.a-carousel-card-empty");"slideCircular"===a.getAttr(m.TRANSITION_STRATEGY)&&(f=g-e-1,0===c.length%2&&--f);b=f=(f+2*c.length)%c.length;"peekCircular"===a.getAttr(m.DISPLAY_STRATEGY)&&--b;d=f+d;if("peekCircular"===a.getAttr(m.DISPLAY_STRATEGY)||a.getAttr(m.SHOW_PARTIAL_NEXT))d+=1;return c.slice(Math.max(b,0),Math.min(d,c.length))}function d(a,b,c, +d){var h=function(){var c=g(a);(b?c.first():c.last()).find("a, button, input, select, textarea, [tabindex]:not([tabindex\x3d'-1'])").not(":disabled").first().focus();e.delay(function(){f(a)},a.getAttr(m.PAGE_SIZE)*a.getAttr(m.DELAY_TIME)+50)};if(0===c||0===d)e.delay(h,0);else{var k=function(b){b||(h(),a.unbind(m.ANIMATING,k))};a.onChange(m.ANIMATING,k)}}function k(a){var c=a.dom.$carousel.children("li"),d=a.getAttr(m.TRANSITION_STRATEGY),e=a.getAttr(m.SET_SIZE),f=e?{"aria-setsize":e}:{};if("swap"=== +d){var g=a.getAttr(m.FIRST_VISIBLE_ITEM);c.each(function(a){var c=b(this);g+a>e?(c.removeAttr("aria-setsize"),c.removeAttr("aria-posinset")):(f["aria-posinset"]=g+a,c.attr(f))})}else c.each(function(a){f["aria-posinset"]=a+1;b(this).attr(f)})}function f(a){a=a.dom.$container;a.find(".a-carousel-accessibility-page-info").html(a.find(".a-carousel-page-count").text())}function h(a,b){if(!a.getAttr(m.NO_TRANSITION)){var c=a.dom.$carousel.children("li"),d=a.getAttr(m.TRANSITION_STRATEGY);a=a.getAttr(m.DISPLAY_STRATEGY); +c=c.not(b);b.attr("aria-hidden",!1);c.attr("aria-hidden",!0);if("slideCircular"===d&&"peekCircular"!==a||"slideHorizontal"===d)b.css("visibility","visible"),c.css("visibility","hidden")}}function c(a,b){if(!a.getAttr(m.CIRCULAR)){var c=a.dom.$container;c.find(".a-carousel-goto-prevpage").attr("aria-disabled",1===b?"true":"false");c.find(".a-carousel-goto-nextpage").attr("aria-disabled",b===a.getAttr(m.TOTAL_PAGES)?"true":"false")}}var b=e.$;return{init:function(a){var b=a.getAttr(m.NAME);k(a);h(a, +g(a));c(a,1);e.on("a:carousel"+(b?":"+b:"")+":repaint",function(){h(a,g(a))});a.onChange(m.SET_SIZE,function(b,c){k(a)});a.onChange(m.LOADING,function(b){a.getAttr(m.ANIMATING)||a.dom.$carousel.attr("aria-busy",(!!b).toString())});a.onChange(m.ANIMATING,function(b){a.getAttr(m.LOADING)||a.dom.$carousel.attr("aria-busy",(!!b).toString());!b&&a.getAttr(m.SET_SIZE)>a.getAttr(m.PAGE_SIZE)&&(b=a.getAttr(m.TRANSITION_STRATEGY),h(a,g(a)),"slide"!==b&&k(a))});a.onChange(m.PAGE_NUMBER,function(b){c(a,b);h(a, +a.dom.$carousel.children("li"))})},afterInit:function(a){f(a)},gotoPage:function(a,b,c){a.getAttr(m.NO_TRANSITION)||d(a,!0,b,c)},nextPage:function(a,b,c){a.getAttr(m.NO_TRANSITION)||d(a,!0,b,c)},prevPage:function(a,b,c){a.getAttr(m.NO_TRANSITION)||d(a,!1,b,c)}}});"use strict";n.when("A","a-carousel-constants").register("a-carousel-accessibility-standard-mobile",function(e,m){function g(e){var f=e.dom.$carousel;e=f.children(".a-carousel-card-empty");f=f.children("li").not(e);var g=f.length,c=g?{"aria-setsize":g}: +{};e.attr("aria-hidden","true").removeAttr("aria-setsize").removeAttr("aria-posinset");f.each(function(b){c["aria-posinset"]=b+1;c["aria-hidden"]="false";d(this).attr(c)})}var d=e.$;e=e.constants.NOOP;return{init:function(d){g(d);d.onChange(m.SET_SIZE,function(){g(d)});d.onChange(m.LOADING,function(e){d.dom.$carousel.attr("aria-busy",(!!e).toString());e||g(d)})},gotoPage:e,nextPage:e,prevPage:e}});"use strict";n.when("A","a-carousel-accessibility-standard-desktop","a-carousel-accessibility-standard-mobile").register("a-carousel-strategies-accessibility", +function(e,m,g){return{standardDesktop:m,standardMobile:g,none:{init:e.constants.NOOP,gotoPage:e.constants.NOOP,nextPage:e.constants.NOOP,prevPage:e.constants.NOOP},"default":e.capabilities.mobile||e.capabilities.tablet?"standardMobile":"standardDesktop"}});"use strict";n.when("a-carousel-strategies-display","a-carousel-strategies-transition","a-carousel-strategies-ajax","a-carousel-strategies-accessibility").register("a-carousel-strategies",function(e,m,g,d){return{display:e,transition:m,ajax:g, +accessibility:d}});"use strict";n.when("A","jQuery","a-carousel-classes","a-carousel-strategies","a-carousel-constants").register("a-carousel-framework",function(e,m,g,d,k){function f(a,b,c,d){var f=a.hasClass("a-begin"),g=0 v?v:a;a!==b.leftOffset&&(d.animate(c,{left:a},0),b.leftOffset=a,b.isDragging=!0,b.dragCount++)}}function f(a){a.preventDefault();if(d.capabilities.touch||1===a.which){a=a.data.$switch;var b=a.data("a-switch-state");m(a,b.isDragging&&1 b.midPoint:!b.isOn);b.isDragging= +!1;t(a)}}function l(a,b,c){c={switchState:a,previousState:c};d.trigger("a:switch:"+b,c);a.name&&d.trigger("a:switch:"+a.name+":"+b,c)}function c(a){if(!a.data("a-switch-state")){var b=a.closest(".a-switch-row"),c=a.children(".a-switch-control"),d=b.find(".a-switch-label"),e=d.siblings("input"),k=e.attr("name"),l=b.hasClass("a-active"),g=!b.hasClass("a-disabled"),h=r.left,f=(a.width()-c.width()+r.right)*z;a.data("a-switch-state",{input:e,container:b,control:c,label:d,isDragging:!1,rightBoundary:f, +leftBoundary:h,midPoint:f/2,initialX:null,leftOffset:l?f:h,maxLeftOffset:r.maxLeftOffset,isOn:l,isEnabled:g,name:k,dragCount:0,clicked:!1})}}function m(a,b){c(a);a=a.data("a-switch-state");var e=a.isOn,k=b!==a.isOn;a.isOn=b;var f=a.control,h=a.maxLeftOffset,g=a.isOn?a.rightBoundary:a.leftBoundary;g=h&&g>h?h:g;d.animate(f,{left:g},300,"ease-out");a.leftOffset=g;f=a.container;a.isOn?f.addClass("a-active"):f.removeClass("a-active");f=a.input;a.isOn?f.attr("checked","checked"):f.removeAttr("checked"); +k&&l(a,"flip",e);b?l(a,"on",e):l(a,"off",e)}var p=function(a){a.bind("touchmove.a-switch-component",{$switch:a},g);a.bind("touchend.a-switch-component",{$switch:a},f);a.bind("touchcancel.a-switch-component",{$switch:a},f);a.bind("mouseup.a-switch-component",{$switch:a},f)},k=function(a){a.unbind("touchmove.a-switch-component");a.unbind("touchend.a-switch-component");a.unbind("touchcancel.a-switch-component");a.unbind("mouseup.a-switch-component")},x=function(a){return(a.originalEvent.touches[0]|| +a.originalEvent.changedTouches[0]).pageX},n=function(a){h("body").bind("mousemove.a-switch-component",{$switch:a},g);h("body").bind("mouseup.a-switch-component",{$switch:a},f)},y=function(a){h("body").unbind("mousemove.a-switch-component",g);h("body").unbind("mouseup.a-switch-component",f)},A=function(a){return a.pageX},r={left:d.capabilities.rtl?1:-1,right:-3},z=d.capabilities.rtl?-1:1;e.when("prv:skin-vars").execute(function(a){r=a.toggle.bounds});var u=null,t=null,q=null;d.capabilities.touch?(u= +p,t=k,q=x):(u=n,t=y,q=A);d.declarative("a-switch","touchstart",function(a){var b=a.$event;b.preventDefault();if(d.capabilities.touch||1===b.which){a=a.$declarativeParent;c(a);var e=a.data("a-switch-state");e.dragCount=0;e.clicked=!0;e.isDragging=!1;e.isEnabled&&(e.initialX=q(b),u(a))}});d.declarative("a-switch-label","click",function(a){a.$event.preventDefault();a=a.$target.closest(".a-switch-row").find(".a-switch");c(a);var b=a.data("a-switch-state");b.isEnabled&&m(a,!b.isOn)});e.when("ready").execute("a-switch-normalization", +function(){h(".a-switch-input").each(function(){var a=h(this),b=a.next().children(".a-switch");m(b,a.prop("checked"))})});return{ensureInitialized:c,setOnState:m,setEnabled:function(a,b){c(a);a=a.data("a-switch-state");var d=a.container;b?d.removeClass("a-disabled"):d.addClass("a-disabled");a.isEnabled=b},SWITCH_STATE:"a-switch-state",SWITCH_CONTAINER_CLASS:"a-switch-row",SWITCH_CLASS:"a-switch"}})}); +/* ******** */ +(function(a){var f=window.AmazonUIPageJS||window.P,l=f._namespace||f.attributeErrors,b=l?l("AmazonUIProgressBar","AmazonUI"):f;b.guardFatal?b.guardFatal(a)(b,window):b.execute(function(){a(b,window)})})(function(a,f,l){a.when("A","ready").register("a-progress",function(b){function a(a){(a?e(a):e(".a-js-progress-bar")).each(function(){var a=e(this);if(b.onScreen(a,0)){var g=+a.attr("data-progress-percentage");var h=-(g-100);var c=a.width();var f=h/100*c;var d=a.find(".a-js-progress-tooltip"),k=d.width(); +d.find(".a-js-tooltip-arrow");g=(g+h/2)/100*c-k/2;h=k+g;(k=h f&&d.addClass("aok-hidden");e(a.find(".a-js-progress-tooltip")).removeClass("a-progress-tooltip-hidden").addClass("a-progress-tooltip-revealed")}})}var e=b.$;a();b.on("resize scroll",function(b){a()});return{init:a}})}); +/* ******** */ +(function(n){var v=window.AmazonUIPageJS||window.P,x=v._namespace||v.attributeErrors,b=x?x("AmazonUIPopover@base","AmazonUI"):v;b.guardFatal?b.guardFatal(n)(b,window):b.execute(function(){n(b,window)})})(function(n,v,x){n.when("A","a-popover-base-factory").register("a-popover-base-apis",function(b,e){return{show:function(b){var c=e.get(b.$trigger?b.$trigger:b);if(c)return c.show.apply(c,arguments)},hide:function(b){var c=e.get(b);if(c)return c.unlock(1),c.hide.apply(c,arguments)},get:function(b){return e.get(b)}, +remove:function(b){return e.remove(b)}}});"use strict";n.when("A","a-popover-util","a-popover-objectclass","a-popover-data","a-analytics").register("a-popover-base-factory",function(b,e,g,c,m){function h(a){return u[a]?u[a]:null}function k(a,d){return new g.PopoverClass(a,d)}function q(a,d){var b=null;if("number"===typeof a)b=h(a);else if("string"===typeof a)(b=l[a]?l[a]:null)||(b=h(a));else if("object"===typeof a)if(a.$popover)b=a;else if(a=f(a),b=a.data("a-popover-id"),b||(b=a.find(".a-declarative").eq(0), +b=b.length?b.data("a-popover-id"):null),b=h(b),!b){var k=a.data("action");(k=k?a.data(k):null)&&k.name&&(b=k.name,b=l[b]?l[b]:null,!b||d&&b.type!==d?b=null:(d=(d=b.attrs("currentDataStrategy"))?c.getStrategyByName(d):c.guessStrategyByAttrs(b.attrs()))&&d.reusePopover?b.$trigger[0]!==a[0]&&(b.$trigger.data("a-popover-id",null),b.$trigger=a):b=null)}return b}function a(){r||(r=k({id:-1,$popover:p,$trigger:p,immersive:!0},{isActive:function(){return!0},hideMethod:function(){this.hideChildren()},showMethod:b.constants.NOOP})); +return r}var f=b.$,d=1,l={},u={},p=f("\x3cdiv id\x3d'a-popover-root' style\x3d'z-index:-1;position:absolute;' /\x3e").appendTo("body"),r;return{getRoot:a,get:function(a,d){d=d?d:this?this.type:null;return(a=q(a,d))&&d&&a.type!==d?null:a},create:function(c,g){var e=f(c),p=g.attributes||{},r=g.typeSpecificFunctions||g.variant||{};g=g.actionCheck||!1;e.data("a-popover-id");var t=p.type,y=null;!t||e.hasClass("a-declarative")&&e.data("action")&&-1!==e.data("action").indexOf(t)||(e=b.declarative.create(e, +"a-"+t),c=e[0]);if(g&&e.data("action")&&-1===e.data("action").indexOf(t))return null;t&&e&&(y=q(e));if(y)return y.type!==t?null:y;e=p;c=f(c);e.type?c&&c.length?(e=b.extend({id:d++,$trigger:c,$triggerWrapper:null},e),r=b.copy(r),r=k(e,r),u[r.id]=r,r.name&&(l[r.name]=r),c.data("a-popover-id",r.id),m.logNexus("aui_analytics.PopoverCloseUsage.1",{hasClose:!!e.closeButton,triggerAttribution:b.attributionChain(c[0]),label:"undefined"===typeof e.popoverLabel?null:e.popoverLabel,closeLabel:"undefined"=== +typeof e.closeButtonLabel?null:e.closeButtonLabel}),c=r.$trigger.closest(".a-popover"),c=!r.attrs("immersive")&&c.length?h(c.data("a-popover-id"))||a():a(),r.parent=c,c.children.push(r)):r=null:r=null;return r},remove:function(a,d){a=this.get(a);var f=!1;if(a){f=a.id;if(a&&-1 b.now()-k||(k=b.now(),b.delay(function(){h(document.activeElement).hasClass("a-popover-start")&&f.getLastTabbable().focus()},0))}});b.declarative("a-popover-a11y","focusin",function(a){var f=m(a.$target);f&&a.$target.length&&a.$target.hasClass("a-popover-end")&&!(q&&100>b.now()-q)&&(q=b.now(),b.delay(function(){f.getFirstTabbable().focus()},0))});b.declarative("a-popover-a11y", +"keydown",function(a){var f=a.$event;f.keyCode===b.constants.keycodes.ESCAPE&&(a=m(a.$target),f.preventDefault(),a&&a.hide())});b.on("resize zoom",function(){g.getRoot().updatePosition()});if(c.isSafari&&b.capabilities.ios)b.on("a:popover:refresh",function(a){a=a.popover;a.$popover&&a.$popover.undelegate('input[type\x3d"date"]',"blur").delegate('input[type\x3d"date"]',"blur",function(){var a=b.$(v);a.scrollTop(a.scrollTop()+1)})})});"use strict";n.when("A","a-popover-base-apis","a-popover-base-handlers").register("a-popover-base", +function(b,e,g){return e});"use strict";n.when("A","a-popover-util","a-popover-data","a-popover-position","a-popover-lightbox","a-popover-animate","prv:a-capabilities").register("a-popover-objectclass",function(b,e,g,c,m,h,k){function q(a,c){var k=-1,g=[1],p=-2;this.parent=null;this.children=[];this.typeSpecificFunctions={};this.attributes={position:"triggerVertical",alone:!1,immersive:!1,restoreFocusOnHide:!0};var q=function(){this.isActive()?this._willTriggerEvents&&e.trigger("visible",this):e.trigger("invisible", +this);return this},r=function(a,l){var k=this.isActive(),c=this.getDataStrategy(),h=!this.$popover,e=l||h;l=!1;a=a||e;if(!e)for(var p=g.length;p--&&!e;)e=!u[g[p]];e&&(e=A.apply(this),e=d(e),h||(c.unloadContent(this),this.$container.remove(),l=!0),d("body").append(e),this.$container=e,this.$popover=this.$container.hasClass("a-popover")?this.$container:this.$container.find(".a-popover"),this.$startAnchor=this.$popover.hasClass("a-popover-start")?this.$popover:this.$popover.find(".a-popover-start"), +this.$endAnchor=this.$popover.find(".a-popover-end"),this.$popover.attr("id","a-popover-"+this.id).data("a-popover-id",this.id));this.attrs("immersive")||(e=parseInt(this.parent.$popover.css("z-index"),10),b.isFiniteNumber(e)||(e=this.parent.attrs("immersive")?1010:0),p=this.$trigger.closest(".a-sheet-web"),1===p.length&&(p=parseInt(p.css("z-index")),b.isFiniteNumber(p)&&(e=Math.max(p,e))),e=Math.max(299,100+e),this.$popover.css("z-index",e));if(c.shouldRefreshContent(this)||a)l||c.unloadContent(this), +c.loadContent(this,h);this.typeSpecificFunctions.updateDimensions!==f&&this.typeSpecificFunctions.updateDimensions.apply(this);g=[];k&&t.call(this,[],!1);return this},t=function(a,d){function c(){k.updatePosition();var f=k.attrs("navigate");!d&&f&&k.attrs("navigate",!1);g.call(k,q,a);d&&e.trigger("show",k);r&&r.apply(k,a);d&&e.trigger("afterShow",k);k.$popover.attr("aria-hidden","false");"tooltip"!==k.type&&l.attr("aria-hidden","true");!d&&f&&k.attrs("navigate",f);p=2}var k=this;d=!!d;var h=k.typeSpecificFunctions, +g=h.showMethod!==f?h.showMethod:n,u=h.beforeShowMethod!==f?h.beforeShowMethod:null,r=h.afterShowMethod!==f?h.afterShowMethod:null;p=1;k._willTriggerEvents=d;k.attrs("originalFocus",document.activeElement);k.$popover.css("visibility","hidden").addClass("a-popover-hidden").show();u&&u.apply(k,a);k.attrs("synchronous")?c():b.delay(function(){c()},0)};this.show=function(){var a=this,d=a.attrs("lightboxOptions")||null;if(a.isActive()||h.isAnimating(a))return this;a.lock(1);d&&m.lock(1);a.parent.$container&& +a.parent.$container.is(".a-popover")&&a.parent.$container.attr("aria-hidden","true");a.attrs("alone")&&b.each(a.parent.children,function(d){d.isActive()&&d.id!==a.id&&!d.attrs("modeless")&&d.unlock().hide()});e.trigger("beforeShow",a);if(!a.$container||a.isDirty()||a.getDataStrategy().shouldRefreshContent(a))e.trigger("refresh",a),r.call(a);if(a.draggable){var f=a.$container;b.draggable(f,{handle:f.find(".a-popover-draggable-handle")})}d&&m.show(b.extend({popover:a},d));t.call(a,arguments,!0);b.delay(function(){a.unlock(1); +d&&m.unlock(1)},0);return this};this.hide=function(){var a=this,k=a.typeSpecificFunctions,c=k.hideMethod!==f?k.hideMethod:w,g=k.beforeHideMethod!==f?k.beforeHideMethod:null,u=k.afterHideMethod!==f?k.afterHideMethod:null,r=a.attrs("lightboxOptions")||null;if(!a.isActive()||a.isLocked()||h.isAnimating(a))return this;p=-1;a.hideChildren();e.trigger("beforeHide",a);g&&g.apply(a,arguments);c.call(a,q,arguments);e.trigger("hide",a);b.delay(function(){function f(){b.delay(function(){var f=null,l=a.$container.find(document.activeElement).length, +k=d(document.activeElement).is("a, button, input:not([type\x3d'hidden']), select, textarea, [tabindex]:not([tabindex\x3d'-1'])");if(l||!k)"dropdown"===a.type?f=a.$trigger:a.$trigger&&d(a.$trigger).length&&(f=a.$trigger.is("a, input, button")?a.$trigger:a.$trigger.find("a, input, button")),f&&f.length||(f=d(a.attrs("originalFocus"))),!f.length||y&&!f.is(":visible")||("secondary-view"===a.type||b.onScreen(f,0))&&f.focus()},400)}u&&u.apply(a,arguments);a.$popover.attr("aria-hidden","true");"tooltip"!== +a.type&&l.attr("aria-hidden","false");a.parent.$container&&a.parent.$container.is(".a-popover")&&a.parent.$container.attr("aria-hidden","false");r&&(a.parent.attrs("lightboxOptions")?m.show(b.extend({popover:a.parent},r)):m.hide(r));e.trigger("afterHide",a);p=-2;a.attrs("restoreFocusOnHide")&&f()},0);return this};this.update=function(a){var d="string"===typeof a?{content:a}:b.copy(a),f=this.attrs();a=this.getDataStrategy();b.each(d,function(a,d){(a&&!f[d]||f[d]&&f[d]!==a)&&g.push(d)});this.isDirty()&& +(d=b.extend({},f,d),this.attrs(d),this.getDataStrategy(d),this.$popover&&a.unloadContent(this),this.isActive()&&(r.call(this,!0),this.focus()));return this};this.refresh=function(a,d){return r.call(this,a||!0,d||!1)};this.isActive=function(){return 1<=p};this.isVisible=function(){return 2===p};this.isContentLoading=function(){return 3===p};this.setContentLoading=function(){p=3};this.isContentLoaded=function(){return 4===p};this.setContentLoaded=function(){p=4};this.isDirty=function(){return 0 g&&f.css({height:g+"px","overflow-y":"scroll"})}e.trigger("afterUpdatePosition",a);e.trigger("positionUpdated",a);b.each(a.children,function(a){a.isActive()&&a.updatePosition()})};a.attrs("immersive")&&r?(l.css({top:0,left:0}),b.delay(function(){h()},0)):h()}return a};p.attrs=function(a,d){var l=this;if(d===f&&"object"!==typeof a)return a?"string"===typeof a?this.attributes[a]!==f?this.attributes[a]:null:null:this.attributes; +"object"===typeof a?b.each(a,function(a,d){l.attrs(d,a)}):"string"===typeof a&&(this.attributes[a]=d,l[a]=d);return this};p.hideChildren=function(){b.each(this.children,function(a){a.unlock(1);a.hide()});return this};p.getFirstTabbable=function(){return this.$popover.find('[data-action\x3d"a-popover-close"]').add(a(this)).first()};p.getLastTabbable=function(){return a(this).last()};p.focus=function(){var a=this,f=d(v),l=f.scrollTop(),k=a.$popover.offset().top;t&&l>k&&f.scrollTop(k);b.delay(function(){a.getFirstTabbable().focus()}, +0);return this};return{PopoverClass:q}});"use strict";n.when("jQuery","ready").register("a-changeover",function(b){b(document).delegate(".a-changeover:not(.a-changeover-manual)","webkitAnimationEnd animationend click touchstart",function(b){this.style.display="none"})});"use strict";n.when("A").register("a-dropdown-base-positions",function(b){return{positionStrategy:function(e){var g=e.$popover,c=e.$trigger,m=e.measure;e=g.find(".a-popover-inner");e.css({"min-width":"0px",width:"auto",height:"auto"}); +var h=c.nextAll(".a-button-dropdown");h.length||(h=c.closest(".a-button-group"));c=m(g,h);m=c.windowWidth-(c.triggerLeft+c.popoverWidth);h=c.windowWidth-c.triggerLeft-c.triggerWidth;var k=c.triggerLeft,q={},a=c.triggerTop-c.windowTop,f=c.windowBottom-c.triggerBottom,d=g.find(".a-popover-inner");a>f&&f f?d.addClass("a-lgtbox-vertical-scroll"): +d.removeClass("a-lgtbox-vertical-scroll");e.hasClass("a-lgtbox-vertical-scroll")&&-1 m&&k>h?c.triggerRight-c.popoverWidth:c.triggerLeft;return q}}});"use strict";n.when("A","a-dropdown-base-positions").register("a-dropdown-base-view-base",function(b,e){return b.extend(e,{updateContent:function(b){"string"===typeof b? +this.$popover.find(".a-popover-inner").html(b):b&&this.$popover.find(".a-popover-inner").html("").append(b)},beforeShowMethod:function(){this.parent.lock(1);"combobox"===this.$trigger.attr("role")&&this.$trigger.attr("aria-expanded",!0)},afterShowMethod:function(){var e=this.$popover,c=e.find(".a-active");b.delay(function(){c.length?c.closest("li").focus():c=e.find("li").first().focus()},0)},beforeHideMethod:function(){this.parent.unlock(1)},afterHideMethod:function(){"combobox"===this.$trigger.attr("role")&& +this.$trigger.attr("aria-expanded",!1);this.$popover.css("width","auto")}})});"use strict";n.when("A","a-dropdown-base-view-base").register("a-dropdown-base-view",function(b,e){return e});"use strict";n.when("A","a-popover-base-factory","a-dropdown-base-view").register("a-dropdown-base-factory",function(b,e,g){function c(a,f,d){var l=['\x3cli tabindex\x3d"0" role\x3d"option"'],c=a.data("aCssClass"),h=a.data("aId"),e=a.data("aHtmlContent"),g=a.data("aImageSource"),q=JSON.stringify({stringVal:a.val()}); +q=['\x3ca tabindex\x3d"-1" href\x3d"javascript:void(0)" aria-hidden\x3d"true" data-value\x3d"',b.escapeHtml(q),'"'];var m=["a-dropdown-link"],n=["a-dropdown-item"];f?(m.push("a-active"),l.push(' aria-selected\x3d"true"')):l.push(' aria-selected\x3d"false"');k&&(b.capabilities.mobile||b.capabilities.tablet)&&m.push("a-list-link-after-group");k=!1;c&&n.push(c);h&&l.push(' id\x3d"'+h+'"');l.push('aria-labelledby\x3d"');l.push(d);l.push('"');q.push(' id\x3d"');q.push(d);q.push('"');l.push(' class\x3d"'+ +n.join(" ")+'"');l.push("\x3e");e?f=e:(f=[],g&&(m.push("a-option-has-image"),f.push('\x3cimg src\x3d"'+g+'" class\x3d"a-rich-option-image" /\x3e')),f.push(a.html()),f=f.join(""));q.push(' class\x3d"');q.push(m.join(" "));q.push('"\x3e');q.push(f);q.push("\x3c/a\x3e");l.push(q.join(""));l.push("\x3c/li\x3e");return l.join("")}function m(a){a.jquery||(a=h(a));var f=a.children("optgroup,option:not(.a-prompt)"),d=!1,l=a[0],b=a.attr("id")?a.attr("id"):"dropdown"+q++;if(-1 f.length&&(f=d.find('[aria-selected\x3d"true"]'));d=f;return{index:0 m)){c=(l.data("a-user-navigated-text")||"")+String.fromCharCode(g).toLocaleLowerCase();l.data("a-user-navigated-text",c);for(var t=l.children();m b.grid_units&&(a.addClass("a-button-span"+b.grid_units),d.addClass("a-button-span"+b.grid_units)));b.width_name&&("base"===b.width_named?d.addClass("a-button-width-normal"):d.removeClass("a-button-width-normal"));if(b.status){var m=b.status;c=d.closest(".a-dropdown-container, .a-splitdropdown-container").find(".a-button");g="error"===m;m="disabled"===m;f.disabled=m;c.toggleClass("a-button-disabled",m);e(f).hasClass("a-native-splitdropdown")?m?c.find("button.a-button-text").attr("aria-disabled", +"true").parents(".a-button-splitdropdown").find("button.a-button-text").removeAttr("role"):c.find("button.a-button-text").removeAttr("aria-disabled").parents(".a-button-splitdropdown").find("button.a-button-text").attr("role","combobox"):m?c.attr("aria-disabled","true"):c.removeAttr("aria-disabled");c.toggleClass("a-button-error",g)}b.native_id&&(f.id=b.native_id,k.length&&(k[0].htmlFor=b.native_id));b.id&&(l.id=b.id);b.native_css_class&&((l=a.data("a-native-class"))&&a.removeClass(l),a.addClass(b.native_css_class).data("a-native-class", +b.native_css_class));b.css_class&&((l=d.data("a-class"))&&d.removeClass(l),d.addClass(b.css_class).data("a-class",b.css_class));b.label_text!==h&&(""===b.label_text?(d.find(".a-dropdown-label").remove(),a.siblings("label").remove()):(l=d.find(".a-dropdown-label"),l.length?l.text(b.label_text):d.find(".a-dropdown-prompt").before(e("\x3cspan class\x3d'a-dropdown-label' /\x3e").text(b.label_text)),k.length?k.text(b.label_text):a.before(e("\x3clabel for\x3d'"+f.id+"' class\x3d'a-native-dropdown' /\x3e").text(b.label_text))), +d.css("min-width",""===b.label_text?"0.1%":"0%"));this.refreshPopover(this.options);return this},setValue:c,val:m,getOptions:function(c){var k=this.options.$select,a=[];c=c===h?k.children("optgroup, option:not(.a-prompt)"):e.isArray(c)?c:[c];for(var f=0,d=c.length;f |\s>/g,"\x3e")},getEndAnchorHtml:function(a){return m},getDescription:function(a){var b="",d=a.id;(a=a.aria_description)&&(b=l("a-popover-aria-description-"+d,a));return b},getStartAnchorSimplifiedHtml:function(){return a}}});"use strict";n.declare("a-popover-accessibility-templates",{startAnchorTemplate:'\x3cspan tabindex\x3d"0" role\x3d"dialog" class\x3d"{{ANCHOR_NAME}} a-popover-a11y-offscreen" {{ARIA_LABEL}} {{ARIA_DESCRIBEDBY}}\x3e\x3c/span\x3e', +startAnchorDeclarativeTemplate:'\x3cspan tabindex\x3d"0" role\x3d"dialog" data-action\x3d"a-popover-a11y" class\x3d"{{ANCHOR_NAME}} a-popover-a11y-offscreen a-declarative" {{ARIA_LABEL}} {{ARIA_DESCRIBEDBY}}\x3e{{LABEL_STR}}\x3c/span\x3e',endAnchorTemplate:'\x3cspan tabindex\x3d"0" class\x3d"a-popover-end a-popover-a11y-offscreen"\x3e\x3c/span\x3e',descriptionTemplate:'\x3cspan id\x3d"{{DESCRIPTION_ID}}" class\x3d"a-popover-a11y-offscreen"\x3e{{DESCRIPTION}}\x3c/span\x3e',offscreenDescriptionTemplate:'\x3cspan id\x3d"{{DESCRIPTION_ID}}" class\x3d"a-popover-a11y-offscreen" aria-hidden\x3d"true"\x3e{{DESCRIPTION}}\x3c/span\x3e', +labelTemplate:'\x3cspan id\x3d"{{LABEL_ID}}" class\x3d"a-popover-a11y-offscreen" aria-hidden\x3d"true"\x3e{{LABEL}}\x3c/span\x3e',offscreenStartTemplate:'\x3cspan tabindex\x3d"0" class\x3d"a-popover-start a-popover-a11y-offscreen"\x3e\x3c/span\x3e'});"use strict";n.when("A","a-popover-util").register("a-popover-ajax",function(b,e){return{update:function(b,c,e){var h={};h.url=c;e.timeout&&(h.timeout=e.timeout);e.ajaxFailMsg&&(h.ajaxFailMsg=e.ajaxFailMsg);e.cache&&(h.cache=e.cache);b.update(h)},showSpinner:function(b){return e.showSpinner(b)}}}); +"use strict";n.when("A").register("a-popover-animate",function(b){function e(c,e){return function(){b[c].apply(b,e)}}function g(b,e){return function(){b._isAnimating=!1;e&&e()}}return{isAnimating:function(b){return b._isAnimating},animate:function(c,m,h,k,q){c._isAnimating=0 a.windowBottom- +20&&(d=Math.min(20,a.windowBottom-a.triggerBottom+20),b.deltaTop=b.top+a.popoverHeight-(a.windowBottom-d),b.top=a.windowBottom-d-a.popoverHeight);return b}function h(a){var b={deltaLeft:0};b.left=a.triggerHorizontalCenter-a.popoverWidth/2;if(20>b.left){var d=Math.min(20,a.triggerLeft-20);b.deltaLeft=b.left-d;b.left=d}else b.left+a.popoverWidth>a.windowRight-20&&(d=Math.min(20,a.windowRight-a.triggerRight+20),b.deltaLeft=b.left+a.popoverWidth-(a.windowRight-d),b.left=a.windowRight-d-a.popoverWidth); +return b}var k=b.$;k(v);var q=null,a=1,f=b.capabilities.mobile&&e.isIE10Plus;n.when("prv:skin-vars-desktop").execute(function(b){a=b.popover.POPOVER_SPACING?b.popover.POPOVER_SPACING:a});return{windowCenter:function(a){a=g(a.$popover,a.$trigger);var b={};b.top=(a.windowHeight-a.popoverHeight)/2;b.left=(a.windowWidth-a.popoverWidth)/2;0>b.top&&(b.top=0);return b},windowTop:function(a){a=g(a.$popover,a.$trigger);var b={top:0};b.left=a.windowWidth/2-a.popoverWidth/2;return b},windowFullWidth:function(a){return{top:0, +left:0}},triggerRight:function(a,b){var d=a.$popover,f=a.$trigger;b||(b=g(d,f));f=m(b);f.left=b.triggerRight;a.attrs("popoverArrow")&&(c(d).addClass("a-arrow-right"),d.find(".a-arrow-border").css("top",b.popoverHeight/2+f.deltaTop));return f},triggerLeft:function(a,b){var d=a.$popover,f=a.$trigger;b||(b=g(d,f));f=m(b);f.left=b.triggerLeft-b.popoverWidth;f.left=0 b.windowRight-b.triggerRight?this.triggerLeft(a,b):this.triggerRight(a,b)},triggerVertical:function(a,b){var c=a.$popover,d=a.$trigger;b=b?b:g(c,d);return b.triggerTop-b.windowTop>b.popoverHeight+20?this.triggerTop(a,b):this.triggerBottom(a,b)},triggerVerticalAlignLeft:function(a,b){var d=a.$popover,f=a.$trigger;b||(b=g(d,f));f={};var e=0,h=b.windowBottom-b.triggerBottom;f.left=b.triggerLeft;f.top=h>b.popoverHeight?b.triggerBottom+ +3:b.triggerTop-b.popoverHeight-3;if(20>f.left){var l=Math.min(20,b.triggerLeft-20);e=f.left-l;f.left=l}else f.left+b.popoverWidth>b.windowRight-20&&(l=Math.min(20,b.windowRight-b.triggerRight+20),e=f.left+b.popoverWidth-(b.windowRight-l),f.left=b.windowRight-l-b.popoverWidth);a.attrs("popoverArrow")&&(c(d).addClass(h>b.popoverHeight?"a-arrow-bottom":"a-arrow-top"),d.find(".a-arrow-border").css("left",b.triggerWidth/2+e));return f},customPosition:function(a,b){return b.call(this,{popover:a,$popover:a.$popover, +$trigger:a.$trigger,measure:g})}}});"use strict";n.when("A","a-modal-view-base","a-modal-positions","a-popover-accessibility").register("a-modal-view",function(b,e,g,c){var m=b.$;m=m("html").hasClass("a-lt-ie9");return b.extend(e,b.capabilities.touch||b.capabilities.mobile||b.capabilities.tablet||m?g.innerScroll:g.modalScroll,{skin:function(e){var h=e.attrs("id"),g=e.attrs("header")||"",a=e.attrs("hideHeader")||!1,f=e.attrs("footer"),d=e.attrs("modeless")||!1,l=e.attrs("closeButton"),m=e.attrs("closeButtonLabel")|| +"",p=e.attrs("hideHeaderCloseButtonLayout")||"",n=e.attrs("popoverLabel")||"",t=e.attrs("padding");e=e.attrs("ariaDescription");e={id:h,header_str:g,label_str:n,aria_description:e};n=c.getDescription(e);var y=c.getPopoverLabelHtml(e);l='\x3cbutton data-action\x3d"a-popover-close" class\x3d"'+(l?"":" a-button-close-a11y")+" a-button-close a-declarative"+(a?l?"top"===p?" a-modal-close-nohead-top":" a-button-top-right":" a-button-a11y-top-right":"")+'" aria-label\x3d"'+m+'"\x3e\x3ci class\x3d"a-icon a-icon-close"\x3e\x3c/i\x3e\x3c/button\x3e'; +g=!a||y?"\x3cheader"+(a?"":' class\x3d"a-popover-header"')+"\x3e"+(a?"":'\x3ch4 class\x3d"a-popover-header-content'+(d?" a-popover-draggable-handle":"")+'" id\x3d"a-popover-header-'+h+'"\x3e'+g+"\x3c/h4\x3e")+l+y+"\x3c/header\x3e":l;f=f?'\x3cdiv class\x3d"a-popover-footer"\x3e'+f+"\x3c/div\x3e":"";t="none"===t?" a-padding-none":"";a=b.capabilities.isAndroid?"":c.getStartAnchorSimplifiedHtml();l=b.capabilities.isAndroid?"":c.getEndAnchorHtml(e);m=d?"":'\x3cdiv class\x3d"a-modal-scroller a-declarative" data-action\x3d"a-popover-floating-close"\x3e'; +e='\x3cdiv class\x3d"a-popover a-popover-modal a-declarative'+(d?" a-modal-modeless":" ")+'" data-action\x3d"a-popover-a11y" aria-modal\x3d"true" role\x3d"dialog"'+c.getAriaLabel(e)+"\x3e";return m+e+a+n+'\x3cdiv class\x3d"a-popover-wrapper"\x3e'+g+('\x3cdiv class\x3d"a-popover-inner'+t+'" id\x3d"a-popover-content-'+h+'"\x3e\x3c/div\x3e')+f+"\x3c/div\x3e"+l+"\x3c/div\x3e"+(d?"":"\x3c/div\x3e")}})});"use strict";n.when("A","a-popover-lightbox","a-popover-optional-helpers","prv:a-capabilities").register("a-modal-positions", +function(b,e,g,c){function m(a){var b=a.$popover.closest(".a-modal-scroller");b.scrollTop(0).css("visibility","visible");b.bind("scroll",function(){a.updateChildrenPosition()})}function h(){var a=b.viewport();2 a)return c({"padding-right":b+"px","box-sizing":"content-box"}),!0;c({"padding-right":"","box-sizing":""});return!1}function q(a){return function(b){a.css(b)}} +var a=b.$,f=c.isIE10Plus&&b.capabilities.mobile,d=0;n.when("prv:skin-vars").execute(function(a){d=a.popover.optionalButtonHeight});n.declare("prv:a-model-applyHorizonalScrollStyles",k);return{innerScroll:{positionStrategy:function(l){var m=l.popover,p=l.$popover,n=l.$trigger,t=p.find(".a-popover-inner").css("height","auto"),y=p.closest(".a-modal-scroller"),z={},w=b.viewport(!0),A=.1*w.height,B=.05*w.width;w=.8*w.height;var x=m.attrs("height");m=m.attrs("min-height");p.css({height:x?x:"","min-height":m? +m:""});n=l.measure(p,n);z.left=(n.windowWidth-n.popoverWidth)/2;k(z.left,B,q(p))&&(z.left=B);g.evaluateActualHeight(l,n.popoverHeight,d)>w?(m=p.find(".a-popover-header, .a-modal-close-nohead-top").outerHeight(!0)||0,x=p.find(".a-popover-footer").outerHeight(!0)||0,l=g.getOffsetTopDelta(l,A,d),w-=l,A+=l,t.css({height:w-m-x+"px","overflow-y":"auto"}),p.css({height:w,"min-height":0}),z.top=A):(z.top=(n.windowHeight-n.popoverHeight)/2,t.css("height","auto"));z.left+=n.zoomLeft;z.top+=n.zoomTop;f&&(y.css("top", +a(v).scrollTop()),p.removeClass("a-popover-pan-y").addClass("a-popover-pan-x"),p=a(document).height(),t=a(document).width(),a("#"+e.LIGHTBOX_ID).css({height:p,width:t>n.popoverWidth?t:n.popoverWidth+B}));c.isMetroIEGuess&&c.isIETouchCapable&&h();return z},beforeShowMethod:b.constants.NOOP,beforeHideMethod:b.constants.NOOP},modalScroll:{positionStrategy:function(a){var d=a.$popover,f=a.$trigger,e=d.closest(".a-modal-scroller"),g=d.find(".a-popover-inner").css("height","auto");if(d.hasClass("a-popover-modal-fixed-height")){var l= +d.find(".a-popover-footer");g.css("padding-bottom",l.height()+15)}g={};var m=b.viewport(!0),n=m.height;l=.1*n;m=.05*m.width;n*=.8;var v=d.height(),x=d.width();a=a.measure(d,f);g.left=(a.windowWidth-x)/2;g.top=(a.windowHeight-v)/2;k(g.left,m,q(d))&&(g.left=m);v>n?e.length?(g.top=0,d.css({position:"relative",margin:a.zoomTop+l+"px 0 "+l+"px "+(a.zoomLeft+g.left)+"px"}),g.left=0,e.css("padding-bottom","1px")):v>n&&(g.top=padding):e.length&&(d.css({position:"absolute",margin:"0px"}),e.css("padding-bottom", +"0px"));g.left+=a.zoomLeft;g.top+=a.zoomTop;c.isMetroIEGuess&&c.isIETouchCapable&&h();return g},beforeShowMethod:function(){m(this)},beforeHideMethod:function(){this.$popover.closest(".a-modal-scroller").css("visibility","hidden").unbind("scroll")}},util:{determineMaximumInnerHeight:function(a){var d=a.$popover;a=.8*b.viewport().height;var c=d.find(".a-popover-header, .a-modal-close-nohead-top").outerHeight(!0)||0;d=d.find(".a-popover-footer").outerHeight(!0)||0;return a-c-d},determineInnerVerticalPadding:function(a){a= +a.$popover.find(".a-popover-inner");return a.outerHeight()-a.height()}}}});"use strict";n.when("A","a-popover-base-factory","a-modal-view","a-popover-util","prv:a-capabilities").register("a-modal-factory",function(b,e,g,c,m){function h(a,f){var d=!1,h=!1;b.capabilities.mobile||b.capabilities.tablet||(d=c.getBool(f.modeless),h=c.getBool(f.draggable));f={modeless:d,draggable:h,type:"modal",alone:!0,immersive:!0,position:"windowCenter",header:f.header,hideHeader:f.hideHeader,footer:f.footer,padding:f.padding, +width:f.width,height:f.height,"max-width":f["max-width"],"max-height":f["max-height"],"min-width":f["min-width"],"min-height":f["min-height"],closeButton:c.getBool(f.closeButton,!0),timeout:f.timeout,lightboxOptions:d?x:{lockScroll:!0,showDuration:k||q?0:null},data:f.data||{},dataStrategy:f.dataStrategy,url:f.url,manualRefresh:!!f.manualRefresh,ajaxFailMsg:f.ajaxFailMsg,cache:c.getBool(f.cache,!0),inlineContent:f.inlineContent?f.inlineContent:f.content,name:f.name,closeButtonLabel:f.closeButtonLabel? +f.closeButtonLabel:"Close",hideHeaderCloseButtonLayout:f.hideHeaderCloseButtonLayout,popoverLabel:f.popoverLabel,ariaDescription:f.ariaDescription,ajaxHeaders:f.ajaxHeaders,withCredentials:c.getBool(f.withCredentials,!1),legacyNavigable:c.getBool(f.legacyNavigable,!0)};return e.create(a,{attributes:f,typeSpecificFunctions:g,actionCheck:!0})}var k=-1 g-c?c-g:0},evaluateActualHeight:function(b,g,c){return b.$popover.find(".a-button-close").length&&!b.$popover.find(".a-button-close-a11y").length?g+c:g}}});"use strict";n.when("A","a-popover-view-base","a-popover-util","a-popover-accessibility").register("a-popover-view",function(b,e,g,c){var m= +!0;n.when("prv:skin-vars").execute(function(b){m=b.popover.closeButtonEnabled});return b.extend(e,{skin:function(e){var g=e.attrs("id"),h=e.attrs("header"),a=m&&e.attrs("closeButton"),f=e.attrs("closeButtonLabel")||"",d=e.attrs("popoverLabel")||"",l=e.attrs("ariaDescription"),n=e.attrs("padding");e=e.attrs("popoverArrow");l={id:g,header_str:h,label_str:d,aria_description:l};b.capabilities.isAndroid&&(f=(d||h)+" "+f);a='\x3cbutton data-action\x3d"a-popover-close" class\x3d"a-button-close '+(a?"":"a-button-close-a11y")+ +' a-declarative" aria-label\x3d"'+f+'"\x3e\x3ci class\x3d"a-icon a-icon-close"\x3e\x3c/i\x3e\x3c/button\x3e';var p=(f=!!h)?"a-popover-has-header":"a-popover-no-header";n="none"===n?" a-padding-none":"";e=e?'\x3cdiv class\x3d"a-arrow-border"\x3e\x3cdiv class\x3d"a-arrow"\x3e\x3c/div\x3e\x3c/div\x3e':"";d=b.capabilities.isAndroid?"":c.getStartAnchorSimplifiedHtml();var r=b.capabilities.isAndroid?"":c.getEndAnchorHtml(l);h=h?'\x3ch4 class\x3d"a-popover-header-content" id\x3d"a-popover-header-'+g+'"\x3e'+ +h+"\x3c/h4\x3e":"";p='\x3cdiv class\x3d"a-popover '+p+' a-declarative" data-action\x3d"a-popover-container a-popover-a11y" aria-modal\x3d"true" role\x3d"dialog"'+c.getAriaLabel(l)+"\x3e";var t=c.getDescription(l);l=c.getPopoverLabelHtml(l);return p+d+t+'\x3cdiv class\x3d"a-popover-wrapper"\x3e'+(f?'\x3cheader class\x3d"a-popover-header"\x3e'+h+a+l+"\x3c/header\x3e":"")+('\x3cdiv class\x3d"a-popover-inner'+n+'"\x3e')+(f?"":l?"\x3cheader\x3e"+a+l+"\x3c/header\x3e":a)+('\x3cdiv class\x3d"a-popover-content" id\x3d"a-popover-content-'+ +g+'"\x3e\x3c/div\x3e')+"\x3c/div\x3e"+e+"\x3c/div\x3e"+r+"\x3c/div\x3e"}})});"use strict";n.when("A","a-popover-base-factory","a-popover-view","a-popover-util").register("a-popover-factory",function(b,e,g,c){function m(b,k){k={type:"popover",alone:!0,header:k.header,width:k.width,height:k.height,"max-width":k["max-width"],"max-height":k["max-height"],"min-width":k["min-width"],"min-height":k["min-height"],padding:k.padding,closeButton:c.getBool(k.closeButton,!0),position:k.position||"triggerVertical", +activate:k.activate||"onmouseover",timeout:k.timeout,data:k.data||{},dataStrategy:k.dataStrategy,url:k.url,manualRefresh:!!k.manualRefresh,ajaxFailMsg:k.ajaxFailMsg,cache:c.getBool(k.cache,!0),inlineContent:k.inlineContent?k.inlineContent:k.content,name:k.name,closeButtonLabel:k.closeButtonLabel?k.closeButtonLabel:"Close",popoverLabel:k.popoverLabel,ariaDescription:k.ariaDescription,focusWhenShown:c.getBool(k.focusWhenShown,!0),popoverArrow:c.getBool(k.popoverArrow,!0),restoreFocusOnHide:c.getBool(k.restoreFocusOnHide, +!0)};return e.create(b,{attributes:k,typeSpecificFunctions:g,actionCheck:!0})}return{type:"popover",create:m,get:function(b){var g=e.get(b,"popover");g||"object"!==typeof b||(b=c.extractDeclarativeParams(b,"popover"))&&(g=m(b.$trigger,b.attributes||{}));return g},remove:function(b){return e.remove(b,"popover")}}});"use strict";n.when("A","a-popover-factory").register("a-popover-handlers",function(b,e){function g(a){a&&!a.destroyTimer&&(a.destroyTimer=b.delay(function(){a.hide()},250))}function c(a){a&& +(clearTimeout(a.destroyTimer),a.destroyTimer=null,clearTimeout(a.parent.destroyTimer),a.parent.destroyTimer=null)}var m=b.$,h={},k=!(b.capabilities.mobile||b.capabilities.tablet)&&b.capabilities.ios;b.declarative("a-popover","click",function(a){var b=e.get(a.$declarativeParent);b&&(b.show(),a.$event.preventDefault())});b.declarative("a-popover","keydown",function(a){var c=b.constants.keycodes,d=a.$event.which;if(d===c.ENTER||d===c.SPACE)a.$event.preventDefault(),e.get(a.$declarativeParent).show()}); +if(!k){var n;b.declarative("a-popover","mouseenter",function(a){var f=e.get(a.$declarativeParent);f&&"onmouseover"===f.attrs("activate")&&(c(f),n=b.delay(function(){(f=e.get(a.$declarativeParent))&&h.popover===f&&1 b.cursor().speed&&c&&"onmouseover"===c.attrs("activate")&&h.popover===c&&1 a;)h=Math.floor((a+f)/2),l=b.substring(0,h+1)+e,parseFloat(d.html(l).css("height"))>c?f=h:a=h+1;b=k.trimSpecialChars(b.substring(0,f),g)+e}d.remove();return b}function h(a){a=f(a).attr("data-a-recalculate",!0);m();return a.length}function d(){return h('.a-truncate:not([data-a-manual-update\x3d"true"]):not([data-a-updated])')}var f=c.$,l=e.create({_componentName:"truncate",init:function(a,b){this._super(a,b);this._$full=this._$element.find(".a-truncate-full");this._$cut= +this._$element.find(".a-truncate-cut");this._$fullText=this.getFullText();this._$offscreenTextHolder=f('\x3cspan class\x3d"a-truncate-calc a-offscreen"/\x3e');c.capabilities.android&&c.capabilities.isAmazonApp&&(a=this.getMaxHeight(),/[^r]em$/.test(a)&&(a=parseFloat(a),b=parseFloat(this._$element.css("font-size")),this._$element.css("max-height",a*b+"px")))},update:function(a){var b=this._$cut.html(),d=g(this);this._$fullText!==d?this._$cut.height(this.getMaxHeight()):this._$cut.height("auto");this._$cut.html(d); +this._$element.attr("data-a-updated",!0);this._$full.addClass("a-offscreen");this._$cut.removeClass("a-hidden");d={truncateContainer:this._$element,truncateInstance:this};a&&a.silent||(a=this.getTruncatedText(),b!==a&&(c.trigger("a:truncate:updated",d),(b=this._$element.data("a-truncate-name"))&&c.trigger("a:truncate:"+b+":updated",d)))},getFullText:function(){return this._$full.html()},getTruncatedText:function(){return this.getIsUpdated()?this._$cut.html():g(this)},getIsUpdated:function(){return this._$element.is("[data-a-updated]")}, +getOverflowMarker:function(){return this._$element.data("a-overflow-marker")||""},getSpecialCharacterList:function(){return this._$element.data("a-special-character-list")||""},getLineHeight:function(){return this._$element[0].style.lineHeight},getMaxHeight:function(){return this._$element[0].style.maxHeight},getIfTextFits:function(){return this._$fullText===g(this)}}),m=function(a){function b(){(d=a())&&c.delay(b,0)}var d=!1;return function(){d||b()}}(function(){var a=f('.a-truncate[data-a-recalculate\x3d"true"]').first(), +b=!!a.length;b&&((new l(a)).update(),a.attr("data-a-recalculate",!1));return b});c.on("ready orientationchange",function(){h('.a-truncate:not([data-a-manual-update\x3d"true"])')});c.on("resize",function(a,b){b.width&&h('.a-truncate:not([data-a-manual-update\x3d"true"])')});c.on("a:pageUpdate",d);return{get:function(a,b){return new l(a,b)},manualTruncate:function(a){return h(f(a).find('.a-truncate[data-a-manual-update\x3d"true"]'))},switchToAutoTruncate:function(a){a=f(a).find('.a-truncate[data-a-manual-update\x3d"true"]'); +a.removeAttr("data-a-manual-update");return a.length},refreshAutoTruncate:d}});e.declare("prv:a-truncate-util",{trimSpecialChars:function(c,d){d=new RegExp("["+d.replace(/[.\\+*?[^\]$(){}=!<>|:-]/g,"\\$\x26")+"\\s]+$");return c.replace(d,"")}})}); +/* ******** */ +(function(l){var m=window.AmazonUIPageJS||window.P,n=m._namespace||m.attributeErrors,b=n?n("AmazonUICardUI","AmazonUI"):m;b.guardFatal?b.guardFatal(l)(b,window):b.execute(function(){l(b,window)})})(function(l,m,n){l.when("A","a-component","prv:a-cardui-peek-toggle","prv:a-cardui-peek-expand").register("a-cardui",function(b,d,g,k){var c=b.$,f=d.create({_componentName:"cardui",init:function(a,c){this._super(a,c);this.metadata={interactedOnce:!1,describedByIds:this._$element.data("describedByIds"),cardExpanded:this.isExpanded(), +cardName:this.getName()}},getCardType:function(){return c(this._$element).data("a-card-type")},isExpanded:function(){},getName:function(){return this._$element.attr("name")},getId:function(){return this._$element.attr("id")},toggle:function(){}});return{get:function(a,d){var e;if(!(e=c(a).data("cardInstance"))){switch(c(a).data("a-card-type")){case "peekToggle":e=f.extend(g);break;case "peekExpand":e=f.extend(k);break;default:e=f}d=new e(a,d);c(a).data("cardInstance",d);b.trigger("a:card:initialized", +d);c(a).attr("id")&&b.trigger("a:card:"+c(a).attr("id")+":initialized",d);e=d}return e}}});"use strict";l.when("A","a-component").register("prv:a-cardui-content",function(b,d){var g=d.create({_componentName:"carduiContent",init:function(b,c){this._super(b,c)},getHeight:function(){return this._$element[0].scrollHeight},getMaxHeightDataAttribute:function(){return this._$element.data("a-max-height")}});return{get:function(b,c){return new g(b,c)}}});"use strict";l.when("A","a-component","a-cardui").register("a-cardui-deck", +function(b,d,g){function k(a,h){f(a).data("cardInstance")||(f(a).attr("name",h.deckName+"-card"+h.cardCount++),f(a).data("describedByIds",h.describedByIds));return g.get(a)}function c(a,h){h=new p(a,h);f(a).data("deckInstance",h);return h}var f=b.$,a=0,p=d.create({_componentName:"carduiDeck",init:function(e,h){this._super(e,h);h=this._$element;e="a-cardui-deck-autoname-"+a++;f(h).attr("name",e);h=this._$element;var c=e+"-teaser-describedby-collapsed",b=e+"-teaser-describedby-expanded";f(h).find(".a-teaser-describedby-collapsed").attr("id", +c);f(h).find(".a-teaser-describedby-expanded").attr("id",b);this.metadata={cardCount:0,deckName:e,describedByIds:{collapsed:c,expanded:b}};this.initializeAllCards()},initializeCard:function(a,h){return k(a,this.metadata)},initializeAllCards:function(){var a=this;f(this._$element).find(".a-cardui").each(function(){return k(this,a.metadata)})},addCards:function(a){var e=this;a&&a.url||l.error("ajax options object or url is not defined.");var c,d=a.targetSelector,k=e._$element;d?(d=f(d),d.closest(k).length? +c=d:l.error("container is outside the deck","ERROR","addCards")):c=k;b.get(a.url,{cache:!1,success:function(a){c.append(a);e.initializeAllCards();b.trigger("a:deck:new-cards-added");f(e._$element).attr("id")&&b.trigger("a:deck:"+f(e._$element).attr("id")+":new-cards-added")},failure:function(a,c,h){b.trigger("a:deck:cards-added-fail",{xhr:a,status:c,errorThrown:h});f(e._$element).attr("id")&&b.trigger("a:deck:"+f(e._$element).attr("id")+":cards-added-fail",{xhr:a,status:c,errorThrown:h})}})}});b.on("ready", +function(){f(".a-cardui-deck").each(function(){c(this)})});return{get:function(a,h){return f(a).data("deckInstance")||c(a,h)}}});"use strict";l.when("A","a-component","prv:a-see-more","prv:a-expander-icon","p-detect","prv:csa-logger").register("prv:a-cardui-expand-control-footer",function(b,d,g,k,c,f){function a(a,c){a._$seeMore.toggleSeeMore(c.cardExpanded);a._$expanderIcon.toggleExpanderIcon(c.cardExpanded)}var p=d.create({_componentName:"carduiExpandControlFooter",init:function(a,c){this._super(a, +c);this._$expanderIcon=k.get(this._$element.find(".a-expander-icon"));this._$seeMore=g.get(this._$element.find(".a-see-more"));this._$button=this._$element.find(".a-cardui-expand-control-footer-button")},toggleExpansion:function(e){var h=this;c.capabilities.transition&&e.interactedOnce?b.fadeOut(h._$element,200,"linear",function(){a(h,e);b.fadeIn(h._$element,200)}):a(h,e)},getName:function(){return this._$element.attr("name")},getId:function(){return this._$element.attr("id")},addTrigger:function(a){this._$element.click(function(){b.trigger("a:card:"+ +a+":toggle",this)});this._$element.length&&f.element(this._$element.get(0),"click");this._$element.keypress(function(c){var e=b.constants.keycodes;c=c.which;c!==e.ENTER&&c!==e.SPACE||b.trigger("a:card:"+a+":toggle",this)});this._$element.length&&f.element(this._$element.get(0),"keypress")}});return{get:function(a,c){return new p(a,c)}}});"use strict";l.when("A","a-component","prv:csa-logger").register("prv:a-cardui-expand-control-title",function(b,d,g){var k=d.create({_componentName:"carduiExpandControlTitle", +init:function(c,b){this._super(c,b);this._$button=this._$element.find('span[role\x3d"button"]');this._$header=this._$element.find("h3")},getName:function(){return this._$element.attr("name")},getId:function(){return this._$element.attr("id")},addTrigger:function(c){this._$element.click(function(){b.trigger("a:card:"+c+":toggle",this)});this._$element.length&&g.element(this._$element.get(0),"click");this._$element.keypress(function(d){var a=b.constants.keycodes;d=d.which;d!==a.ENTER&&d!==a.SPACE|| +b.trigger("a:card:"+c+":toggle",this)});this._$element.length&&g.element(this._$element.get(0),"keypress")}});return{get:function(c,b){return new k(c,b)}}});"use strict";l.when("A","a-component").register("prv:a-cardui-teaser",function(b,d){var g=d.create({_componentName:"carduiTeaser",init:function(b,c){this._super(b,c)},getHeight:function(){return this._$element[0].scrollHeight}});return{get:function(b,c){return new g(b,c)}}});"use strict";l.when("A","a-component").register("prv:a-expander-icon", +function(b,d){var g=d.create({_componentName:"expanderIcon",init:function(b,c){this._super(b,c);this._$icon=this._$element.find(".a-css-icon")},toggleExpanderIcon:function(b){var c=b?"a-css-icon-expand":"a-css-icon-collapse";b=b?"a-css-icon-collapse":"a-css-icon-expand";this._$icon.addClass("a-css-icon-draw");this._$icon.removeClass(c).addClass(b)}});return{get:function(b,c){return new g(b,c)}}});"use strict";l.when("A","a-component","prv:a-cardui-scroll-viewport").register("a-reactive-container", +function(b,d,g){var k=d.create({_componentName:"reactiveContainer",init:function(c,b){this._super(c,b);this._$measured=!1;this._$element.addClass("a-reactive-container-transition")},setHeight:function(c){this._$element.css("height",c+"px");this._$measured?g.adjustScroll(this,parseFloat(c)):this._$measured=!0},resetInitialization:function(){this._$measured=!1},getHeight:function(){return this._$element.css("height")}});return{get:function(c,b){return new k(c,b)}}});"use strict";l.when("A","a-component").register("prv:a-see-more", +function(b,d){var g=d.create({_componentName:"seeMore",init:function(b,c){this._super(b,c);this._$seeMoreText=this._$element.find(".a-see-more-text");this._$seeLessText=this._$element.find(".a-see-less-text")},toggleSeeMore:function(b){b?(this._$seeMoreText.hide(),this._$seeLessText.show()):(this._$seeMoreText.show(),this._$seeLessText.hide())}});return{get:function(b,c){return new g(b,c)}}});"use strict";l.when("A").register("prv:a-cardui-scroll-viewport",function(b){return{adjustScroll:function(){}}}); +"use strict";l.when("A","prv:a-cardui-expand-control-title","prv:a-cardui-expand-control-footer","prv:a-cardui-teaser","prv:a-cardui-content","prv:a-reactive-container").register("prv:a-cardui-type-utility",function(b,d,g,k,c,f){return{getExpandControlTitle:function(a){return d.get(a._$element.find(".a-cardui-expand-control-title"))},getExpandControlFooter:function(a){return g.get(a._$element.find(".a-cardui-expand-control-footer"))},getTeaser:function(a){return k.get(a._$element.find(".a-cardui-teaser"))}, +getContent:function(a){return c.get(a._$element.find(".a-cardui-content"))},getReactiveContainer:function(a){a=a._$element.find(".a-reactive-container");return 0 f;f++)a.push("0123456789"[Math.floor(10*Math.random())]);return a.join("")},hasKeys:function(a,f){return f.every(function(c){return c in +a})}}});h.when("A","3p-promise","prv:a-modal-framework-constants").register("a-modal-framework-inline",function(a,e,f){return{getContent:function(a,d){var c="undefined"===typeof a.source?a:a.source;return new e(function(a,b){""!==c?(d.html(c),a()):b(f.errorMessages.EMPTY_CONTENT)})},abortContent:function(){}}});h.when("A","3p-promise","prv:a-modal-framework-constants").register("a-modal-framework-preload",function(a,e,f){var c=a.$,d=a.constants.HIDE_CLASS;return{getContent:function(a,g){if(a.source){var b= +c((0===a.source.indexOf("#")?"":"#")+a.source);return new e(function(a,c){0 b.indexOfArray(g,a))return e.error(a+" is not a valid status"),!1;b.each(g,function(a){f.removeClass(h[a]);d.prop("disabled",!1)});d.prop("disabled","disabled"===a);f.addClass(h[a]);return this},show:function(){this._$element.attr("data-a-visible",!0);return this},toggle:function(){"true"=== +this._$element.attr("data-a-visible")?this.hide():this.show();return this}});return function(a,b){return new c(a,b)}})}); +/* ******** */ +(function(g){var e=window.AmazonUIPageJS||window.P,h=e._namespace||e.attributeErrors,d=h?h("AmazonUIStepper","AmazonUI"):e;d.guardFatal?d.guardFatal(g)(d,window):d.execute(function(){g(d,window)})})(function(g,e,h){g.when("A","jQuery","a-analytics").register("a-stepper-framework",function(d,e,h){function m(a){var b=e(a).first();if(b.data("stepperinstance"))return b.data("stepperinstance");var c={getStatus:function(){return b.data("a-value-status")},getValue:function(){return b.data("steppervalue")}, +getName:function(){return b.attr("name")},setValue:function(a){p(b,a);return c},setStatus:function(a){n(b,a);return c}};b.data("stepperinstance",c);return c}function r(a,b){var c=a.find('[data-a-selector\x3d"decrement"]'),d=a.find('[data-a-selector\x3d"decrement-icon"]'),g=a.find('[data-a-selector\x3d"increment"]'),e=a.find('[data-a-selector\x3d"increment-icon"]'),f=b.steppervalue,h=f-b.valuestep =b.valuemax;f=h?"trash":"normal";var k=b?"disabled":"normal";a.attr("data-a-size");c.attr("aria-disabled", +h);d.removeClass().addClass("a-icon a-icon-small-"+{normal:"remove",disabled:"remove-disabled",trash:"trash"}[f]);a.attr("data-a-decrement-status",f);g.attr("aria-disabled",b);e.removeClass().addClass("a-icon a-icon-small-"+{normal:"add",disabled:"add-disabled"}[k]);a.attr("data-a-increment-status",k)}function k(a,b){var c=a.data();b=c.steppervalue+b*c.valuestep;b={$stepperElement:a,stepperElement:a.get(),stepper:m(a),newValue:b};d.trigger("a:stepper:value:change",b);(c=a.attr("name"))?d.trigger("a:stepper:value:change:"+ +c,b):h.logError("[AUI] Stepper is missing required name attribute.","WARN",d.attributionChain(a.get(0)))}function q(a,b){a.attr(b,"");a.one("animationend",function(){a.removeAttr(b)})}function n(a,b){var c=a.find('[data-a-selector\x3d"spinbutton"]'),e={loading:a.data().loadingstatelabel};if(0>d.indexOfArray(["normal","loading"],b))return g.error(b+" is not a valid status"),!1;a.attr("data-a-value-status",b);c.attr({"aria-valuetext":e[b]})}function p(a,b){var c=a.data(),d=c.steppervalue;if(d!==b){var e= +c.valuemax||Infinity,g=c.valuemin,f=c.valuestep,h=a.find('[data-a-selector\x3d"decrement-icon"]'),k=a.find('[data-a-selector\x3d"value"]'),m=b>d?"data-a-animate-down":"data-a-animate-up";f=g+f;var l;d===f&&b>f&&(l="data-a-animate-down");d>f&&b===f&&(l="data-a-animate-up");b e||(a.data("steppervalue",b),a.attr("data-steppervalue",b),c.steppervalue=b,r(a,c),l&&q(h,l),setTimeout(function(){var b=a.find('[data-a-selector\x3d"spinbutton"]'),d=a.find('[data-a-selector\x3d"value"]'),e=c.steppervalue, +f=c.valuemin,g=c.valuemaxreachedlabel,h=c.valueminreachedlabel,l=e;e>=c.valuemax&&(l=e+", "+g);e<=f&&(l=e+", "+h);b.attr({"aria-valuenow":e,"aria-valuetext":l});d.text(e);n(a,"normal");q(k,m)},116.5))}}d.declarative("a-stepper","click",function(a){a.$event.stopPropagation();a.$event.preventDefault()});d.declarative("a-stepper-spinbutton","keydown",function(a){var b=a.$currentTarget.closest('[data-a-component\x3d"stepper"]'),c=a.$event.which;38!==c&&40!==c||a.$event.preventDefault();40===c&&k(b,-1); +38===c&&k(b,1)});d.declarative("a-stepper-decrement","click",function(a){a=a.$currentTarget.closest('[data-a-component\x3d"stepper"]');0!==a.length&&k(a,-1)});d.declarative("a-stepper-increment","click",function(a){a=a.$currentTarget.closest('[data-a-component\x3d"stepper"]');0!==a.length&&k(a,1)});return{getStepper:m,setStatus:n,setValue:p}});"use strict";g.when("a-stepper-framework").register("a-stepper",function(d){return{getStepperByName:function(e){return d.getStepper(document.querySelector('[data-a-component\x3d"stepper"][name\x3d"'+ +e+'"]'))},getStepper:d.getStepper}})}); +/* ******** */ +(function(c){var b=window.AmazonUIPageJS||window.P,d=b._namespace||b.attributeErrors,a=d?d("AmazonUIToast","AmazonUI"):b;a.guardFatal?a.guardFatal(c)(a,window):a.execute(function(){c(a,window)})})(function(c,b,d){}); +/* ******** */ +(function(c){var a=window.AmazonUIPageJS||window.P,d=a._namespace||a.attributeErrors,b=d?d("AmazonUI","AmazonUI"):a;b.guardFatal?b.guardFatal(c)(b,window):b.execute(function(){c(b,window)})})(function(c,a,d){a.pcv=a.pcv||{};a.pcv.AmazonUI="eec2df32ac055c01b72150f9bb9e8eef63693331"}); +/* ******** */ diff --git a/Amazon_sources/Kindle_ Your Notes and Highlights_files/31bJewCvY-L.js.download b/Amazon_sources/Kindle_ Your Notes and Highlights_files/31bJewCvY-L.js.download new file mode 100644 index 0000000..89f5c5a --- /dev/null +++ b/Amazon_sources/Kindle_ Your Notes and Highlights_files/31bJewCvY-L.js.download @@ -0,0 +1,21 @@ +(function(c,m){function y(a){if(a)return a.replace(/^\s+|\s+$/g,"")}function x(a,g){if(!a)return{};var b="INFO"===g.logLevel;a.m&&a.m.message&&(a=a.m);var f=g.m||g.message||"";f=a.m&&a.m.message?f+a.m.message:a.m&&a.m.target&&a.m.target.tagName?f+("Error handler invoked by "+a.m.target.tagName+" tag"):a.m?f+a.m:a.message?f+a.message:f+"Unknown error";f={m:f,name:a.name,type:a.type,csm:N+" "+(a.fromOnError?"onerror":"ueLogError")};var h,l=0;f.logLevel=g.logLevel||A;g.adb&&(f.adb=g.adb);if(h=g.attribution)f.attribution= +""+h;if(!b){f.pageURL=g.pageURL||""+(window.location?window.location.href:"")||"missing";f.f=a.f||a.sourceURL||a.fileName||a.filename||a.m&&a.m.target&&a.m.target.src;f.l=a.l||a.line||a.lineno||a.lineNumber;f.c=a.c?""+a.c:a.c;f.s=[];f.t=c.ue.d();if((b=a.stack||(a.err?a.err.stack:""))&&b.split)for(f.csm+=" stack",h=b.split("\n");l c.ue_err.mxe)){c.ue_err.ter.push(a); +g=g||{};var b=a.logLevel||g.logLevel;g.logLevel=b;g.attribution=a.attribution||g.attribution;b&&b!==A&&b!==L&&b!==D&&b!==H||c.ue_err.ec++;b&&b!=A||ue_err.ecf++;B(a,g)}}if(c.ue_err&&(!c.ueLogError||c.ueLogError.isStub)){var K=c.ue_err_chan||"jserr",A="FATAL",L="ERROR",D="WARN",H="DOWNGRADED",N="v5",F=20,G=256,O=/\(?([^\s]*):(\d+):\d+\)?/,u=/.*@(.*):(\d*)/;B.skipTrace=1;x.skipTrace=1;C.skipTrace=1;(function(){if(c.ue_err.erl){var a=c.ue_err.erl.length,g;for(g=0;ga?"0"+a:a}function b(a){c.lastIndex=0;return c.test(a)?'"'+a.replace(c,function(a){var b=h[a]; +return"string"===typeof b?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function e(a,c){var d,w=n,k=c[a];k&&"object"===typeof k&&"function"===typeof k.toJSON&&(k=k.toJSON(a));"function"===typeof g&&(k=g.call(c,a,k));switch(typeof k){case "string":return b(k);case "number":return isFinite(k)?String(k):"null";case "boolean":case "null":return String(k);case "object":if(!k)return"null";n+=f;var r=[];if("[object Array]"===Object.prototype.toString.apply(k)){c=k.length;for(a= +0;a 1?decodeURIComponent(c[1]):"";a[d]=e}),a}function f(){return g.serviceName||"KindlePlayer"}b.queryParameters=e();var g=window.KindleGlobal,h=g.srsBaseHref||"https://"+window.location.hostname+"/service/web/",i=h+"reader/",j=h+"content/";b.getAuthenticatedBaseServiceUrl=c,b.getUnauthenticatedBaseServiceUrl=d,b.appConfig={version:g.appStaticVersion,versionForRS:g.appVersionForReadingStreams,deviceCapabilityVersion:g.deviceCapabilityVersion},b.getMetricsProgram=f});var __extends=this&&this.__extends||function(a,b){function c(){this.constructor=a}for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)};define("modules/utils/Errors",["require","exports"],function(a,b){"use strict";!function(a){a[a.GeneralLoggerInvalidPath=101]="GeneralLoggerInvalidPath",a[a.ReaderCreatePositionInvalidType=201]="ReaderCreatePositionInvalidType",a[a.ReaderViewInvalidActionInvoked=202]="ReaderViewInvalidActionInvoked",a[a.ReaderGetBookInfoUnknownFormat=203]="ReaderGetBookInfoUnknownFormat",a[a.ReaderMetadataImplUnknownFormat=204]="ReaderMetadataImplUnknownFormat"}(b.Codes||(b.Codes={}));var c=b.Codes,d=function(a){function b(b){if(a.call(this),this.message=b,this.name="KcrError",void 0===this.stack||""===this.stack)try{throw new Error}catch(c){this.stack=c.stack}}return __extends(b,a),b.prototype.setErrorCode=function(a){return this.errorCode=a,this},b.prototype.setCausedBy=function(a){return this.causedBy=a,this},b.prototype.toString=function(){return this.name+": "+(this.errorCode?"("+this.errorCode+" "+c[this.errorCode]+") ":"")+(this.message||"")},b}(Error);b.KcrError=d;var e=function(a){function b(b,c,d){a.call(this,b),this.message=b,this.url=c,this.status=d,this.name="HttpNetworkError"}return __extends(b,a),b.prototype.toString=function(){return a.prototype.toString.call(this)+" (URL="+this.url+"; HTTP status="+this.status+")"},b}(d);b.HttpNetworkError=e;var f=function(a){function b(b,c,d,e,f){a.call(this,b),this.message=b,this.url=c,this.jqXHR=d,this.textStatus=e,this.thrownError=f,this.name="JQueryAjaxError"}return __extends(b,a),b.prototype.toString=function(){return a.prototype.toString.call(this)+" (URL="+this.url+"; AJAX status="+this.textStatus+"; HTTP status="+this.jqXHR.status+"; HTTP error="+this.thrownError+")"},b}(d);b.JQueryAjaxError=f;var g=function(a){function b(b,c){a.call(this,b),this.message=b,this.rjsError=c,this.name="RequireJSError"}return __extends(b,a),b.prototype.toString=function(){var b=this.rjsError.requireModules&&this.rjsError.requireModules[0];return a.prototype.toString.call(this)+" (moduleName="+b+")"},b}(d);b.RequireJSError=g}),define("modules/utils/DeviceUtils",["require","exports","modules/utils/Errors"],function(a,b,c){"use strict";function d(){return-1!==M.indexOf("iPad")}function e(){return-1!==M.indexOf("iPhone")||-1!==M.indexOf("iPod")}function f(){return d()||e()}function g(){return!!M.match(/iPad;.*CPU.*OS 7_\d/i)}function h(){return!!M.match(/Android/i)}function i(){var a=!(!L.vendor||!L.vendor.match(/Amazon/i)),b=!(!M||!M.match(/KF[A-Z]{2}(WI|WA)/i));return h()&&(a||b)}function j(){return d()?"touchend":"click"}function k(){var a;if(f()?a=/OS\s(\d+)/i:h()&&(a=/Android\s(\d+(?:\.\d+)+)/i),a){var b=a.exec(M);if(b&&b.length>1)return parseInt(b[1],10)}throw new c.KcrError("Cannot get major version for the current user agent")}function l(){return!!M.match(/(Chrome|CriOS)/i)}function m(){return f()&&!q()&&!L.standalone}function n(){return M.indexOf("FB_IAB/FB4A")>=0}function o(){return h()&&(n()||s()||r()||!!window._cordovaNative||!!M.match(/WebView|; wv[;)]/i))}function p(){return m()||o()}function q(){return!!M.match(/Safari/i)}function r(){return!!M.match(/Twitter/i)}function s(){return!!M.match(/WhatsApp/i)}function t(){return window.KindleGlobal.deviceInfo&&window.KindleGlobal.deviceInfo.isDesktop}function u(){return!(f()||h()&&l())}function v(){return m()}function w(){return"ontouchstart"in window||!!L.msMaxTouchPoints}function x(){var a=window.KindleGlobal.deviceInfo;return a.name.toLowerCase().split(" ")[0]+"@"+a.version.split(".")[0]}function y(){return f()?"iOS":h()?"Android":t()?"Desktop":"Other"}function z(){return window.KindleGlobal.deviceInfo.deviceType}function A(){return n()}function B(){return q()&&f()?Math.min(window.innerHeight,$(window).height()):window.innerHeight}function C(){try{return f()&&7===k()}catch(a){return!1}}function D(){return-1!==M.indexOf("MSIE")||-1!==M.indexOf("Trident")}function E(){return-1!==M.indexOf("Firefox")}function F(){return!!M.match("Trident/[78].0")}function G(){return!!M.match("Edge/d+")}function H(){return D()||F()||G()}function I(){return F()}function J(){return D()}function K(){return D()}var L=window.navigator,M=L.userAgent;b.isIOS=f,b.isiPadiOS7=g,b.isAndroid=h,b.isFireOS=i,b.getClickEvent=j,b.getMobileOSMajorVersion=k,b.isChrome=l,b.isWebView=p,b.isSafari=q,b.isTwitter=r,b.isDesktop=t,b.requireDelayOnResize=u,b.shouldHideErrorDialogWhenNavigating=v,b.isTouchDevice=w,b.getBrowserWithMajorVersion=x,b.getDevicePlatform=y,b.getDeviceCategory=z,b.isFBOpenLinkWorkaroundNeeded=A,b.getWindowHeight=B,b.shouldSimulateClickForITunes=C,b.isFirefox=E,b.isMSBrowser=H,b.hasTransparentDivProblem=I,b.hasFullscreenCrashProblem=J,b.hasHammerSwipeClickBothFireProblem=K}),define("modules/utils/QueryParamUtils",["require","exports"],function(a,b){"use strict";function c(a){var b=new RegExp("[\\?&]"+a+"=([^]*)"),c=b.exec(location.search);return null===c?void 0:decodeURIComponent(c[1].replace(/\+/g," "))}function d(a,b){return b?a+(a.indexOf("?")<0?"?":"&")+b:a}function e(a,b){if(!b)return a;var c="";for(var d in b)c+=d+"="+b[d]+"&";return c.slice(0,-1),a+(a.indexOf("?")<0?"?":"&")+c}function f(a,b){var c=a.split("#",2),d=c[1],e=c[0].split("?",2),f=e[0],g=e[1]||"",h={};g.split("&").forEach(function(a){var b=a.split("=",2);2!==b.length||b[0]in h||(h[b[0]]=b[1])});var i;for(i in b){var j=b[i];null!==j&&void 0!==j?h[i]=b[i]:h[i]&&delete h[i]}g="";var k="?";for(i in h)g+=k+i+"="+h[i],k="&";return f+g+(d?"#"+d:"")}function g(a){return d(a,"sId="+window.KindleGlobal.requestInfo.sId)}b.getQueryParameter=c,b.appendQueryParams=d,b.appendQueryParamsMap=e,b.updateQueryParams=f,b.setSessionIdQueryParam=g}),define("modules/utils/RefTag",["require","exports","modules/utils/QueryParamUtils"],function(a,b,c){"use strict";function d(a){var c=window.KindleGlobal.requestInfo&&window.KindleGlobal.requestInfo.refTag;return c||(a?a+g():b.Constants.NO_REFTAG)}function e(a){return f(d(a))}function f(a){return j+"="+a}function g(){switch(window.KindleGlobal.error){case"UNSUPPORTED_BROWSER":return"_ub";case"GEO_LOCATION_NOT_ALLOWED":case"CONTENT_NOT_ALLOWED":return"_ip";case"CONTENT_NOT_SUPPORTED":return"_uc";default:return""}}function h(a){return window.KindleGlobal.endpointRefTag&&a?window.KindleGlobal.endpointRefTag+a:null}function i(a){var b=d();if(!a||a===b){var e={};e[j]=void 0;var f=c.updateQueryParams(window.location.href,e);window.history.replaceState(f,"",f)}}b.Constants={GET_APP_READER_FOOTER_SUFFIX:"_gka_rf",NO_REFTAG:"k4w_no_ref",RIK_SUFFIX:"_rik",BUY_ACTION_ON_READER_HEADER_SUFFIX:"_store_rh",VIEW_DETAILS_ON_READER_HEADER_SUFFIX:"_details_rh",BUY_ACTION_ON_LANDING_PAGE_SUFFIX:"_store_lp",BUY_ACTION_ON_END_ACTION_SUFFIX:"_store_ea",VIEW_DETAILS_ON_LANDING_PAGE_SUFFIX:"_dp_lp",VIEW_DETAILS_ON_END_ACTION_SUFFIX:"_dp_ea",GET_APP_END_ACTION_SUFFIX:"_gka_ea",TEXT_ME_SUFFIX:"_text_me",RIK_DESKTOP_SUFFIX:"_rik_desktop",VIEW_DETAILS_ON_ERROR_DIALOG:"_details_error",K4W_KA_NOTEBOOK:"k4w_ka_notebook"};var j="ref_";b.getRefTag=d,b.getRefTagQueryParam=e,b.formatRefTagForQS=f,b.formatError=g,b.getEndpointRefTag=h,b.removeRefTagFromUrl=i}),define("modules/metrics/ReadingStreams",["require","exports"],function(a,b){"use strict";function c(){return d||(d=new h),d}var d,e="Unknown",f=function(){function a(){}return a.OpenContext="OpenContext",a.ShowContext="ShowContext",a.HideContext="HideContext",a.OpenContent="OpenContent",a.Action="Action",a.ContentAction="ContentAction",a.ConsumeContentSpan="ConsumeContentSpan",a.ConsumeContentPoint="ConsumeContentPoint",a.AuxContentState="AuxContentState",a.Metadata="Metadata",a.SettingState="SettingState",a}();b.EventTypes=f;var g=function(){function a(){}return a.CONTEXT_KP="KindlePlayerClient",a.CONTEXT_KSHARE="KShare",a.CONTEXT_KSHARE_LANDING_PAGE_LOADED="KShareLandingPageLoaded",a.CONTEXT_KSHARE_LANDING_PAGE="KShareLandingPage",a.CONTEXT_KSHARE_END_ACTION="KShareEndAction",a.CONTEXT_COVER_PAGE="CoverPage",a.CONTEXT_READER="Reader",a.CONTEXT_PRE_AUTH="KSharePreAuth",a.CONTEXT_POST_AUTH="KSharePostAuth",a.CONTEXT_RIK_INTERSTITIAL="KShareRikInterstitial",a.CONTEXT_RIK_DESKTOP="RIKDesktop",a.CONTEXT_TEXT_ME="TextMe",a.CONTEXT_UNSUPPORTED_BROWSER="UnsupportedBrowser",a.CONTEXT_SHARING_DIALOG="SharingDialog",a.CONTEXT_ERROR_DIALOG="ErrorDialog",a.CONTEXT_PAGE_LOADED="KindlePlayerPageLoaded",a.CONTEXT_PDOC_SHARE_PAGE="PDocQuoteSharePage",a.ERROR_DP_URL_NOT_CONFIGURED="DetailPageUrlNotConfigured",a.ACTION_SCROLL="Scroll",a.ACTION_END_ACTION_BACK_BUTTON_CLICKED="BackClicked",a.ACTION_LEARN_MORE_CLICKED="LearnMoreClicked",a.ACTION_VIEW_FULL_DETAILS_CLICKED="ViewFullDetailsClicked",a.ACTION_NAVIGATION_ATTEMPT_PAST_BOOK_END="NavigationAttemptPastBookEnd",a.ACTION_CLOSE_BUTTON_CLICKED="CloseClicked",a.ACTION_OVERLAY_CLICKED="OverlayClicked",a.ACTION_PREVIEW_BOOK_BUTTON_CLICKED="PreviewBookClicked",a.ACTION_LANDING_PAGE_SWIPE_LEFT="LandingPageSwipeLeft",a.ACTION_END_ACTION_SWIPE_RIGHT="EndActionSwipeRight",a.ACTION_LEFT_ARROW_PRESSED="KeyPressed = =LeftArrow",a.ACTION_RIGHT_ARROW_PRESSED="KeyPressed = =RightArrow",a.ACTION_ESC_PRESSED="KeyPressed = =Escape",a.ACTION_SHARE_CLICKED="ShareClicked",a.ACTION_SHARE_CHANNEL_CLICKED="ShareChannelClicked",a.ACTION_SLIDER_CLICKED="SliderClicked",a.ACTION_SLIDER_DRAGGED="SliderDragged",a.ACTION_SLIDER_DRAGGED_DISTANCE="SliderDragged::Distance",a.ACTION_OPEN_KCR="OpenKCR",a.ACTION_TEXT_ME="TextMe",a.ACTION_WISH_LIST_CLICKED="AddToWishListClicked",a.ACTION_DOWNLOAD_CHROME_CLICKED="DownloadChromeClicked",a.ACTION_DOWNLOAD_FIREFOX_CLICKED="DownloadFirefoxClicked",a.ACTION_DOWNLOAD_IE_CLICKED="DownloadIEClicked",a.ACTION_DOWNLOAD_SAFARI_CLICKED="DownloadSafariClicked",a.ACTION_BUY_BUTTON_CLICKED="BuyClicked",a.ACTION_GET_KINDLE_APP_CLICKED="GetKindleAppClicked",a.ACTION_SHOW_MORE_COLLAPSED_QUOTE="ShowMore = =Collapsed = =Quote",a.ACTION_SHOW_MORE_COLLAPSED_SYNOPSIS="ShowMore = =Collapsed = =Synopsis",a.ACTION_SHOW_MORE_EXPANDED_QUOTE="ShowMore = =Expanded = =Quote",a.ACTION_SHOW_MORE_EXPANDED_SYNOPSIS="ShowMore = =Expanded = =Synopsis",a.ACTION_CONDITIONS_OF_USE_CLICKED="ConditionsOfUseClicked",a.ACTION_PRIVACY_NOTICE_CLICKED="PrivacyNoticeClicked",a.ACTION_LEGAL_NOTICES_CLICKED="LegalNoticesClicked",a.ACTION_LOGOUT_CLICKED="LogoutClicked",a.ACTION_RETRY_CLICKED="RetryClicked",a.CONTEXT_NOTEBOOK_PAGE="NotebookPage",a.CONTEXT_NOTEBOOK_PAGE_EMPTY_LIB="NotebookPageEmptyLib",a.CONTEXT_NOTEBOOK_PAGE_EMPTY_ANNOTATIONS="NotebookPageEmptyAnnotations",a.CONTEXT_ERROR_ALERT="ErrorAlert",a.ACTION_NOTEBOOK_PAGE_ANNOTATIONS_LOAD_FAIL="NotebookPageAnnotationsLoadFail",a.ACTION_NOTEBOOK_PAGE_LIBRARY_LOAD_FAIL="NotebookPageLibraryLoadFail",a.ACTION_NOTEBOOK_SEARCH_SUBMITTED="NotebookSearchSubmitted",a.ACTION_NOTEBOOK_SEARCH_RESULTS_FOUND="NotebookSearchResultsFound",a.ACTION_DETAIL_PAGE_CLICKED="DetailPageUrlClicked",a.ACTION_OPEN_IN_KINDLE_TRIGGER="OpenInKindleTrigger",a.ACTION_OPEN_IN_KINDLE_SUCCESS="OpenInKindleSuccess",a.ACTION_OPEN_IN_KINDLE_FAIL="OpenInKindleFail",a.ACTION_HIGHLIGHT_DELETED="HighlightDeleted",a.ACTION_NOTE_DELETED="NoteDeleted",a.ACTION_NOTE_ADDED="NoteAdded",a.ACTION_NOTE_EDITED="NoteEdited",a.ACTION_HIGHLIGHTS_NOTES_COPY="HighlightsNotesCopy",a.ACTION_HIGHLIGHT_TRUNCATED="HighlightTruncated",a.ACTION_HIGHLIGHT_HIDDEN="HighlightHidden",a.ACTION_HIGHLIGHT_EMPTY_TEXT="HighlightEmptyText",a}();b.RSConstants=g;var h=function(){function a(){this.events=[],this.CONTEXT_CHANGE_IMMERSIVE_FOOTER="ReaderFontSizeChangeFooter",this.CONTEXT_CHANGE_IMMERSIVE_HEADER="ReaderChangeImmersiveHeader",this.CONTEXT_READER="Reader",this.CONTEXT_SHARING_DIALOG="SharingDialog",this.CONTEXT_JS_ERROR="JSError",this.ACTION_FONT_SIZE_CHANGE="FontSizeChange",this.ACTION_CONTENT_NOT_RENDERED_IN_TIME="BookContentNotRenderedInTime",this.ACTION_BUY_BUTTON_CLICKED="BuyClicked",this.ACTION_GET_KINDLE_APP_CLICKED="GetKindleAppClicked",this.ACTION_READ_IN_KINDLE_CLICKED="ReadInKindleClicked",this.ACTION_WISH_LIST_CLICKED="AddToWishListClicked",this.ACTION_VIEW_FULL_DETAILS_CLICKED="ViewFullDetailsClicked",this.ACTION_LEARN_MORE_CLICKED="LearnMoreClicked",this.ACTION_CLOSE_CLICKED="CloseClicked",this.ACTION_SHARE_CLICKED="ShareClicked",this.ACTION_SHARE_CHANNEL_CLICKED="ShareChannelClicked",this.SPAN_TYPE_TEXT="Text",this.ERROR_DP_URL_NOT_CONFIGURED="DetailPageUrlNotConfigured",this.UNHANDLED_REJECTION="UnhandledRejection",this.ACTION_SLIDER_CLICKED="SliderClicked",this.ACTION_SLIDER_DRAGGED="SliderDragged",this.ACTION_SLIDER_DRAGGED_DISTANCE="SliderDragged::Distance",this.ACTION_REGION_MAGNIFICATION_ACTIVATE="RegionMagnificationEnabled",this.ACTION_REGION_MAGNIFICATION_DEACTIVATE="RegionMagnificationDisabled",this.ACTION_REGION_MAGNIFICATION_FORWARD="RegionMagnificationForward",this.ACTION_REGION_MAGNIFICATION_BACKWARD="RegionMagnificationBackward"}return a.prototype.getEvents=function(){return this.events.slice(0)},a.prototype.clearEvents=function(a){var b=this.events;b.splice(0,a&&a ").html(a).text()}function f(a){var b=new RegExp("\r\n","g"),c=new RegExp("\n","g");return d(a).replace(b,"
").replace(c,"
")}function g(a){var b=new RegExp("
","g");return e(a.replace(b,"\n"))}var h=/\${([\w_]+)}/g;b.format=c,b.escapeHTML=d,b.unescapeHTML=e,b.escapeAndFormatHTML=f,b.unescapeAndFormatHTML=g}),define("modules/utils/Utility",["require","exports","modules/utils/DeviceUtils","modules/metrics/MetricsUtils","modules/utils/QueryParamUtils","modules/metrics/ReadingStreams","modules/utils/RefTag","modules/utils/StringUtils"],function(a,b,c,d,e,f,g,h){"use strict";function i(a,b){var c=window;c.Kindle=c.Kindle||{},c.Kindle[a]=b}function j(){return window.KindleGlobal.requestInfo&&window.KindleGlobal.requestInfo.associateTag}function k(){var a=j();return a?"tag="+a:null}function l(){return window.KindleGlobal&&window.KindleGlobal.requestInfo?window.KindleGlobal.requestInfo.embedPreviewMode:void 0}function m(a,b){var c=g.getEndpointRefTag(b);a=e.appendQueryParams(a,g.getRefTagQueryParam(c));var d=k();d&&(a=e.appendQueryParams(a,d));var f=window.KindleGlobal.requestInfo;return f.linkCode&&(a=e.appendQueryParams(a,"linkCode="+f.linkCode)),f.linkType&&(a=e.appendQueryParams(a,"linkType="+f.linkType)),f.linkId&&(a=e.appendQueryParams(a,"linkId="+f.linkId)),a}function n(a){return h.format(window.KindleGlobal.readUrlTemplate,{path:a||""})}function o(a,b){var d=g.getRefTag(b),f=g.formatRefTagForQS(d);if(c.isIOS())f="ct="+d;else if(c.isAndroid()){var h=g.formatRefTagForQS(d),i=k();i&&(h+="&"+i),f="referrer="+encodeURIComponent("utm_source=kindle_player&utm_content="+encodeURIComponent(window.btoa(h)))}return e.appendQueryParams(a,f)}function p(a){$("",{href:a})[0].click()}function q(a,b,c){function d(){var a=$(this).is(":hidden")?this.naturalHeight:$(this).height(),d=$(this).is(":hidden")?this.naturalWidth:$(this).width();x>a&&x>d?c&&c(this):b&&b(this)}a.load(d).each(function(){this.complete&&$(this).load()})}function r(a,b){window.open(a,"_blank",b||"")}function s(a,b,c){void 0===b&&(b=y);var d,e,f=!1;return function(){var g=c||this,h=Date.now();f||d&&!(h>=d+b)||(f=!0,a.apply(g,arguments),clearTimeout(e),e=setTimeout(function(){d=h,f=!1},b))}}function t(a,b,c){void 0===b&&(b=y);var d;return function(){var e=c||this,f=Date.now();(!d||f>=d+b)&&a.apply(e,arguments),d=f}}function u(){var a=window.location;return a.origin||a.protocol+"//"+a.hostname+(a.port?":"+a.port:"")}function v(){var a=window.location.search;return!!a&&-1!==a.indexOf("from=Bookcard")}function w(a,b,c){!function(e){var g=f.getManager();if(!e)return void d.recordAction(c,g.ERROR_DP_URL_NOT_CONFIGURED);d.recordAction(c,g.ACTION_VIEW_FULL_DETAILS_CLICKED);var h=m(e,b);a?r(h):window.open(h,"_self","")}(window.KindleGlobal.bookDetailPageUrl)}var x=5,y=200;b.addToGlobalKindle=i,b.getAssociateTag=j,b.getEmbedPreviewMode=l,b.getAmazonAttributedUrl=m,b.getReadUrl=n,b.getAppStoreUrlWithRefTag=o,b.simulateClickForLink=p,b.checkImageLoaded=q,b.openInNewWindow=r,b.throttled=s,b.debounced=t,b.getOrigin=u,b.isFromBookCard=v,b.openBookDetails=w}),define("modules/metrics/PMET",["require","exports","modules/utils/Config","modules/utils/DeviceUtils","modules/utils/RefTag","modules/utils/Utility"],function(a,b,c,d,e,f){"use strict";function g(a){return a&&a.match(v)?a.replace(w,""):a}function h(){var a={};return a[u.Version]=c.appConfig.version,a[u.Browser]=d.getBrowserWithMajorVersion(),a[u.RefTag]=g(e.getRefTag()),a[u.AssociateTag]=f.getAssociateTag(),a[u.EmbedPreviewMode]=f.getEmbedPreviewMode(),a}function i(){return window.performance.now()}function j(){return A.slice(0)}function k(a){A.splice(0,a&&aE}function q(){if(p()){var a=0;for(var c in B){var d=B[c];a+=d.mainTimer.discardRunningTimers();for(var e in d.timers){a+=d.timers[e].discardRunningTimers()}}m(l(b.Constants.SUSPEND_DETECTED));var d=l(b.Constants.DISCARDED_METRIC_TIMERS_AFTER_SUSPEND);d.mainCounter.increment(a+t),m(d),t=0,console.warn("Client exceeded suspend time threshold; discarded %d running metric timer(s)",a)}o()}function r(a){C=a}window.performance=window.performance||{},window.performance.now=window.performance.now||Date.now,b.Constants={BOOK_CONTENT_RENDERED:"BookContentRendered",LOCAL_CONTENT:"LocalContent",REMOTE_CONTENT:"RemoteContent",QUARTILE_STARTED:"QuartileStarted",SUSPEND_DETECTED:"SuspendDetected",DISCARDED_METRIC_TIMERS_AFTER_SUSPEND:"DiscardedMetricTimersAfterSuspend",NOTEBOOK_PAGE_LOADED:"NotebookPageLoaded",NOTEBOOK_PAGE_LIBRARY_LOADED:"NotebookPageLibraryLoaded",NOTEBOOK_PAGE_ANNOTATIONS_LOADED:"NotebookPageAnnotationsLoaded"};var s="::",t=0,u={OS:"OS",Browser:"Browser",Version:"Version",RefTag:"RefTag",AssociateTag:"AssociateTag",EmbedPreviewMode:"EmbedPreviewMode"},v=/^(cm_sw|k4w_oembed)/i,w=/_[^_]+$/i;b.getBreakdownMap=h;var x=function(){function a(a,b){void 0===b&&(b=0),this.name=a,this.count=b,this.count=b,this.breakdown=[]}return a.prototype.increment=function(a){return void 0===a&&(a=1),this.count+=a,this},a}();b.Counter=x;var y=function(){function a(a){this.name=a,this.time=0,this.count=0,this.started=[],this.breakdown=[]}return a.prototype.start=function(){return this.started.push(i()),this},a.prototype.stop=function(){return this.started.length>0?p()?(this.started.pop(),t++,console.warn("Discarded a running timer in Timer.stop() because client suspend was detected")):(this.time+=i()-this.started.pop(),this.count++):console.warn("Extra StopTimer called for timer: "+this.name),this},a.prototype.startTimer=function(){return this.start(),this},a.prototype.stopTimer=function(){return this.stop(),this},a.prototype.discardRunningTimers=function(){var a=this.started.length;return this.started=[],a},a.prototype.setTime=function(a){return this.time=a,this},a}();b.Timer=y;var z=function(){function a(a,b){void 0===b&&(b=!1),this.name=a,this.reportedName=a,this.counters={},this.timers={},this.breakdown=[],this.properties={},this.mainTimer=new y(this.name),b&&this.mainTimer.start(),this.mainCounter=new x(this.name)}return a.prototype.getSubTimer=function(a){return this.timers[a]=this.timers[a]||new y(a),this.timers[a]},a.prototype.getSubCounter=function(a){return this.counters[a]=this.counters[a]||new x(a),this.counters[a]},a.prototype.incrementSubCounter=function(a,b){return void 0===b&&(b=1),this.getSubCounter(a).increment(b),this},a.prototype.increment=function(){return this.mainCounter.increment(),this},a.prototype.startTimer=function(){return this.mainTimer.start(),this},a.prototype.stopTimer=function(){return this.mainTimer.stop(),this},a.prototype.appendToReportedName=function(){for(var a=[],b=0;b =b?(d(e,j,k),void c.record(c.createMetric("AjaxErrorAfterRetry"))):void setTimeout(function(){console.debug("Retrying ajax request ("+b+" remaining)..."),g.ajax(a).done().then(h,i(b-1))},f)}}void 0===e&&(e=3),void 0===f&&(f=3e3),g.ajax(a).done().then(b,i(e))}function j(a){function b(a){e.resolve(a)}function c(b,c,d){e.reject(new f.JQueryAjaxError(a.serviceCall||"JQuery ajax error",a.url,b,c,d))}var e=d.defer();return i(a,b,c),e.promise}function k(a){var b={url:a.url,serviceCall:a.serviceCall,dataType:"json"};return b.beforeSend=function(a){return a.setRequestHeader("Amzn-Device-Type",r),!0},a.postData&&(b.type="POST",b.contentType="application/json",b.processData=!1,b.data=JSON.stringify(a.postData)),void 0!==a.async&&(b.async=a.async),j(b)}function l(a){var b={url:a.url,serviceCall:a.serviceCall,dataType:"json"},c=window.KindleGlobal.srsDeviceToken;return b.beforeSend=function(a){return a.setRequestHeader("Amzn-Device-Type",r),a.setRequestHeader("X-ADP-Session-Token",c),!0},a.postData&&(b.type="POST",b.contentType="application/json",b.processData=!1,b.data=JSON.stringify(a.postData)),void 0!==a.async&&(b.async=a.async),j(b)}function m(a){function b(){var b=a.useAuthenticated?s:t;return b+="startReading?asin="+a.asin,a.kindleSessionId&&(b+="&kindleSessionId="+a.kindleSessionId),a.contentVersion&&(b+="&contentVersion="+a.contentVersion),a.formatVersion&&(b+="&formatVersion="+a.formatVersion),void 0!==a.isSample&&(b+="&isSample="+(a.isSample?"true":"false")),window.KindleGlobal.capabilities.ALLOW_FULL_BOOK&&(b+="&checkSubscription=true"),b+=u,encodeURI(b)}return a.useAuthenticated?l({url:b(),serviceCall:"startReading"}):k({url:b(),serviceCall:"startReading"})}function n(a){function b(){var b=a.useAuthenticated?s:t;return b+="getFileUrl?asin="+a.asin,a.kindleSessionId&&(b+="&kindleSessionId="+a.kindleSessionId),a.contentVersion&&(b+="&contentVersion="+a.contentVersion),a.formatVersion&&(b+="&formatVersion="+a.formatVersion),void 0!==a.isSample&&(b+="&isSample="+(a.isSample?"true":"false")),a.skeletonIds&&(b+="&skeletonIds="+a.skeletonIds.join(",")),a.fragmentIds&&(b+="&fragmentIds="+a.fragmentIds.join(",")),a.glyphIds&&(b+="&glyphIds="+a.glyphIds.join(",")),a.resourceIds&&(b+="&resourceIds="+a.resourceIds.join(",")),a.locationMapIds&&(b+="&locationMapIds="+a.locationMapIds.join(",")),window.KindleGlobal.capabilities.ALLOW_FULL_BOOK&&(b+="&checkSubscription=true"),encodeURI(b)}return a.useAuthenticated?l({url:b(),serviceCall:"getFileUrl"}):k({url:b(),serviceCall:"getFileUrl"})}function o(a){function b(){var b=s;return b+="stillReading?asin="+a.asin,a.guid&&(b+="&guid="+encodeURIComponent(a.guid)),a.kindleSessionId&&(b+="&kindleSessionId="+a.kindleSessionId),a.lastPageRead&&(b+="&lastPageRead="+a.lastPageRead),a.localTimeOffset&&(b+="&localTimeOffset="+a.localTimeOffset),a.positionType&&(b+="&positionType="+encodeURIComponent(a.positionType)),window.KindleGlobal.capabilities.ALLOW_FULL_BOOK&&(b+="&checkSubscription=true"),b}return l({url:b(),serviceCall:"stillReading"})}function p(a){function b(){var b=s;return b+="doneReading?asin="+a.asin,a.guid&&(b+="&guid="+encodeURIComponent(a.guid)),a.kindleSessionId&&(b+="&kindleSessionId="+a.kindleSessionId),a.lastPageRead&&(b+="&lastPageRead="+a.lastPageRead),a.localTimeOffset&&(b+="&localTimeOffset="+a.localTimeOffset),a.positionType&&(b+="&positionType="+encodeURIComponent(a.positionType)),window.KindleGlobal.capabilities.ALLOW_FULL_BOOK&&(b+="&checkSubscription=true"),b}return l({url:b(),serviceCall:"doneReading"})}function q(b,c,d,e,g){function h(c){var i=c.requireModules,j=new Array;i.forEach(function(a){if(v.hasOwnProperty(a)||(v[a]=d),0>=v[a])throw g&&g(c),new f.RequireJSError("Failed to require library '"+a+"' using RequireJS.",c);requirejs.undef(a),v[a]--,j.push(a)}),setTimeout(function(){console.debug("Retrying RequireJS requests..."),a(b,null,h)},e)}void 0===d&&(d=3),void 0===e&&(e=3e3),a(b,c,h)}var r=window.KindleGlobal.amazonDeviceType,s=e.getAuthenticatedBaseServiceUrl(),t=e.getUnauthenticatedBaseServiceUrl(),u="&clientVersion="+e.appConfig.deviceCapabilityVersion;b.qJsonpUsingAjax=h,b.qAjax=j,b.ajaxUnauthenticated=k,b.ajaxAuthenticated=l,b.startReading=m,b.getFileUrl=n,b.stillReading=o,b.doneReading=p;var v={};b.requireWithRetry=q}),define("modules/utils/ReaderViewLoader",["require","exports","modules/utils/Service"],function(a,b,c){"use strict";function d(a){c.requireWithRetry(["KindlePlayerLoader"],function(){c.requireWithRetry(["KindlePlayer"],function(b){a(b)})})}b.whenReaderReady=d}),define("modules/metrics/MetricsUtils",["require","exports","./PMET","./ReadingStreams","modules/errors/JqueryPromiseErrorHandler","modules/utils/Service","modules/utils/ReaderViewLoader"],function(a,b,c,d,e,f,g){"use strict";function h(a,b,e,f){void 0===e&&(e={}),void 0===f&&(f=null),c.record(c.createMetric(b).appendToReportedName(a)),d.getManager().performAction(a,b,e,f)}function i(a,b){void 0===b&&(b={}),c.record(c.createMetric("Viewed").appendToReportedName(a)),d.getManager().showContext(a,b)}function j(a){t=a}function k(){return t}function l(){return!u||"pending"!==u.state()&&"resolved"!==u.state()?(u=$.Deferred(),g.whenReaderReady(function(){f.requireWithRetry(["modules/metrics/ReadingStreams","modules/metrics/PMET","modules/metrics/MetricsUtils"],function(a,b,c){a&&a.getManager?u.resolve(a.getManager(),b,c):u.reject(new Error("Metrics Managers not properly loaded"))})}),u.promise()):u.promise()}function m(){return v?v.promise():(v=$.Deferred(),$(document).ready(function(){g.whenReaderReady(function(){f.requireWithRetry(["modules/metrics/UploadManager"],function(a){a.init(),v.resolve(a)})})}),v.promise())}function n(a,b){var c=$.Deferred();return h(a,b),m().then(function(a){a.uploadMetrics(!0),c.resolve()}),c.promise()}function o(a,b,c){l().then(function(d,e){d.showContext(a,b||{},c);var f=e.createMetric("Viewed").appendToReportedName(a);w[f.reportedName]||(e.record(f),w[f.reportedName]=1)},e.onPromiseRejected)}function p(a,b,c){l().then(function(d){d.hideContext(a,b||{},c)},e.onPromiseRejected)}function q(a,b){var c=$.Deferred();return l().always(function(d,e){var f=e.createMetric(a);b&&f.appendToReportedName(b),e.record(f),c.resolve()}),c.promise()}function r(a,b,c){l().then(function(d,e){"string"==typeof a&&(a=e.createMetric(a)),e.record(a),b.name=a.reportedName,d.recordMetadata(c,b)},e.onPromiseRejected)}function s(){return{timezoneOffset:(new Date).getTimezoneOffset()}}var t,u,v,w={};b.recordAction=h,b.recordViewShown=i,b.setCurrentContainerView=j,b.getCurrentContainerView=k,b.getManagers=l,b.recordActionAndUploadMetrics=n,b.recordShowContext=o,b.recordHideContext=p,b.recordPMET=q,b.recordPMETAndRSMetadata=r,b.getInitialRSMetadata=s}),define("modules/utils/LocalStorage",["require","exports"],function(a,b){"use strict";function c(){var a="testLocalStorage",b="1";try{if(!window.localStorage)return!1;if(window.localStorage.setItem(a,b),window.localStorage.getItem(a)!==b)return!1}catch(c){return!1}return!0}function d(a){return void 0===a&&(a=e),c()?new h(a):new g(a)}var e="KindlePlayer",f={},g=function(){function a(a){this.namespace=a,f[a]||(f[a]={}),this.data=f[a]}return a.prototype.getItem=function(a){return this.data[a]},a.prototype.setItem=function(a,b){this.data[a]=b},a.prototype.removeItem=function(a){var b=this.data[a];return delete this.data[a],b}, +a.prototype.clear=function(){this.data={},delete f[this.namespace]},a}();b.MemoryStorage=g;var h=function(){function a(a){this.namespace=a;var b=window.localStorage.getItem(a);this.data=b&&JSON.parse(b)||{}}return a.prototype.getItem=function(a){return this.data[a]},a.prototype.setItem=function(a,b){this.data[a]=b,window.localStorage.setItem(this.namespace,JSON.stringify(this.data))},a.prototype.removeItem=function(a){var b=this.data[a];return delete this.data[a],window.localStorage.setItem(this.namespace,JSON.stringify(this.data)),b},a.prototype.clear=function(){this.data={},window.localStorage.removeItem(this.namespace)},a}();b.LocalStorage=h,b.getStorage=d}),define("modules/metrics/UploadManager",["require","exports","modules/utils/Config","modules/utils/Service","modules/metrics/MetricsUtils","modules/metrics/PMET","modules/metrics/ReadingStreams","modules/utils/LocalStorage","modules/utils/DeviceUtils","jquery"],function(a,b,c,d,e,f,g,h,i,j){"use strict";function k(a){function b(){var a=o;return a+="uploadMetrics"}function c(){return{devicePlatform:a.devicePlatform,clientName:a.clientName,version:a.version,versionForCapability:a.versionForRS,versionForRS:a.versionForRS,messageNumber:a.messageNumber,sessionId:a.sessionId,metricBreakdown:a.breakdowns,metrics:a.metrics,readingStreamsMetrics:a.readingStreamsMetrics,marketplace:a.marketplace,pfm:a.pfm}}var e={Input:c(),Operation:"uploadMetricsExternal"},f=!a.isSync,g={url:b(),serviceCall:"uploadMetrics",postData:e,async:f};return console.debug("Uploading metrics:",e.Input),d.ajaxUnauthenticated(g).then(function(a){return a})}function l(a){function b(){x=!1,"hidden"!==document.visibilityState&&m()}if(!x){x=!0;var c=j.map(f.getBreakdownMap(),function(a,b){return b}),d=parseInt(u.getItem(v)||"0",10),e=j.map(t.getEvents(),function(a){return JSON.stringify(a)}),g=j.map(f.getMetrics(),function(a){return{method:a.reportedName,time:a.mainTimer.time,count:a.mainCounter.count,breakdown:c,properties:a.properties,counters:j.map(a.counters,function(a){return{name:a.name,count:a.count,breakdown:c}}),timers:j.map(a.timers,function(a){return delete a.started,a.breakdown=c,a})}});z.push.apply(z,e),y.push.apply(y,g),t.clearEvents(e.length),f.clearMetrics(g.length),z.length>0||y.length>0?(k({devicePlatform:p,clientName:q,marketplace:window.KindleGlobal.marketplace,pfm:window.KindleGlobal.pfm,breakdowns:f.getBreakdownMap(),version:r,versionForCapability:s,versionForRS:s,messageNumber:d,sessionId:window.KindleGlobal.requestInfo&&window.KindleGlobal.requestInfo.sId,metrics:y,readingStreamsMetrics:z,isSync:a}).then(function(){y=[],z=[]}).finally(b).catch(function(a){console.warn("Error occurred during uploadMetrics() attempt (will try again shortly):",a)}),u.setItem(v,(d+1).toString())):b()}}function m(){B&&clearTimeout(B),B=setTimeout(l,A)}function n(){function a(){var a=e.getCurrentContainerView();a&&(t.hideContext(a),f.record(f.createMetric("ClosedTab").appendToReportedName(a))),l(!0)}w||(w=!0,m(),document.addEventListener("visibilitychange",function(){var a=e.getCurrentContainerView();"hidden"===document.visibilityState?(a&&t.hideContext(a),l()):(a&&t.showContext(a),m())}),j(window).bind("unload",a),window.addEventListener("beforeunload",function(){j(window).unbind("unload",a),a()}))}var o=c.getUnauthenticatedBaseServiceUrl(),p=window.KindleGlobal.amazonDeviceType+":"+i.getDeviceCategory(),q=c.getMetricsProgram(),r=c.appConfig.version,s=c.appConfig.versionForRS,t=g.getManager(),u=h.getStorage(),v="messageNumber",w=!1,x=!1,y=[],z=[],A=2e3;b.uploadMetrics=l;var B;b.init=n}),define("modules/marketplace/Marketplace",["require","exports"],function(a,b){"use strict";var c=function(){function a(){this.USAmazon={marketplaceCode:"us"},this.CAAmazon={marketplaceCode:"ca"},this.BRAmazon={marketplaceCode:"br"},this.AUAmazon={marketplaceCode:"au"},this.MXAmazon={marketplaceCode:"mx"},this.GBAmazon={marketplaceCode:"uk"},this.DEAmazon={marketplaceCode:"de"},this.FRAmazon={marketplaceCode:"fr"},this.ITAmazon={marketplaceCode:"it"},this.ESAmazon={marketplaceCode:"es"},this.INAmazon={marketplaceCode:"in"},this.JPAmazon={marketplaceCode:"jp"},this.CNAmazon={marketplaceCode:"cn"},this.NLAmazon={marketplaceCode:"nl"},this.RUAmazon={marketplaceCode:"ru"}}return a}();b.AmazonMarketplaces=c;var d=new c;b.default=d}),define("modules/utils/ReadInKindle",["require","exports","modules/utils/DeviceUtils","modules/metrics/PMET","modules/metrics/ReadingStreams","modules/utils/RefTag","modules/utils/Utility","modules/utils/QueryParamUtils","modules/marketplace/Marketplace"],function(a,b,c,d,e,f,g,h,i){"use strict";function j(){var a=k();console.debug("Opening URL for RIK: "+a),c.isFBOpenLinkWorkaroundNeeded()?window.location.href=a:g.openInNewWindow(a)}function k(){var a,e=d.createMetric(b.metricsPrefix);return c.isAndroid()&&!c.isFireOS()&&q.marketplace!==i.default.CNAmazon.marketplaceCode?(d.record(e.appendToReportedName("Interstitial")),a=g.getReadUrl(q.appName+"-rik")):(d.record(e.appendToReportedName("PreAuth")),a=g.getReadUrl(q.appName+"-pre-auth"),c.isFireOS()&&(a=h.appendQueryParams(a,"fos=true")),c.isIOS()&&(a=a.replace(/^https/,"http"),a=h.updateQueryParams(a,{type:"EBSP",ref:"kindleplayer"}))),h.setSessionIdQueryParam(a)}function l(){if(c.isIOS()){var a=f.getEndpointRefTag(f.Constants.RIK_SUFFIX),b=g.getAppStoreUrlWithRefTag(window.KindleGlobal.appStoreUrl,a),d=window.KindleGlobal.openAppUrl;b&&d&&n(d,b)}}function m(a){var b=document.createElement("iframe");return b.style.display="none",document.body.appendChild(b),b.src=a,b}function n(a,c){var e=m(a),f=b.metricsPrefix+"::DeepLinking",g=d.createMetric(f);d.record(g.appendToReportedName(t)),p.recordMetadata(f,{status:t});var h=d.createMetric(f),i=Date.now();setTimeout(function(){Date.now()-i>r+s?(e.parentNode.removeChild(e),e=null,d.record(h.appendToReportedName(v)),p.recordMetadata(f,{status:v})):document.webkitHidden||document.hidden||(d.record(h.appendToReportedName(u)),p.recordMetadata(f,{status:u}),o(c))},r)}function o(a){console.debug("Opening URL for RIK: "+a),window.location.href=a}var p=e.getManager(),q=window.KindleGlobal,r=1e3,s=500;b.metricsPrefix="ReadInKindle";var t="DeepLinkingAttempted",u="OpenedFallback",v="TimeExceeded";b.trigger=j,b.performDeepLinkingIfPossible=l}),define("modules/ui/views/PreAuth",["require","exports","modules/errors/JqueryPromiseErrorHandler","modules/metrics/ReadingStreams","modules/metrics/MetricsUtils"],function(a,b,c,d,e){"use strict";return function(){function a(){var a=$("#kp-pre-auth-sign-in-button"),c=window.KindleGlobal.signinUrl;a.on("click",function(){e.recordPMET(b,"SignIn").always(function(){window.location.href=c})});var d=$("#kp-pre-auth-change-account-button"),f=window.KindleGlobal.forceSigninUrl;d.on("click",function(){e.recordPMET(b,"ChangeAccount").always(function(){window.location.href=f})})}var b="ReadInKindle::PreAuth";b+=window.KindleGlobal.requestInfo.auth?"::Authenticated":"::Unauthenticated",$(document).ready(function(){if("PreAuth"===window.KindleGlobal.page){var b=d.RSConstants.CONTEXT_PRE_AUTH;e.getManagers().then(function(a,c,d){d.setCurrentContainerView(b)},c.onPromiseRejected),e.recordShowContext(b),a()}})}()}),define("modules/ui/views/RIKDesktop",["require","exports","modules/utils/RefTag","modules/errors/JqueryPromiseErrorHandler","modules/utils/Service","modules/metrics/ReadingStreams","modules/metrics/MetricsUtils"],function(a,b,c,d,e,f,g){"use strict";return function(){function a(){e.requireWithRetry(["modules/utils/QueryParamUtils"],function(a){var d=$("#kp-rik-desktop-kcr-button"),e=c.getEndpointRefTag(c.Constants.RIK_DESKTOP_SUFFIX),h=c.getRefTagQueryParam(e),i=a.appendQueryParams(window.KindleGlobal.kcrv1Url,h);d.click(function(){window.location=i,g.recordActionAndUploadMetrics(b,f.RSConstants.ACTION_OPEN_KCR)})})}var b=f.RSConstants.CONTEXT_RIK_DESKTOP;$(document).ready(function(){"RIKDesktop"===window.KindleGlobal.page&&(g.getManagers().then(function(a,c,d){d.setCurrentContainerView(b)},d.onPromiseRejected),g.recordShowContext(b),a())})}()}),define("modules/ui/views/RikInterstitial",["require","exports","modules/errors/JqueryPromiseErrorHandler","modules/utils/Service","modules/metrics/ReadingStreams","modules/metrics/MetricsUtils"],function(a,b,c,d,e,f){"use strict";return function(){function a(){var a=$("#kp-rik-interstitial-open-app"),c=window.KindleGlobal.openAppUrl;a.on("click",function(){var a="OpenApp";d.requireWithRetry(["modules/utils/DeviceUtils"],function(c){f.recordPMET(b,a+"::"+c.getDevicePlatform())}),f.recordPMET(b,a).always(function(){window.location.href=c})});var e=$("#kp-rik-interstitial-install-app"),g=window.KindleGlobal.installAppUrl;e.on("click",function(){var a="InstallApp";d.requireWithRetry(["modules/utils/DeviceUtils"],function(c){f.recordPMET(b,a+"::"+c.getDevicePlatform())}),f.recordPMET(b,a).always(function(){window.location.href=g})})}var b="ReadInKindle::Interstitial";$(document).ready(function(){if("RIKInterstitial"===window.KindleGlobal.page){var g=e.RSConstants.CONTEXT_RIK_INTERSTITIAL;f.getManagers().then(function(a,b,c){c.setCurrentContainerView(g)},c.onPromiseRejected),f.recordShowContext(g),a(),d.requireWithRetry(["modules/utils/ReadInKindle"],function(a){a.performDeepLinkingIfPossible()}),d.requireWithRetry(["modules/utils/DeviceUtils"],function(a){f.recordPMET(b,a.getDevicePlatform())})}})}()}),define("modules/ui/views/UnsupportedBrowser",["require","exports","modules/errors/JqueryPromiseErrorHandler","modules/metrics/ReadingStreams","modules/metrics/MetricsUtils"],function(a,b,c,d,e){"use strict";return function(){function a(){f=[{domId:"#kp-download-chrome-button",downloadUrl:"https://www.google.com/chrome/browser/",metricName:d.RSConstants.ACTION_DOWNLOAD_CHROME_CLICKED},{domId:"#kp-download-firefox-button",downloadUrl:"https://www.mozilla.org/en-US/firefox/all/",metricName:d.RSConstants.ACTION_DOWNLOAD_FIREFOX_CLICKED},{domId:"#kp-download-safari-button",downloadUrl:"https://support.apple.com/downloads/safari",metricName:d.RSConstants.ACTION_DOWNLOAD_SAFARI_CLICKED},{domId:"#kp-download-ie-button",downloadUrl:"http://windows.microsoft.com/en-us/internet-explorer/download-ie",metricName:d.RSConstants.ACTION_DOWNLOAD_IE_CLICKED}],f.forEach(b)}function b(a){$(a.domId).on("click",function(){e.recordActionAndUploadMetrics(a.metricName,d.RSConstants.CONTEXT_UNSUPPORTED_BROWSER).always(function(){window.open(a.downloadUrl,"_blank")})})}var f;$(document).ready(function(){if("UnsupportedBrowser"===window.KindleGlobal.page){var b=d.RSConstants.CONTEXT_UNSUPPORTED_BROWSER;e.getManagers().then(function(a,c,d){d.setCurrentContainerView(b)},c.onPromiseRejected),e.recordShowContext(b),a()}})}()}),define("modules/ui/widgets/KindleAppDownload",["require","exports","modules/metrics/ReadingStreams","modules/metrics/MetricsUtils","modules/utils/RefTag","modules/utils/Utility","modules/utils/DeviceUtils"],function(a,b,c,d,e,f,g){"use strict";function h(a,b){b.find("#kp-get-kindle-app-button, #kp-get-kindle-app-link").click(function(){d.recordActionAndUploadMetrics(a,c.RSConstants.ACTION_GET_KINDLE_APP_CLICKED),i()})}function i(){var a=e.getEndpointRefTag(e.Constants.GET_APP_END_ACTION_SUFFIX),b=f.getAppStoreUrlWithRefTag(window.KindleGlobal.appStoreUrl,a);g.shouldSimulateClickForITunes()?f.simulateClickForLink(b):f.openInNewWindow(b)}b.initialize=h}),define("modules/ui/views/PDocQuoteShareLandingPageView",["require","exports","modules/ui/widgets/KindleAppDownload","modules/metrics/ReadingStreams","modules/metrics/MetricsUtils"],function(a,b,c,d,e){"use strict";return function(){function a(a){a.find(".kp-conditions-of-use").click(function(){e.recordAction(f,d.RSConstants.ACTION_CONDITIONS_OF_USE_CLICKED)}),a.find(".kp-privacy-notice").click(function(){e.recordAction(f,d.RSConstants.ACTION_PRIVACY_NOTICE_CLICKED)}),a.find(".kp-legal-notices").click(function(){e.recordAction(f,d.RSConstants.ACTION_LEGAL_NOTICES_CLICKED)})}function b(b){g=b,a(g)}var f=d.RSConstants.CONTEXT_PDOC_SHARE_PAGE;c.initialize(f,$("#kp-pdoc-get-kindle-app"));var g;return{initLegalFooter:a,initialize:b}}()});var __extends=this&&this.__extends||function(a,b){function c(){this.constructor=a}for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)};define("modules/notebook/Clipboard",["require","exports","handlebars","modules/utils/DeviceUtils","modules/metrics/MetricsUtils","modules/metrics/ReadingStreams"],function(a,b,c,d,e,f){"use strict";var g;!function(a){a[a.Highlight=1]="Highlight",a[a.Note=2]="Note",a[a.ChildNote=3]="ChildNote",a[a.Metadata=4]="Metadata"}(g||(g={}));var h=function(){function a(a,b){var c=this;this.text=a,this.type=b,this.isHighlight=function(){return c.is(g.Highlight)},this.isNote=function(){return c.is(g.Note)||c.is(g.ChildNote)},this.isChildNote=function(){return c.is(g.ChildNote)},this.isMetadata=function(){return c.is(g.Metadata)},this.text=a,this.type=b}return a.prototype.is=function(a){return this.type===a},a}(),i=function(a){function b(b,c){var d=this;a.call(this,b,g.Metadata),this.starred=c,this.isStarred=function(){return d.starred},this.starred=c,this.text=this.text.replace(/\n/g," "),this.text=this.text.replace(/\s+/g," ")}return __extends(b,a),b}(h),j=function(a){function b(b,c){void 0===c&&(c=[]),a.call(this,b,g.Highlight),this.notes=c,this.text=b,this.notes=c}return __extends(b,a),b}(h),k=function(a){function b(b,c,d){var e=this;void 0===c&&(c=!1),void 0===d&&(d=!1),a.call(this,b,d?g.ChildNote:g.Note),this.starred=c,this.isStarred=function(){return e.starred},this.starred=c}return __extends(b,a),b}(h),l={txtTemplate:"ClipboardText",htmlTemplate:"ClipboardHtml",noteClass:"kp-notebook-note",highlightClass:"kp-notebook-highlight",metadataClass:"kp-notebook-metadata",starredSelector:".kp-notebook-starred,.kp-notebook-note-starred",copyableSelector:".kp-notebook-selectable:not(.aok-hidden):not(.kp-notebook-starred):not(.kp-notebook-note-starred):not(#note-label)"},m=function(){function a(){var a=this;this.CopyHandler=function(b){var c=b.originalEvent;if(a.isNotNull(document.getSelection())){var g=document.getSelection(),h=a.associateNotesToHighlights(a.extractCopyableObjectsFromSelection(g));if(h.length>0){var i=$(a.renderHandlebarToJQuery(h,l.htmlTemplate)),j=a.renderHandlebarToJQuery(h,l.txtTemplate),k=i.get(0).outerHTML;a.isWindows()&&(j=j.replace(/\n/g,"\r\n"));var m=window;m.clipboardData?m.clipboardData.setData("Text",j):(c.clipboardData.setData("text/html",k),c.clipboardData.setData("text/plain",j)),d.isIOS()||c.preventDefault();for(var n=0,o=0,p=0,q=h;p 0){var r=this.createCopyable(q,i);this.isNotNull(r)&&o.push(r)}}for(var s=0,t=o;s 0&&(this.isNotNull(e)&&(b[0].text=e.text),this.isNotNull(f)&&(b[b.length-1].text=f.text))}else{var i=d.startContainer.textContent.substring(d.startOffset,d.endOffset),v=this.createCopyable(d.startContainer,i);this.isNotNull(v)&&b.push(v)}}return b},a.prototype.renderHandlebarToJQuery=function(a,b){var d={objects:a};return c.templates[b](d)},a.prototype.associateNotesToHighlights=function(a){if(this.isNull(a))return null;if(a.length<2)return a.slice();for(var b=new Array,c=null,d=0;d =0},a}();b.SearchEngine=c}),define("modules/notebook/Search",["require","exports","modules/notebook/SearchCore","modules/metrics/ReadingStreams","modules/metrics/MetricsUtils"],function(a,b,c,d,e){"use strict";function f(a){$(y).submit(function(){return u=Date.now(),v=[],e.recordAction(d.RSConstants.CONTEXT_NOTEBOOK_PAGE,d.RSConstants.ACTION_NOTEBOOK_SEARCH_SUBMITTED),k(window.KindleGlobal.deviceInfo.deviceType!==x),window.KindleGlobal.deviceInfo.deviceType!==w&&$(z).blur(),!1}),r=null!==a&&void 0!==a?a:function(){}}function g(a){t=a}function h(){return t}function i(){var a=new c.SearchEngine;$(".kp-notebook-library-each-book").each(function(){var b=$(this),c=b.attr("id"),d="";b.find(".kp-notebook-searchable").each(function(){d+=" "+$(this).text()}),a.appendToSearchIndex(c,d)}),s=a}function j(){if(p(),$("#kp-notebook-library-no-results").addClass("aok-hidden"),window.KindleGlobal.deviceInfo.deviceType!==x){var a=$(".a-row .kp-notebook-library-each-book")[0].id;r(a)}}function k(a){var b=m(),c=s.search(b),d=$(".a-row .kp-notebook-library-each-book").length;o(b,c),0===c.length&&t&&0!==d?($("#kp-notebook-library-no-results").removeClass("aok-hidden"),n(b)):($("#kp-notebook-library-no-results").addClass("aok-hidden"),d!==c.length&&0!==c.length&&l(c)),0===c.length&&window.KindleGlobal.deviceInfo.deviceType===w&&null!==r&&void 0!==r?r(""):a&&""!==b&&c[0]!==$("#kp-notebook-annotations-asin").val()&&r(c[0])}function l(a){var b=[];a.forEach(function(a){-1===v.indexOf(a)&&b.push(a)});var c={numberOfResultsFound:b.length,searchTimeInMilliseconds:Date.now()-u,hasLibraryFullyLoaded:t};b.length>0&&(e.recordAction(d.RSConstants.CONTEXT_NOTEBOOK_PAGE,d.RSConstants.ACTION_NOTEBOOK_SEARCH_RESULTS_FOUND,c,Date.now()),v.push.apply(v,b))}function m(){return void 0===$("#kp-notebook-search-input").val()?"":$("#kp-notebook-search-input").val().trim()}function n(a){var b="#kp-notebook-search-no-results-text",c="kp-notebook-search-string";-1!==$(b).text().indexOf("{0}")&&$(b).html($(b).text().replace("{0}","")),$(b).find("."+c).text(a)}function o(a,b){""===a?p():q(b)}function p(){$(".kp-notebook-library-each-book").removeClass("aok-hidden")}function q(a){$(".kp-notebook-library-each-book").each(function(){var b=$(this),c=b.attr("id");-1===$.inArray(c,a)?b.addClass("aok-hidden"):b.removeClass("aok-hidden")})}var r,s=new c.SearchEngine,t=!1,u=Date.now(),v=[],w="Desktop",x="Mobile",y="#kp-notebook-search-form",z="#kp-notebook-search-input";b.attachHandlers=f,b.setLibraryLoadCompleted=g,b.getLibraryLoadCompleted=h,b.buildSearchIndex=i,b.setNotebookViewToInitialState=j,b.updateNotebookView=k}),define("modules/utils/csrf",["require","exports"],function(a,b){"use strict";var c="CSRF Token not present in the DOM.",d="CSRF Header could not be added to AJAX request.";b.getCsrfToken=function(){var a=document.querySelector('input[name="anti-csrftoken-a2z"]');if(!a||!a.getAttribute("value"))throw new TypeError(c);return a.getAttribute("value")},b.addCsrfHeader=function(a,e){void 0===e&&(e=!1);var f=a;try{f["anti-csrftoken-a2z"]=b.getCsrfToken()}catch(g){if("TypeError"!==g.name||g.message!==c)throw g;if(e)throw new TypeError(d);console.error(d)}return f}}),define("modules/ui/views/NotebookView",["require","exports","modules/utils/QueryParamUtils","modules/utils/RefTag","modules/utils/DeviceUtils","modules/utils/StringUtils","modules/notebook/Clipboard","modules/metrics/ReadingStreams","modules/metrics/MetricsUtils","modules/metrics/PMET","modules/metrics/CSM","modules/notebook/Search","modules/utils/csrf"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){"use strict";return function(){function a(a,d,e,k,o){function p(a){var b=document.createElement("iframe");return b.style.display="none",document.body.appendChild(b),b.src=a,b}function q(b){for(var c=b.split("-")[1],d=document.getElementById(c),e=u(d),f=a.$(" "),g=0;g
0&&!c.hasClass("aok-hidden"),f=d.length>0&&d.text().length>0,g=new Array,h=a.$(b).attr("id");return window.KindleGlobal.deviceInfo.deviceType===L&&g.push(v(N,"KP_YNH_OPTIONS_DD_READMORE",h)),e&&f?g.push(v(P,"KP_YNH_OPTIONS_DD_EDIT_NOTE",h),v(R,"KP_YNH_OPTIONS_DD_DELETE_HIGHLIGHT",h),v(Q,"KP_YNH_OPTIONS_DD_DELETE_NOTE",h)):e?g.push(v(O,"KP_YNH_OPTIONS_DD_ADD_NOTE",h),v(R,"KP_YNH_OPTIONS_DD_DELETE_HIGHLIGHT",h)):f&&g.push(v(P,"KP_YNH_OPTIONS_DD_EDIT_NOTE",h),v(Q,"KP_YNH_OPTIONS_DD_DELETE_NOTE",h)),g}function v(b,c,d){var e=window.KindleGlobal.localizedStrings[c],f=a.$(" "+e+" ");return f.find("a").bind("click",t(b)),f}function w(){var b=a.$("#editNoteDiv");b.hasClass("aok-hidden")||b.prev().removeClass("aok-hidden");var c=a.$("#addNoteDiv");a.$(b).addClass("aok-hidden"),a.$(c).addClass("aok-hidden")}function x(){var c=$(this).attr("value"),d=a.$("#editNoteDiv");w(),T(c);var e=document.getElementById(c),g=F(e),h=document.getElementById(g);a.$(d).insertAfter(h),a.$("#editNoteAnnotationId").val(c),a.$("#editNoteError").addClass("aok-hidden"),d.removeClass("aok-hidden"),a.$(h).addClass("aok-hidden");var i=a.$("textarea#editNoteTextArea");i.val(f.unescapeAndFormatHTML(a.$(h).find("#note").html())),i.removeClass("kp-notebook-textarea-error"),b(i)}function y(){var b=$(this).attr("value");a.$("#deleteNoteAnnotationId").val(b),w(),window.KindleGlobal.deviceInfo.deviceType===K&&d.get(a.$("#deleteNoteModal")).attrs("width","300"),a.$("#deleteNoteError").addClass("aok-hidden"),d.get(a.$("#deleteNoteModal")).show()}function z(){var c=$(this).attr("value"),d=a.$("#addNoteDiv");T(c),w();var e=document.getElementById(c),f=D(e),g=document.getElementById(f);a.$(d).insertAfter(g),a.$("#addNoteAnnotationId").val(c),a.$("#addNoteTextArea").val(""),a.$("#addNoteError").addClass("aok-hidden"),a.$(d).removeClass("aok-hidden");var h=a.$("#addNoteTextArea");h.removeClass("kp-notebook-textarea-error"),b(h)}function B(){var b=$(this).attr("value");a.$("#deleteHighlightAnnotationId").val(b),w(),window.KindleGlobal.deviceInfo.deviceType===K&&d.get(a.$("#deleteHighlightModal")).attrs("width","300"),a.$("#deleteHighlightError").addClass("aok-hidden"),d.get(a.$("#deleteHighlightModal")).show()}function C(b){a.$("#addNoteDiv").insertAfter(b).addClass("aok-hidden"),a.$("#editNoteDiv").insertAfter(b).addClass("aok-hidden")}function D(b){return a.$(b).find(".kp-notebook-highlight").attr("id")}function F(b){return a.$(b).find(".kp-notebook-note").attr("id")}function G(){var a=$(this).attr("value");T(a),H(I,a),i.recordAction(S,h.RSConstants.ACTION_OPEN_IN_KINDLE_TRIGGER)}function H(b,e){var f={},g=document.getElementById(e);f.asin=b,f.location=a.$(g).find("#kp-annotation-location").val();var j=c.appendQueryParamsMap(window.KindleGlobal.openAppUrl,f),k=p(j),l=function(){k&&(k.parentNode.removeChild(k),k=null)},m=setTimeout(function(){a.$(window).unbind("blur",n),l(),d.get(a.$("#readMoreModal")).show(),i.recordAction(S,h.RSConstants.ACTION_OPEN_IN_KINDLE_FAIL)},M),n=function(){clearTimeout(m),a.$(window).unbind("blur",n),l(),i.recordAction(S,h.RSConstants.ACTION_OPEN_IN_KINDLE_SUCCESS)};a.$(window).bind("blur",n)}function T(b){o.get(a.$(document.getElementById("popover-"+b+"-action"))).hide()}var U=new g.NotebookClipboardHandlers;a.$(document.documentElement).bind("copy",U.CopyHandler),a.declarative("get-annotations-for-asin","click",function(a){s(a.data.asin)}),a.declarative("back","click",function(){a.$("#kp-notebook-annotations-pane").addClass("aok-hidden"),a.$("#header").addClass("aok-hidden"),a.$("#library").show()}),a.on("a:dropdown:select",function(a){"kp-notebook-library-sortOrder"===a.name&&n(a)}),a.on("a:popover:beforeShow:optionsPopover",function(a){q(a.popover.$trigger.find("a").attr("id"))}),a.on("a:popover:afterShow:optionsPopover",function(b){var c=b.popover.$trigger.find("a").attr("id"),d=document.getElementById(c+"-action");$("#annotation-scroller").unbind("scroll.my-popover-scroll-unique-name").bind("scroll.my-popover-scroll-unique-name",function(){var b=a.$;o.get(b(d)).hide()})}),a.declarative("edit-note-action","click",function(){var b=a.$("#editNoteAnnotationId").val(),c=a.$("#editNoteTextArea").val();if(J.test(c)){var d=k(document.getElementById("editNoteText"));d.disable();var e=document.getElementById(b),g=F(e),j=document.getElementById(g),l=a.$("#editNoteDiv");a.$("#editNoteError").addClass("aok-hidden"),g=g.split("-")[1];var n=[];m.addCsrfHeader(n),a.$.ajax({url:r("note"),type:"POST",contentType:"application/x-www-form-urlencoded; charset=UTF-8",headers:n,data:{noteId:g,noteText:c},success:function(b){if(b.result){var d=f.escapeAndFormatHTML(c);a.$(j).find("#note").html(d),l.addClass("aok-hidden"),a.$(j).removeClass("aok-hidden"),i.recordAction(S,h.RSConstants.ACTION_NOTE_EDITED)}else a.$("#editNoteError").removeClass("aok-hidden"),i.recordAction(h.RSConstants.CONTEXT_ERROR_ALERT,h.RSConstants.ACTION_NOTE_EDITED)},error:function(){a.$("#editNoteError").removeClass("aok-hidden"),i.recordAction(h.RSConstants.CONTEXT_ERROR_ALERT,h.RSConstants.ACTION_NOTE_EDITED)},complete:function(){d.enable()}})}else a.$("#editNoteTextArea").addClass("kp-notebook-textarea-error")}),a.declarative("cancel-edit-note-action","click",function(){var b=a.$("#editNoteAnnotationId").val(),c=a.$("#editNoteDiv"),d=document.getElementById(b),e=F(d),f=document.getElementById(e);c.addClass("aok-hidden"),a.$(f).removeClass("aok-hidden"),a.$("#editNoteTextArea").val("").removeClass("kp-notebook-textarea-error")}),$("#kp-notebook-search-input").keyup(function(){$("#kp-notebook-search-input").val().length<1?$("#kp-notebook-search-clear").addClass("aok-hidden"):$("#kp-notebook-search-clear").removeClass("aok-hidden")}),a.declarative("delete-note-action","click",function(){var b=k("#deleteNote");b.disable();var e={},f=a.$("#deleteNoteAnnotationId").val(),g=document.getElementById(f),j=F(g),l=document.getElementById(j);j=j.split("-")[1],e.noteId=j,a.$("#deleteNoteError").addClass("aok-hidden");var n=[];m.addCsrfHeader(n),a.$.ajax({url:c.appendQueryParamsMap(r("note"),e),headers:n,type:"DELETE",success:function(b){if(b.result){C(g);var c=a.$(g).find(".kp-notebook-highlight");0===c.length||c.hasClass("aok-hidden")?a.$(g).remove():(a.$(l).find("#note").text(""),a.$(l).addClass("aok-hidden").attr("id","note-")),A(),d.get(a.$("#deleteNoteModal")).hide(),i.recordAction(S,h.RSConstants.ACTION_NOTE_DELETED)}else a.$("#deleteNoteError").removeClass("aok-hidden"),i.recordAction(h.RSConstants.CONTEXT_ERROR_ALERT,h.RSConstants.ACTION_NOTE_DELETED)},error:function(){a.$("#deleteNoteError").removeClass("aok-hidden"),i.recordAction(h.RSConstants.CONTEXT_ERROR_ALERT,h.RSConstants.ACTION_NOTE_DELETED)},complete:function(){b.enable()}})}),a.declarative("add-note-action","click",function(){var b=a.$("#addNoteTextArea").val();if(J.test(b)){var c=k(document.getElementById("addNoteText"));c.disable();var d=a.$("#addNoteAnnotationId").val(),e=document.getElementById(d),g=a.$("#addNoteDiv"),j={};j.highlightId=d,j.noteText=b,a.$("#addNoteError").addClass("aok-hidden");var l=[];m.addCsrfHeader(l),a.$.ajax({url:r("note"),data:{highlightId:d,noteText:b},headers:l,contentType:"application/x-www-form-urlencoded; charset=UTF-8",type:"POST",success:function(c){var d=c.noteId;a.$(e).find("#note-").attr("id","note-"+d);var j=document.getElementById("note-"+d),k=f.escapeAndFormatHTML(b);a.$(j).find("#note").html(k),a.$(j).removeClass("aok-hidden"),a.$(g).addClass("aok-hidden"),A(),i.recordAction(S,h.RSConstants.ACTION_NOTE_ADDED)},error:function(){a.$("#addNoteError").removeClass("aok-hidden"),i.recordAction(h.RSConstants.CONTEXT_ERROR_ALERT,h.RSConstants.ACTION_NOTE_ADDED)},complete:function(){c.enable()}})}else a.$("#addNoteTextArea").addClass("kp-notebook-textarea-error")}),a.declarative("cancel-add-note-action","click",function(){a.$("#addNoteDiv").addClass("aok-hidden"),a.$("#addNoteTextArea").val("").removeClass("kp-notebook-textarea-error")}),a.declarative("clear-search-field","click",function(){$("#kp-notebook-search-input").val(""),$("#kp-notebook-search-clear").addClass("aok-hidden"),l.buildSearchIndex(),l.setNotebookViewToInitialState()}),a.declarative("delete-highlight-action","click",function(){var b=k("#deleteHighlight");b.disable();var e={},f=a.$("#deleteHighlightAnnotationId").val(),g=document.getElementById(f),j=D(g),l=document.getElementById(j),n=F(g),o=document.getElementById(n);j=j.split("-")[1],e.highlightId=j,a.$("#deleteHighlightError").addClass("aok-hidden");var p=[];m.addCsrfHeader(p),a.$.ajax({url:c.appendQueryParamsMap(r("highlight"),e),headers:p,type:"DELETE",success:function(b){b.result?(C(g),""===a.$(l).next().find("#note").text()?a.$(g).remove():(a.$(l).find("#highlight").text(""),a.$(l).addClass("aok-hidden"),a.$(g).find("#note-label").text(""),a.$(g).find("#annotationHighlightHeader").addClass("aok-hidden"),a.$(g).find("#annotationNoteHeader").removeClass("aok-hidden"),a.$(o).removeClass("a-spacing-top-base")),A(),d.get(a.$("#deleteHighlightModal")).hide(),i.recordAction(S,h.RSConstants.ACTION_HIGHLIGHT_DELETED)):(a.$("#deleteHighlightError").removeClass("aok-hidden"), +i.recordAction(h.RSConstants.CONTEXT_ERROR_ALERT,h.RSConstants.ACTION_HIGHLIGHT_DELETED))},error:function(){a.$("#deleteHighlightError").removeClass("aok-hidden"),i.recordAction(h.RSConstants.CONTEXT_ERROR_ALERT,h.RSConstants.ACTION_HIGHLIGHT_DELETED)},complete:function(){b.enable(),E()}})}),a.declarative("kp-notebook-detail-page-url","click",function(){i.recordAction(S,h.RSConstants.ACTION_DETAIL_PAGE_CLICKED)});var V=j.getMetric(j.Constants.NOTEBOOK_PAGE_LOADED);j.record(V.stopTimer())}function b(a){setTimeout(function(){$(a).focus()},600)}function n(a){var b=window.location.href,d=c.updateQueryParams(b,{sort:a.value});window.location.href=d}function o(a){$(".a-color-base-background").removeClass("a-color-base-background"),$("#"+a).addClass("a-color-base-background")}function p(){return window.location.origin+window.location.pathname}function q(a){return["stagingKey"].forEach(function(b){var d=c.getQueryParameter(b);void 0!==d&&""!==d&&(a[b]=d)}),a}function r(a){return p()+"/"+("note"===a?"note":"highlight")+window.location.search}function s(a){if(j.createMetric(j.Constants.NOTEBOOK_PAGE_ANNOTATIONS_LOADED).startTimer(),"Mobile"===window.KindleGlobal.deviceInfo.deviceType?($("#library").hide(),$("#header").removeClass("aok-hidden")):o(a),$("#kp-notebook-annotations-pane").addClass("aok-hidden"),$("#kp-notebook-annotations-pane").html(""),""!==a){$("#kp-notebook-spinner").show();var b={};b.asin=a,b.contentLimitState="",$.get(c.appendQueryParamsMap(p(),q(b)),function(b){$("#kp-notebook-annotations-pane").html(b),void 0!==$("#kp-notebook-check-validity")?($("#kp-notebook-annotations-pane").removeClass("aok-hidden"),$("#kp-notebook-spinner").hide(),$(".kp-notebook-library-each-book:not(.aok-hidden)").length,I=a,v(a)):window.location.reload()}).fail(function(a){0===a.status&&window.location.reload()})}}function t(){var a=$($(".kp-notebook-annotations-next-page-start").get(0)).val();u(0,I,a)}function u(a,b,d){if(void 0!==d&&""!==d){a++;var e={};e.asin=b,e.token=d,e.contentLimitState=$(".kp-notebook-content-limit-state").last().val(),$.get(c.appendQueryParamsMap(p(),q(e)),function(c){b===I&&($("#kp-notebook-annotations").append(c),d=$($(".kp-notebook-annotations-next-page-start").get(a)).val(),u(a,b,d))}).fail(function(){$("#kp-notebook-annotations-load-error").removeClass("aok-hidden"),i.recordAction(S,h.RSConstants.ACTION_NOTEBOOK_PAGE_ANNOTATIONS_LOAD_FAIL)})}else{$("#kp-notebook-annotations-spinner").hide(),A(),E();var f=j.getMetric(j.Constants.NOTEBOOK_PAGE_ANNOTATIONS_LOADED);f&&j.record(f.stopTimer())}}function v(a){if(""===a&&0!==$("a-row kp-notebook-library-each-book").length)return void $("#kp-notebook-annotations-pane").html("");var b=$("#kp-notebook-annotated-date-"+a).val();$("#kp-notebook-annotated-date").text(b),z(),t()}function w(){0===$(".kp-notebook-library-each-book").length&&i.recordViewShown(h.RSConstants.CONTEXT_NOTEBOOK_PAGE_EMPTY_LIB),x(0,$($(".kp-notebook-library-next-page-start").get(0)).val())}function x(a,b){if(void 0!==b&&""!==b){a++;var d={};d.library="list",d.token=b,$.get(c.appendQueryParamsMap(p(),q(d)),function(c){var d=y(c);$("#kp-notebook-library").append(d),b=$($(".kp-notebook-library-next-page-start").get(a)).val(),x(a,b)}).fail(function(){$("#kp-notebook-library-load-error").removeClass("aok-hidden"),i.recordAction(S,h.RSConstants.ACTION_NOTEBOOK_PAGE_LIBRARY_LOAD_FAIL)})}else{$("#kp-notebook-library-spinner").hide();var e=j.getMetric(j.Constants.NOTEBOOK_PAGE_LIBRARY_LOADED);e&&j.record(e.stopTimer()),l.setLibraryLoadCompleted(!0)}l.buildSearchIndex(),l.updateNotebookView(window.KindleGlobal.deviceInfo.deviceType!==K)}function y(a){var b=$(""+a+""),c=[];$("#kp-notebook-library div.kp-notebook-library-each-book").each(function(a,b){c.push(b.id)});var d=[];b.find("div.kp-notebook-library-each-book").each(function(a,b){d.push(b.id)});for(var e=0;e=0&&b.find("div#"+f).remove()}return b.children()}function z(){$("#annotation-section").css("margin-bottom","0px"),$("#library-section").css("margin-bottom","0px"),$("#annotation-section").height(e.getWindowHeight()-$("#kp-notebook-head").outerHeight(!0)),$("#library-section").height(e.getWindowHeight()-$("#kp-notebook-head").outerHeight(!0)-$("#books-filter").outerHeight(!0)-$("#kp-notebook-search-row").outerHeight(!0))}function A(){var a=$(".kp-notebook-highlight:not(.aok-hidden)").length,b=$(".kp-notebook-note:not(.aok-hidden)").length,c=$(".a-row .kp-notebook-library-each-book").length;0===a&&0===b&&0===c&&($("#empty-annotations-pane").removeClass("aok-hidden"),$("#kp-notebook-search-input").addClass("a-form-disabled"),$("#kp-notebook-search-input").attr("disabled","disabled"),$("#kp-notebook-search-button").addClass("a-button-disabled"),$("#kp-notebook-search-button").attr("disabled","disabled"),i.recordViewShown(h.RSConstants.CONTEXT_NOTEBOOK_PAGE_EMPTY_ANNOTATIONS)),""!==I?($("#kp-notebook-highlights-count").text(a),$("#kp-notebook-notes-count").text(b)):($("#kp-notebook-highlights-count").text("--"),$("#kp-notebook-notes-count").text("--"))}function B(){return $(".kp-notebook-highlight-truncated").length}function C(){return $(".kp-notebook-highlight-hidden").length}function D(){return $(".kp-notebook-highlight-empty-text").length}function E(){B()>0||C()>0?$("#kp-notebook-hidden-annotations-summary").removeClass("aok-hidden"):$("#kp-notebook-hidden-annotations-summary").addClass("aok-hidden"),F()}function F(){var a=$("#kp-notebook-annotations-asin").val();G(h.RSConstants.ACTION_HIGHLIGHT_TRUNCATED,B(),a),G(h.RSConstants.ACTION_HIGHLIGHT_HIDDEN,C(),a),G(h.RSConstants.ACTION_HIGHLIGHT_EMPTY_TEXT,D(),a)}function G(a,b,c){b>0&&i.recordAction(S,a,{asin:c,count:b})}function H(){window.KindleGlobal.deviceInfo.deviceType===K&&($("#kp-notebook-search-input").focus(function(){$("#kp-notebook-head").css("position","absolute")}),$("#kp-notebook-search-input").blur(function(){$("#kp-notebook-head").css("position","fixed")}),$("#library-section-mobile").on("touchstart",function(){$("#kp-notebook-head").css("position","fixed")}))}var I,J=/\S/,K="Mobile",L="Desktop",M=1500,N="readmore",O="addnote",P="editnote",Q="deletenote",R="deletehighlight",S=h.RSConstants.CONTEXT_NOTEBOOK_PAGE;return $(document).ready(function(){i.recordViewShown(S),d.removeRefTagFromUrl(d.Constants.K4W_KA_NOTEBOOK),I=$("#kp-notebook-annotations-asin").val(),o(I),k.logCriticalFeatureMarker(),v(I),w(),H(),$("#kp-notebook-head-placeholder").height($("#kp-notebook-head").outerHeight(!0)),window.onresize=function(){z()},l.attachHandlers(function(a){s(a)})}),{initialize:a}}()}); \ No newline at end of file diff --git a/Amazon_sources/Kindle_ Your Notes and Highlights_files/Kindle_Logo_RGB.png b/Amazon_sources/Kindle_ Your Notes and Highlights_files/Kindle_Logo_RGB.png new file mode 100644 index 0000000..5abc6fe Binary files /dev/null and b/Amazon_sources/Kindle_ Your Notes and Highlights_files/Kindle_Logo_RGB.png differ diff --git a/Amazon_sources/Kindle_ Your Notes and Highlights_files/Note_icon.png b/Amazon_sources/Kindle_ Your Notes and Highlights_files/Note_icon.png new file mode 100644 index 0000000..f8078ec Binary files /dev/null and b/Amazon_sources/Kindle_ Your Notes and Highlights_files/Note_icon.png differ diff --git a/Amazon_sources/Kindle_ Your Notes and Highlights_files/Notebook.hbs.js.download b/Amazon_sources/Kindle_ Your Notes and Highlights_files/Notebook.hbs.js.download new file mode 100644 index 0000000..4cc11f6 --- /dev/null +++ b/Amazon_sources/Kindle_ Your Notes and Highlights_files/Notebook.hbs.js.download @@ -0,0 +1,254 @@ +/* Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. */ +(function() { + var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; +templates['ClipboardHtml'] = template(function (Handlebars,depth0,helpers,partials,data) { + this.compilerInfo = [4,'>= 1.0.0']; +helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; + var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression, self=this; + +function program1(depth0,data) { + + var buffer = "", stack1; + stack1 = helpers['with'].call(depth0, depth0, {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + return buffer; + } +function program2(depth0,data) { + + var buffer = "", stack1; + buffer += " "; + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isNote), {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isHighlight), {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isMetadata), {hash:{},inverse:self.noop,fn:self.program(13, program13, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n "; + return buffer; + } +function program3(depth0,data) { + + var buffer = "", stack1, helper; + buffer += "\n"; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + buffer += escapeExpression(stack1) + + "
\n "; + return buffer; + } + +function program5(depth0,data) { + + var buffer = "", stack1, helper; + buffer += "\n"; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + buffer += escapeExpression(stack1) + + "
"; + stack1 = helpers['if'].call(depth0, (depth0 && depth0.notes), {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n "; + return buffer; + } +function program6(depth0,data) { + + var buffer = "", stack1; + buffer += "\n "; + stack1 = helpers.each.call(depth0, (depth0 && depth0.notes), {hash:{},inverse:self.noop,fn:self.program(7, program7, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n
\n "; + return buffer; + } +function program7(depth0,data) { + + var buffer = "", stack1; + stack1 = helpers['with'].call(depth0, depth0, {hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n "; + return buffer; + } +function program8(depth0,data) { + + var buffer = "", stack1; + buffer += "\n "; + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isStarred), {hash:{},inverse:self.program(11, program11, data),fn:self.program(9, program9, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + return buffer; + } +function program9(depth0,data) { + + var buffer = "", stack1, helper; + buffer += "\n★ "; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + buffer += escapeExpression(stack1) + + "
\n "; + return buffer; + } + +function program11(depth0,data) { + + var buffer = "", stack1, helper; + buffer += "\n"; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + buffer += escapeExpression(stack1) + + "
\n "; + return buffer; + } + +function program13(depth0,data) { + + var buffer = "", stack1; + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isStarred), {hash:{},inverse:self.program(16, program16, data),fn:self.program(14, program14, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n "; + return buffer; + } +function program14(depth0,data) { + + var buffer = "", stack1, helper; + buffer += "★ "; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + buffer += escapeExpression(stack1) + + "
\n "; + return buffer; + } + +function program16(depth0,data) { + + var buffer = "", stack1, helper; + buffer += "\n"; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + buffer += escapeExpression(stack1) + + "
"; + return buffer; + } + + buffer += ""; + stack1 = helpers.each.call(depth0, (depth0 && depth0.objects), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += ""; + return buffer; + }); +templates['ClipboardText'] = template(function (Handlebars,depth0,helpers,partials,data) { + this.compilerInfo = [4,'>= 1.0.0']; +helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; + var stack1, functionType="function", self=this; + +function program1(depth0,data) { + + var buffer = "", stack1; + stack1 = helpers['with'].call(depth0, depth0, {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + return buffer; + } +function program2(depth0,data) { + + var buffer = "", stack1; + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isHighlight), {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isNote), {hash:{},inverse:self.noop,fn:self.program(12, program12, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isMetadata), {hash:{},inverse:self.noop,fn:self.program(14, program14, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + return buffer; + } +function program3(depth0,data) { + + var buffer = "", stack1, helper; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + if(stack1 || stack1 === 0) { buffer += stack1; } + stack1 = helpers['if'].call(depth0, (depth0 && depth0.notes), {hash:{},inverse:self.program(10, program10, data),fn:self.program(4, program4, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + return buffer; + } +function program4(depth0,data) { + + var buffer = "", stack1; + stack1 = helpers.each.call(depth0, (depth0 && depth0.notes), {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + return buffer; + } +function program5(depth0,data) { + + var buffer = "", stack1; + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isStarred), {hash:{},inverse:self.program(8, program8, data),fn:self.program(6, program6, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n"; + return buffer; + } +function program6(depth0,data) { + + var buffer = "", stack1, helper; + buffer += "\n★ "; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n"; + return buffer; + } + +function program8(depth0,data) { + + var buffer = "", stack1, helper; + buffer += "\n"; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n"; + return buffer; + } + +function program10(depth0,data) { + + + return "\n\n"; + } + +function program12(depth0,data) { + + var buffer = "", stack1, helper; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n\n"; + return buffer; + } + +function program14(depth0,data) { + + var buffer = "", stack1; + stack1 = helpers['if'].call(depth0, (depth0 && depth0.isStarred), {hash:{},inverse:self.program(17, program17, data),fn:self.program(15, program15, data),data:data}); + if(stack1 || stack1 === 0) { buffer += stack1; } + return buffer; + } +function program15(depth0,data) { + + var buffer = "", stack1, helper; + buffer += "★ "; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n"; + return buffer; + } + +function program17(depth0,data) { + + var buffer = "", stack1, helper; + if (helper = helpers.text) { stack1 = helper.call(depth0, {hash:{},data:data}); } + else { helper = (depth0 && depth0.text); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n"; + return buffer; + } + + stack1 = helpers.each.call(depth0, (depth0 && depth0.objects), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data}); + if(stack1 || stack1 === 0) { return stack1; } + else { return ''; } + }); +})(); \ No newline at end of file diff --git a/Amazon_sources/Kindle_ Your Notes and Highlights_files/handlebars.runtime-v1.3.0.js.download b/Amazon_sources/Kindle_ Your Notes and Highlights_files/handlebars.runtime-v1.3.0.js.download new file mode 100644 index 0000000..f546751 --- /dev/null +++ b/Amazon_sources/Kindle_ Your Notes and Highlights_files/handlebars.runtime-v1.3.0.js.download @@ -0,0 +1,27 @@ +/*! + + handlebars v1.3.0 + +Copyright (C) 2011 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +@license +*/ +var Handlebars=function(){var a=function(){"use strict";function a(a){this.string=a}return a.prototype.toString=function(){return""+this.string},a}(),b=function(a){"use strict";function b(a){return h[a]||"&"}function c(a,b){for(var c in b)Object.prototype.hasOwnProperty.call(b,c)&&(a[c]=b[c])}function d(a){return a instanceof g?a.toString():a||0===a?(a=""+a,j.test(a)?a.replace(i,b):a):""}function e(a){return!a&&0!==a||!(!m(a)||0!==a.length)}var f={},g=a,h={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},i=/[&<>"'`]/g,j=/[&<>"'`]/;f.extend=c;var k=Object.prototype.toString;f.toString=k;var l=function(a){return"function"==typeof a};l(/x/)&&(l=function(a){return"function"==typeof a&&"[object Function]"===k.call(a)});var l;f.isFunction=l;var m=Array.isArray||function(a){return!(!a||"object"!=typeof a)&&"[object Array]"===k.call(a)};return f.isArray=m,f.escapeExpression=d,f.isEmpty=e,f}(a),c=function(){"use strict";function a(a,c){var d;c&&c.firstLine&&(d=c.firstLine,a+=" - "+d+":"+c.firstColumn);for(var e=Error.prototype.constructor.call(this,a),f=0;f0?a.helpers.each(b,c):d(this):e(b)}),a.registerHelper("each",function(a,b){var c,d=b.fn,e=b.inverse,f=0,g="";if(k(a)&&(a=a.call(this)),b.data&&(c=o(b.data)),a&&"object"==typeof a)if(j(a))for(var h=a.length;f = 1.0.0"};f.REVISION_CHANGES=i;var j=g.isArray,k=g.isFunction,l=g.toString,m="[object Object]";f.HandlebarsEnvironment=c,c.prototype={constructor:c,logger:n,log:e,registerHelper:function(a,b,c){if(l.call(a)===m){if(c||b)throw new h("Arg not supported with multiple helpers");g.extend(this.helpers,a)}else c&&(b.not=c),this.helpers[a]=b},registerPartial:function(a,b){l.call(a)===m?g.extend(this.partials,a):this.partials[a]=b}};var n={methodMap:{0:"debug",1:"info",2:"warn",3:"error"},DEBUG:0,INFO:1,WARN:2,ERROR:3,level:3,log:function(a,b){if(n.level<=a){var c=n.methodMap[a];"undefined"!=typeof console&&console[c]&&console[c].call(console,b)}}};f.logger=n,f.log=e;var o=function(a){var b={};return g.extend(b,a),b};return f.createFrame=o,f}(b,c),e=function(a,b,c){"use strict";function d(a){var b=a&&a[0]||1,c=m;if(b!==c){if(b =0===c})}function k(a){var b=oa.split("|"),c=a.createDocumentFragment();if(c.createElement)for(;b.length;)c.createElement(b.pop());return c}function l(a,b){return J.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function m(a,b){if(1===b.nodeType&&J.hasData(a)){var c,d,e,f=J._data(a),g=J._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d 0){if("border"!==c)for(;e ").appendTo(b),d=c.css("display");c.remove(),"none"!==d&&""!==d||(nb||(nb=G.createElement("iframe"),nb.frameBorder=nb.width=nb.height=0),b.appendChild(nb),ob&&nb.createElement||(ob=(nb.contentWindow||nb.contentDocument).document,ob.write((J.support.boxModel?"":"")+""),ob.close()),c=ob.createElement(a),ob.body.appendChild(c),d=J.css(c,"display"),b.removeChild(nb)),rb[a]=d}return rb[a]}function F(a){return J.isWindow(a)?a:9===a.nodeType&&(a.defaultView||a.parentWindow)}var G=a.document,H=a.navigator,I=a.location,J=function(){function c(){if(!h.isReady){try{G.documentElement.doScroll("left")}catch(a){return void setTimeout(c,1)}h.ready()}}var d,e,f,g,h=function(a,b){return new h.fn.init(a,b,d)},i=a.jQuery,j=a.$,k=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,l=/\S/,m=/^\s+/,n=/\s+$/,o=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,p=/^[\],:{}\s]*$/,q=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,r=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,s=/(?:^|:|,)(?:\s*\[)+/g,t=/(webkit)[ \/]([\w.]+)/,u=/(opera)(?:.*version)?[ \/]([\w.]+)/,v=/(msie) ([\w.]+)/,w=/(mozilla)(?:.*? rv:([\w.]+))?/,x=/-([a-z]|[0-9])/gi,y=/^-ms-/,z=function(a,b){return(b+"").toUpperCase()},A=H.userAgent,B=Object.prototype.toString,C=Object.prototype.hasOwnProperty,D=Array.prototype.push,E=Array.prototype.slice,F=String.prototype.trim,I=Array.prototype.indexOf,J={};return h.fn=h.prototype={constructor:h,init:function(a,c,d){var e,f,g,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if("body"===a&&!c&&G.body)return this.context=G,this[0]=G.body,this.selector=a,this.length=1,this;if("string"==typeof a){if(!(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:k.exec(a))||!e[1]&&c)return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a);if(e[1])return c=c instanceof h?c[0]:c,i=c?c.ownerDocument||c:G,g=o.exec(a),g?h.isPlainObject(c)?(a=[G.createElement(g[1])],h.fn.attr.call(a,c,!0)):a=[i.createElement(g[1])]:(g=h.buildFragment([e[1]],[i]),a=(g.cacheable?h.clone(g.fragment):g.fragment).childNodes),h.merge(this,a);if((f=G.getElementById(e[2]))&&f.parentNode){if(f.id!==e[2])return d.find(a);this.length=1,this[0]=f}return this.context=G,this.selector=a,this}return h.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),h.makeArray(a,this))},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return E.call(this,0)},get:function(a){return null==a?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();return h.isArray(a)?D.apply(d,a):h.merge(d,a),d.prevObject=this,d.context=this.context,"find"===b?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return h.each(this,a,b)},ready:function(a){return h.bindReady(),f.add(a),this},eq:function(a){return a=+a,-1===a?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(E.apply(this,arguments),"slice",E.call(arguments).join(","))},map:function(a){return this.pushStack(h.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:D,sort:[].sort,splice:[].splice},h.fn.init.prototype=h.fn,h.extend=h.fn.extend=function(){var a,c,d,e,f,g,i=arguments[0]||{},j=1,k=arguments.length,l=!1;for("boolean"==typeof i&&(l=i,i=arguments[1]||{},j=2),"object"==typeof i||h.isFunction(i)||(i={}),k===j&&(i=this,--j);j 0)return;f.fireWith(G,[h]),h.fn.trigger&&h(G).trigger("ready").off("ready")}},bindReady:function(){if(!f){if(f=h.Callbacks("once memory"),"complete"===G.readyState)return setTimeout(h.ready,1);if(G.addEventListener)G.addEventListener("DOMContentLoaded",g,!1),a.addEventListener("load",h.ready,!1);else if(G.attachEvent){G.attachEvent("onreadystatechange",g),a.attachEvent("onload",h.ready);var b=!1;try{b=null==a.frameElement}catch(d){}G.documentElement.doScroll&&b&&c()}}},isFunction:function(a){return"function"===h.type(a)},isArray:Array.isArray||function(a){return"array"===h.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return null==a?String(a):J[B.call(a)]||"object"},isPlainObject:function(a){if(!a||"object"!==h.type(a)||a.nodeType||h.isWindow(a))return!1;try{if(a.constructor&&!C.call(a,"constructor")&&!C.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(d){return!1}var c;for(c in a);return c===b||C.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){return"string"==typeof b&&b?(b=h.trim(b),a.JSON&&a.JSON.parse?a.JSON.parse(b):p.test(b.replace(q,"@").replace(r,"]").replace(s,""))?new Function("return "+b)():void h.error("Invalid JSON: "+b)):null},parseXML:function(c){if("string"!=typeof c||!c)return null;var d,e;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return d&&d.documentElement&&!d.getElementsByTagName("parsererror").length||h.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&l.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(y,"ms-").replace(x,z)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var e,f=0,g=a.length,i=g===b||h.isFunction(a);if(d)if(i){for(e in a)if(!1===c.apply(a[e],d))break}else for(;f 0&&a[0]&&a[j-1]||0===j||h.isArray(a)))for(;i 1?L.call(arguments,0):b,--h||i.resolveWith(i,d)}}function c(a){return function(b){g[a]=arguments.length>1?L.call(arguments,0):b,i.notifyWith(j,g)}}var d=L.call(arguments,0),e=0,f=d.length,g=new Array(f),h=f,i=f<=1&&a&&J.isFunction(a.promise)?a:J.Deferred(),j=i.promise();if(f>1){for(;e a",c=m.getElementsByTagName("*"),d=m.getElementsByTagName("a")[0],!c||!c.length||!d)return{};e=G.createElement("select"),f=e.appendChild(G.createElement("option")),g=m.getElementsByTagName("input")[0],b={leadingWhitespace:3===m.firstChild.nodeType,tbody:!m.getElementsByTagName("tbody").length,htmlSerialize:!!m.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:"/a"===d.getAttribute("href"),opacity:/^0.55/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:"on"===g.value,optSelected:f.selected,getSetAttribute:"t"!==m.className,enctype:!!G.createElement("form").enctype,html5Clone:"<:nav>"!==G.createElement("nav").cloneNode(!0).outerHTML,submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},J.boxModel=b.boxModel="CSS1Compat"===G.compatMode,g.checked=!0,b.noCloneChecked=g.cloneNode(!0).checked,e.disabled=!0,b.optDisabled=!f.disabled;try{delete m.test}catch(n){b.deleteExpando=!1}if(!m.addEventListener&&m.attachEvent&&m.fireEvent&&(m.attachEvent("onclick",function(){b.noCloneEvent=!1}),m.cloneNode(!0).fireEvent("onclick")),g=G.createElement("input"),g.value="t",g.setAttribute("type","radio"),b.radioValue="t"===g.value,g.setAttribute("checked","checked"),g.setAttribute("name","t"),m.appendChild(g),h=G.createDocumentFragment(),h.appendChild(m.lastChild),b.checkClone=h.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=g.checked,h.removeChild(g),h.appendChild(m),m.attachEvent)for(k in{submit:1,change:1,focusin:1})j="on"+k,l=j in m,l||(m.setAttribute(j,"return;"),l="function"==typeof m[j]),b[k+"Bubbles"]=l;return h.removeChild(m),h=e=f=m=g=null,J(function(){var c,d,e,f,g,h,j,k,n,o,p,q,r=G.getElementsByTagName("body")[0];r&&(j=1,q="padding:0;margin:0;border:",o="position:absolute;top:0;left:0;width:1px;height:1px;",p=q+"0;visibility:hidden;",k="style='"+o+q+"5px solid #000;",n="
",c=G.createElement("div"),c.style.cssText=p+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(c,r.firstChild),m=G.createElement("div"),c.appendChild(m),m.innerHTML="
",i=m.getElementsByTagName("td"),l=0===i[0].offsetHeight,i[0].style.display="",i[1].style.display="none",b.reliableHiddenOffsets=l&&0===i[0].offsetHeight,a.getComputedStyle&&(m.innerHTML="",h=G.createElement("div"),h.style.width="0",h.style.marginRight="0",m.style.width="2px",m.appendChild(h),b.reliableMarginRight=0===(parseInt((a.getComputedStyle(h,null)||{marginRight:0}).marginRight,10)||0)),void 0!==m.style.zoom&&(m.innerHTML="",m.style.width=m.style.padding="1px",m.style.border=0,m.style.overflow="hidden",m.style.display="inline",m.style.zoom=1,b.inlineBlockNeedsLayout=3===m.offsetWidth,m.style.display="block",m.style.overflow="visible",m.innerHTML="",b.shrinkWrapBlocks=3!==m.offsetWidth),m.style.cssText=o+p,m.innerHTML=n,d=m.firstChild,e=d.firstChild,f=d.nextSibling.firstChild.firstChild,g={doesNotAddBorder:5!==e.offsetTop,doesAddBorderForTableAndCells:5===f.offsetTop},e.style.position="fixed",e.style.top="20px",g.fixedPosition=20===e.offsetTop||15===e.offsetTop,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",g.subtractsBorderForOverflowNotVisible=-5===e.offsetTop,g.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,a.getComputedStyle&&(m.style.marginTop="1%",b.pixelMargin="1%"!==(a.getComputedStyle(m,null)||{marginTop:0}).marginTop),void 0!==c.style.zoom&&(c.style.zoom=1),r.removeChild(c),h=m=c=null,J.extend(b,g))}),b}();var M=/^(?:\{.*\}|\[.*\])$/,N=/([A-Z])/g;J.extend({cache:{},uuid:0,expando:"jQuery"+(J.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return!!(a=a.nodeType?J.cache[a[J.expando]]:a[J.expando])&&!e(a)},data:function(a,c,d,e){if(J.acceptData(a)){var f,g,h,i=J.expando,j="string"==typeof c,k=a.nodeType,l=k?J.cache:a,m=k?a[i]:a[i]&&i,n="events"===c;if(m&&l[m]&&(n||e||l[m].data)||!j||d!==b)return m||(k?a[i]=m=++J.uuid:m=i),l[m]||(l[m]={},k||(l[m].toJSON=J.noop)),"object"!=typeof c&&"function"!=typeof c||(e?l[m]=J.extend(l[m],c):l[m].data=J.extend(l[m].data,c)),f=g=l[m],e||(g.data||(g.data={}),g=g.data),d!==b&&(g[J.camelCase(c)]=d),n&&!g[c]?f.events:(j?null==(h=g[c])&&(h=g[J.camelCase(c)]):h=g,h)}},removeData:function(a,b,c){if(J.acceptData(a)){var d,f,g,h=J.expando,i=a.nodeType,j=i?J.cache:a,k=i?a[h]:h;if(j[k]){if(b&&(d=c?j[k]:j[k].data)){J.isArray(b)||(b in d?b=[b]:(b=J.camelCase(b),b=b in d?[b]:b.split(" ")));for(f=0,g=b.length;f
t 1,null,!1))},removeData:function(a){return this.each(function(){J.removeData(this,a)})}}),J.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",J._data(a,b,(J._data(a,b)||0)+1))},_unmark:function(a,b,c){if(!0!==a&&(c=b,b=a,a=!1),b){c=c||"fx";var d=c+"mark",e=a?0:(J._data(b,d)||1)-1;e?J._data(b,d,e):(J.removeData(b,d,!0),f(b,c,"mark"))}},queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=J._data(a,b),c&&(!d||J.isArray(c)?d=J._data(a,b,J.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=J.queue(a,b),d=c.shift(),e={};"inprogress"===d&&(d=c.shift()),d&&("fx"===b&&c.unshift("inprogress"),J._data(a,b+".run",e),d.call(a,function(){J.dequeue(a,b)},e)),c.length||(J.removeData(a,b+"queue "+b+".run",!0),f(a,b,"queue"))}}),J.fn.extend({queue:function(a,c){var d=2;return"string"!=typeof a&&(c=a,a="fx",d--),arguments.length 1)},removeAttr:function(a){return this.each(function(){J.removeAttr(this,a)})},prop:function(a,b){return J.access(this,J.prop,a,b,arguments.length>1)},removeProp:function(a){return a=J.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(J.isFunction(a))return this.each(function(b){J(this).addClass(a.call(this,b,this.className))});if(a&&"string"==typeof a)for(b=a.split(S),c=0,d=this.length;c -1)return!0;return!1},val:function(a){var c,d,e,f=this[0];{if(arguments.length)return e=J.isFunction(a),this.each(function(d){var f,g=J(this);1===this.nodeType&&(f=e?a.call(this,d,g.val()):a,null==f?f="":"number"==typeof f?f+="":J.isArray(f)&&(f=J.map(f,function(a){return null==a?"":a+""})),(c=J.valHooks[this.type]||J.valHooks[this.nodeName.toLowerCase()])&&"set"in c&&c.set(this,f,"value")!==b||(this.value=f))});if(f)return(c=J.valHooks[f.type]||J.valHooks[f.nodeName.toLowerCase()])&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,"string"==typeof d?d.replace(T,""):null==d?"":d)}}}),J.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i="select-one"===a.type;if(f<0)return null;for(c=i?f:0,d=i?f+1:h.length;c =0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(a&&3!==i&&8!==i&&2!==i)return e&&c in J.attrFn?J(a)[c](d):void 0===a.getAttribute?J.prop(a,c,d):(h=1!==i||!J.isXMLDoc(a),h&&(c=c.toLowerCase(),g=J.attrHooks[c]||(X.test(c)?P:O)),d!==b?null===d?void J.removeAttr(a,c):g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,""+d),d):g&&"get"in g&&h&&null!==(f=g.get(a,c))?f:(f=a.getAttribute(c),null===f?b:f))},removeAttr:function(a,b){var c,d,e,f,g,h=0;if(b&&1===a.nodeType)for(d=b.toLowerCase().split(S),f=d.length;h =0}})});var Z=/^(?:textarea|input|select)$/i,$=/^([^\.]*)?(?:\.(.+))?$/,_=/(?:^|\s)hover(\.\S+)?\b/,aa=/^key/,ba=/^(?:mouse|contextmenu)|click/,ca=/^(?:focusinfocus|focusoutblur)$/,da=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,ea=function(a){var b=da.exec(a) +;return b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)")),b},fa=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c.class||{}).value))},ga=function(a){return J.event.special.hover?a:a.replace(_,"mouseenter$1 mouseleave$1")};J.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,p,q;if(3!==a.nodeType&&8!==a.nodeType&&c&&d&&(g=J._data(a))){for(d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=J.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return void 0===J||a&&J.event.triggered===a.type?b:J.event.dispatch.apply(h.elem,arguments)},h.elem=a),c=J.trim(ga(c)).split(" "),j=0;j =0&&(q=q.slice(0,-1),h=!0),q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),e&&!J.event.customEvent[q]||J.event.global[q]))if(c="object"==typeof c?c[J.expando]?c:new J.Event(q,c):new J.Event(q),c.type=q,c.isTrigger=!0,c.exclusive=h,c.namespace=r.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,l=q.indexOf(":")<0?"on"+q:"",e){if(c.result=b,c.target||(c.target=e),d=null!=d?J.makeArray(d):[],d.unshift(c),m=J.event.special[q]||{},!m.trigger||!1!==m.trigger.apply(e,d)){if(o=[[e,m.bindType||q]],!f&&!m.noBubble&&!J.isWindow(e)){for(p=m.delegateType||q,j=ca.test(p+q)?e:e.parentNode,k=null;j;j=j.parentNode)o.push([j,p]),k=j;k&&k===e.ownerDocument&&o.push([k.defaultView||k.parentWindow||a,p])}for(i=0;i o&&s.push({elem:this,matches:n.slice(o)}),d=0;d 0?this.on(b,null,a,c):this.trigger(b)},J.attrFn&&(J.attrFn[b]=!0),aa.test(b)&&(J.event.fixHooks[b]=J.event.keyHooks),ba.test(b)&&(J.event.fixHooks[b]=J.event.mouseHooks)}),/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +function(){function a(a,b,c,d,f,g){for(var h=0,i=d.length;h0){k=j;break}j=j[a]}d[h]=k}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e="sizcache"+(Math.random()+"").replace(".",""),f=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){return i=!1,0});var m=function(a,b,c,e){c=c||[],b=b||G;var f=b;if(1!==b.nodeType&&9!==b.nodeType)return[];if(!a||"string"!=typeof a)return c;var h,i,j,k,l,n,q,r,t=!0,u=m.isXML(b),w=[],x=a;do{if(d.exec(""),(h=d.exec(x))&&(x=h[3],w.push(h[1]),h[2])){k=h[3];break}}while(h);if(w.length>1&&p.exec(a))if(2===w.length&&o.relative[w[0]])i=v(w[0]+w[1],b,e);else for(i=o.relative[w[0]]?[b]:m(w.shift(),b);w.length;)a=w.shift(),o.relative[a]&&(a+=w.shift()),i=v(a,i,e);else if(!e&&w.length>1&&9===b.nodeType&&!u&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(l=m.find(w.shift(),b,u),b=l.expr?m.filter(l.expr,l.set)[0]:l.set[0]),b)for(l=e?{expr:w.pop(),set:s(e)}:m.find(w.pop(),1!==w.length||"~"!==w[0]&&"+"!==w[0]||!b.parentNode?b:b.parentNode,u),i=l.expr?m.filter(l.expr,l.set):l.set,w.length>0?j=s(i):t=!1;w.length;)n=w.pop(),q=n,o.relative[n]?q=w.pop():n="",null==q&&(q=b),o.relative[n](j,q,u);else j=w=[];if(j||(j=i),j||m.error(n||a),"[object Array]"===g.call(j))if(t)if(b&&1===b.nodeType)for(r=0;null!=j[r];r++)j[r]&&(!0===j[r]||1===j[r].nodeType&&m.contains(b,j[r]))&&c.push(i[r]);else for(r=0;null!=j[r];r++)j[r]&&1===j[r].nodeType&&c.push(i[r]);else c.push.apply(c,j);else s(j,c);return k&&(m(k,f,c,e),m.uniqueSort(c)),c};m.uniqueSort=function(a){if(t&&(h=i,a.sort(t),h))for(var b=1;b 0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e ":function(a,b){var c,d="string"==typeof b,e=0,f=a.length;if(d&&!l.test(b)){for(b=b.toLowerCase();e =0)?c||d.push(g):c&&(b[h]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if("nth"===a[1]){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec("even"===a[2]&&"2n"||"odd"===a[2]&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);return a[0]=f++,a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");return!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),"~="===a[2]&&(a[4]=" "+a[4]+" "),a},PSEUDO:function(a,b,c,e,f){if("not"===a[1]){if(!((d.exec(a[3])||"").length>1||/^\w/.test(a[3]))){var g=m.filter(a[3],b,c,!0^f);return c||e.push.apply(e,g),!1}a[3]=m(a[3],null,null,b)}else if(o.match.POS.test(a[0])||o.match.CHILD.test(a[0]))return!0;return a},POS:function(a){return a.unshift(!0),a}},filters:{enabled:function(a){return!1===a.disabled&&"hidden"!==a.type},disabled:function(a){return!0===a.disabled},checked:function(a){return!0===a.checked},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,!0===a.selected},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return"input"===a.nodeName.toLowerCase()&&"text"===c&&(b===c||null===b)},radio:function(a){return"input"===a.nodeName.toLowerCase()&&"radio"===a.type},checkbox:function(a){return"input"===a.nodeName.toLowerCase()&&"checkbox"===a.type},file:function(a){return"input"===a.nodeName.toLowerCase()&&"file"===a.type},password:function(a){return"input"===a.nodeName.toLowerCase()&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return("input"===b||"button"===b)&&"submit"===a.type},image:function(a){return"input"===a.nodeName.toLowerCase()&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return("input"===b||"button"===b)&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return 0===b},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2==0},odd:function(a,b){return b%2==1},lt:function(a,b,c){return b c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if("contains"===e)return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if("not"===e){for(var g=b[3],h=0,i=g.length;h=0}},ID:function(a,b){return 1===a.nodeType&&a.getAttribute("id")===b},TAG:function(a,b){return"*"===b&&1===a.nodeType||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):null!=a[c]?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return null==d?"!="===f:!f&&m.attr?null!=d:"="===f?e===g:"*="===f?e.indexOf(g)>=0:"~="===f?(" "+e+" ").indexOf(g)>=0:g?"!="===f?e!==g:"^="===f?0===e.indexOf(g):"$="===f?e.substr(e.length-g.length)===g:"|="===f&&(e===g||e.substr(0,g.length+1)===g+"-"):e&&!1!==d},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){return a=Array.prototype.slice.call(a,0),b?(b.push.apply(b,a),b):a};try{Array.prototype.slice.call(G.documentElement.childNodes,0)[0].nodeType}catch(w){s=function(a,b){var c=0,d=b||[];if("[object Array]"===g.call(a))Array.prototype.push.apply(d,a);else if("number"==typeof a.length)for(var e=a.length;c ",d.insertBefore(a,d.firstChild),G.getElementById(c)&&(o.find.ID=function(a,c,d){if(void 0!==c.getElementById&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||void 0!==e.getAttributeNode&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=void 0!==a.getAttributeNode&&a.getAttributeNode("id");return 1===a.nodeType&&c&&c.nodeValue===b}),d.removeChild(a),d=a=null}(),function(){var a=G.createElement("div");a.appendChild(G.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if("*"===a[1]){for(var d=[],e=0;c[e];e++)1===c[e].nodeType&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&void 0!==a.firstChild.getAttribute&&"#"!==a.firstChild.getAttribute("href")&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),G.querySelectorAll&&function(){var a=m,b=G.createElement("div");if(b.innerHTML="",!b.querySelectorAll||0!==b.querySelectorAll(".TEST").length){m=function(b,c,d,e){if(c=c||G,!e&&!m.isXML(c)){var f=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(f&&(1===c.nodeType||9===c.nodeType)){if(f[1])return s(c.getElementsByTagName(b),d);if(f[2]&&o.find.CLASS&&c.getElementsByClassName)return s(c.getElementsByClassName(f[2]),d)}if(9===c.nodeType){if("body"===b&&c.body)return s([c.body],d);if(f&&f[3]){var g=c.getElementById(f[3]);if(!g||!g.parentNode)return s([],d);if(g.id===f[3])return s([g],d)}try{return s(c.querySelectorAll(b),d)}catch(n){}}else if(1===c.nodeType&&"object"!==c.nodeName.toLowerCase()){var h=c,i=c.getAttribute("id"),j=i||"__sizzle__",k=c.parentNode,l=/^\s*[+~]/.test(b);i?j=j.replace(/'/g,"\\$&"):c.setAttribute("id",j),l&&k&&(c=c.parentNode);try{if(!l||k)return s(c.querySelectorAll("[id='"+j+"'] "+b),d)}catch(p){}finally{i||h.removeAttribute("id")}}}return a(b,c,d,e)};for(var c in a)m[c]=a[c];b=null}}(),function(){var a=G.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var c=!b.call(G.createElement("div"),"div"),d=!1;try{b.call(G.documentElement,"[test!='']:sizzle")}catch(e){d=!0}m.matchesSelector=function(a,e){if(e=e.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']"),!m.isXML(a))try{if(d||!o.match.PSEUDO.test(e)&&!/!=/.test(e)){var f=b.call(a,e);if(f||!c||a.document&&11!==a.document.nodeType)return f}}catch(w){}return m(e,null,null,[a]).length>0}}}(),function(){var a=G.createElement("div");a.innerHTML="",a.getElementsByClassName&&0!==a.getElementsByClassName("e").length&&(a.lastChild.className="e",1!==a.getElementsByClassName("e").length&&(o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(void 0!==b.getElementsByClassName&&!c)return b.getElementsByClassName(a[1])},a=null))}(),G.documentElement.contains?m.contains=function(a,b){return a!==b&&(!a.contains||a.contains(b))}:G.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(16&a.compareDocumentPosition(b))}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return!!b&&"HTML"!==b.nodeName};var v=function(a,b,c){for(var d,e=[],f="",g=b.nodeType?[b]:b;d=o.match.PSEUDO.exec(a);)f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(f=e;f =0:J.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d,e=[],f=this[0];if(J.isArray(a)){for(var g=1;f&&f.ownerDocument&&f!==b;){for(c=0;c -1:J.find.matchesSelector(f,a)){e.push(f);break}if(!(f=f.parentNode)||!f.ownerDocument||f===b||11===f.nodeType)break}return e=e.length>1?J.unique(e):e,this.pushStack(e,"closest",a)},index:function(a){return a?"string"==typeof a?J.inArray(this[0],J(a)):J.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c="string"==typeof a?J(a,b):J.makeArray(a&&a.nodeType?[a]:a),d=J.merge(this.get(),c);return this.pushStack(i(c[0])||i(d[0])?d:J.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),J.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return J.dir(a,"parentNode")},parentsUntil:function(a,b,c){return J.dir(a,"parentNode",c)},next:function(a){return J.nth(a,2,"nextSibling")},prev:function(a){return J.nth(a,2,"previousSibling")},nextAll:function(a){return J.dir(a,"nextSibling")},prevAll:function(a){return J.dir(a,"previousSibling")},nextUntil:function(a,b,c){return J.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return J.dir(a,"previousSibling",c)},siblings:function(a){return J.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return J.sibling(a.firstChild)},contents:function(a){return J.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:J.makeArray(a.childNodes)}},function(a,b){J.fn[a]=function(c,d){var e=J.map(this,b,c);return ha.test(a)||(d=c),d&&"string"==typeof d&&(e=J.filter(d,e)),e=this.length>1&&!na[a]?J.unique(e):e,(this.length>1||ja.test(d))&&ia.test(a)&&(e=e.reverse()),this.pushStack(e,a,la.call(arguments).join(","))}}),J.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),1===b.length?J.find.matchesSelector(b[0],a)?[b[0]]:[]:J.find.matches(a,b)},dir:function(a,c,d){for(var e=[],f=a[c];f&&9!==f.nodeType&&(d===b||1!==f.nodeType||!J(f).is(d));)1===f.nodeType&&e.push(f),f=f[c];return e},nth:function(a,b,c,d){b=b||1;for(var e=0;a&&(1!==a.nodeType||++e!==b);a=a[c]);return a},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}});var oa="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",pa=/ jQuery\d+="(?:\d+|null)"/g,qa=/^\s+/,ra=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,sa=/<([\w:]+)/,ta=/]","i"),ya=/checked\s*(?:[^=]|=\s*.checked.)/i,za=/\/(java|ecma)script/i,Aa=/^\s*",""],legend:[1,""],thead:[1," ","
"],tr:[2,"","
"],td:[3,""],col:[2,"
"," "],area:[1,""],_default:[0,"",""]},Ca=k(G);Ba.optgroup=Ba.option,Ba.tbody=Ba.tfoot=Ba.colgroup=Ba.caption=Ba.thead,Ba.th=Ba.td,J.support.htmlSerialize||(Ba._default=[1,"div
"," ",""]),J.fn.extend({text:function(a){return J.access(this,function(a){return a===b?J.text(this):this.empty().append((this[0]&&this[0].ownerDocument||G).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(J.isFunction(a))return this.each(function(b){J(this).wrapAll(a.call(this,b))});if(this[0]){var b=J(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){for(var a=this;a.firstChild&&1===a.firstChild.nodeType;)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return J.isFunction(a)?this.each(function(b){J(this).wrapInner(a.call(this,b))}):this.each(function(){var b=J(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=J.isFunction(a);return this.each(function(c){J(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){J.nodeName(this,"body")||J(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){1===this.nodeType&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){1===this.nodeType&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=J.clean(arguments);return a.push.apply(a,this.toArray()),this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);return a.push.apply(a,J.clean(arguments)),a}},remove:function(a,b){for(var c,d=0;null!=(c=this[d]);d++)a&&!J.filter(a,[c]).length||(b||1!==c.nodeType||(J.cleanData(c.getElementsByTagName("*")),J.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)for(1===a.nodeType&&J.cleanData(a.getElementsByTagName("*"));a.firstChild;)a.removeChild(a.firstChild);return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return J.clone(this,a,b)})},html:function(a){return J.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return 1===c.nodeType?c.innerHTML.replace(pa,""):null;if("string"==typeof a&&!va.test(a)&&(J.support.leadingWhitespace||!qa.test(a))&&!Ba[(sa.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ra,"<$1>$2>");try{for(;d1&&k 0?this.clone(!0):this).get();J(e[g])[b](i),d=d.concat(i)}return this.pushStack(d,a,e.selector)}}),J.extend({clone:function(a,b,c){var d,e,f,g=J.support.html5Clone||J.isXMLDoc(a)||!xa.test("<"+a.nodeName+">")?a.cloneNode(!0):r(a);if(!(J.support.noCloneEvent&&J.support.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||J.isXMLDoc(a)))for(n(a,g),d=o(a),e=o(g),f=0;d[f];++f)e[f]&&n(d[f],e[f]);if(b&&(m(a,g),c))for(d=o(a),e=o(g),f=0;d[f];++f)m(d[f],e[f]);return d=e=null,g},clean:function(a,b,c,d){var e,f,g,h=[];b=b||G,void 0===b.createElement&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||G);for(var i,j=0;null!=(i=a[j]);j++)if("number"==typeof i&&(i+=""),i){if("string"==typeof i)if(ua.test(i)){i=i.replace(ra,"<$1>$2>");var l,m=(sa.exec(i)||["",""])[1].toLowerCase(),n=Ba[m]||Ba._default,o=n[0],p=b.createElement("div"),r=Ca.childNodes;for(b===G?Ca.appendChild(p):k(b).appendChild(p),p.innerHTML=n[1]+i+n[2];o--;)p=p.lastChild;if(!J.support.tbody){var s=ta.test(i),t="table"!==m||s?" "!==n[1]||s?[]:p.childNodes:p.firstChild&&p.firstChild.childNodes;for(g=t.length-1;g>=0;--g)J.nodeName(t[g],"tbody")&&!t[g].childNodes.length&&t[g].parentNode.removeChild(t[g])}!J.support.leadingWhitespace&&qa.test(i)&&p.insertBefore(b.createTextNode(qa.exec(i)[0]),p.firstChild),i=p.childNodes,p&&(p.parentNode.removeChild(p),r.length>0&&(l=r[r.length-1])&&l.parentNode&&l.parentNode.removeChild(l))}else i=b.createTextNode(i);var u;if(!J.support.appendChecked)if(i[0]&&"number"==typeof(u=i.length))for(g=0;g1)},J.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Da(a,"opacity");return""===c?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{float:J.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var f,g,h=J.camelCase(c),i=a.style,j=J.cssHooks[h];if(c=J.cssProps[h]||h,d===b)return j&&"get"in j&&(f=j.get(a,!1,e))!==b?f:i[c];if(!(g=typeof d,"string"===g&&(f=La.exec(d))&&(d=+(f[1]+1)*+f[2]+parseFloat(J.css(a,c)),g="number"),null==d||"number"===g&&isNaN(d)||("number"!==g||J.cssNumber[h]||(d+="px"),j&&"set"in j&&(d=j.set(a,d))===b)))try{i[c]=d}catch(k){}}},css:function(a,c,d){var e,f;return c=J.camelCase(c),f=J.cssHooks[c],c=J.cssProps[c]||c,"cssFloat"===c&&(c="float"),f&&"get"in f&&(e=f.get(a,!0,d))!==b?e:Da?Da(a,c):void 0},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),J.curCSS=J.css,G.defaultView&&G.defaultView.getComputedStyle&&(Ea=function(a,b){var c,d,e,f,g=a.style;return b=b.replace(Ia,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(""!==(c=e.getPropertyValue(b))||J.contains(a.ownerDocument.documentElement,a)||(c=J.style(a,b))),!J.support.pixelMargin&&e&&Ma.test(b)&&Ka.test(c)&&(f=g.width,g.width=c,c=e.width,g.width=f),c}),G.documentElement.currentStyle&&(Fa=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;return null==f&&g&&(e=g[b])&&(f=e),Ka.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left="fontSize"===b?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d)),""===f?"auto":f}),Da=Ea||Fa,J.each(["height","width"],function(a,b){J.cssHooks[b]={get:function(a,c,d){if(c)return 0!==a.offsetWidth?s(a,b,d):J.swap(a,Na,function(){return s(a,b,d)})},set:function(a,b){return Ja.test(b)?b+"px":b}}}),J.support.opacity||(J.cssHooks.opacity={get:function(a,b){return Ha.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=J.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,b>=1&&""===J.trim(f.replace(Ga,""))&&(c.removeAttribute("filter"),d&&!d.filter)||(c.filter=Ga.test(f)?f.replace(Ga,e):f+" "+e)}}),J(function(){J.support.reliableMarginRight||(J.cssHooks.marginRight={get:function(a,b){return J.swap(a,{display:"inline-block"},function(){return b?Da(a,"margin-right"):a.style.marginRight})}})}),J.expr&&J.expr.filters&&(J.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return 0===b&&0===c||!J.support.reliableHiddenOffsets&&"none"===(a.style&&a.style.display||J.css(a,"display"))},J.expr.filters.visible=function(a){return!J.expr.filters.hidden(a)}),J.each({margin:"",padding:"",border:"Width"},function(a,b){J.cssHooks[a+b]={expand:function(c){var d,e="string"==typeof c?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+Oa[d]+b]=e[d]||e[d-2]||e[0];return f}}});var Pa,Qa,Ra=/%20/g,Sa=/\[\]$/,Ta=/\r?\n/g,Ua=/#.*$/,Va=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Wa=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,Xa=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,Ya=/^(?:GET|HEAD)$/,Za=/^\/\//,$a=/\?/,_a=/ + + + + + + + + + +
Kindle: Your Notes and Highlights + ++ + + + + + + + + + + + + + + + + + + + + +\ No newline at end of file diff --git a/License b/License index 65de889..b2b8754 100644 --- a/License +++ b/License @@ -1,7 +1,7 @@ -Copyright (c) 2016-21 [these people](https://github.com/hadynz/obsidian-kindle-plugin/graphs/contributors) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Copyright (c) 2016-21 [these people](https://github.com/hadynz/obsidian-kindle-plugin/graphs/contributors) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 9256c33..de264f0 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,79 @@ -# Obsidian Kindle Plugin - - - - -Sync (and resync) your Kindle notes and highlights directly into your [Obsidian][1] vault. You -can choose to sync using one of two methods: - -### Amazon's Kindle Reader - -Sync from the cloud any ebooks that you've purchased directly from Amazon. The plugin will -screen scrape your highlights from [Amazon's Kindle Reader][4] and continuously keep them in sync. - -This method will not work for highlights from books, articles, PDFs, and personal documents -not purchased from Amazon (see next method). - -### Kindle Device (My Clippings) - -Sync your highlights by uploading your `My Clippings.txt` file stored on your Kindle device. -This file includes highlights, bookmarks and notes for any book on your Kindle regardless -if it has been purchased via Amazon. - -You can extract your `My Clippings.txt` file by plugging it into your computer using USB. - - - -## Features - -- **Continuous, automatic syncing** — One button press to sync your highlights using your Amazon account via [Amazon's Kindle Reader][4]. - - Subsequent syncing will do an intelligent diff and bring in any new highlights without impacting any edits that you've done to your highlights file. - -- **Sync non-Amazon books** — Sync your highlights by uploading your `My Clippings.txt` file from your Kindle device - -- **Enriched metadata** — Enrich your notes by downloading extra metadata information about your book from Amazon.com - -- **Powerful, flexible templating with preview** — Customise your highlights and file names to your liking by configuring your own template using ([Nunjucks][2]) templating language with live preview - -## Mission statement - -Inspired by Obsidian's principle of "your data sitting in a local folder" and "never leaving -you're life's work held hostage in the cloud again", this plugin tries to do exactly that -with your precious Kindle notes and highlights. Why should you struggle in accessing your own -data, or paying for a third party service to access information that you own? - -## Known considerations - -### Security - -If you choose to sync your highlights via Amazon's online Kindle Reader, it is important to note -that by logging in to your Amazon account via Obsidian your Amazon session becomes available to -any other plugin across your vaults until your session expires. - -You can mitigate this risk by logging out after every sync (from settings) or using the offline -method of syncing by uploading your `My Clippings.txt` file instead. - -### Export limits - -For several reasons (see [here][5] and [here][6]) the Kindle platform can sometimes limit the amount -of highlighted text that can be exported from a particular book. This limit varies from book to book, purchased from Amazon or have DRM protection. There is currently no known alternative to work around this. - -## Say Thanks - -If you like this plugin and would like to buy me a coffee, you can! - -[+ + + +Annotated books from your library
(Most recently accessed shown first)Sorry, we''ve experienced a problem. Please try again.+Your search {0} did not match any of your annotated book titles or authors. Please try again.+ + + + + + + + + + + + + + + + + + + + + + + +++ + ++++++ + + + +++ +The concrete character of mind consists, then, wholly of the various arrangements formed by the various presentations in their different qualities. ++ +Note:I would add, that these things are the collective presence of the totality of memory, stored in the whole body and appearing as "mind". But mind is all that appears. If we call its presentations re-presentations, it presupposes that there was something else that could be symbolised, re-presented, imaged. I am not sure what grounds we have for presuming this. Sure it seems to be the case that I am here, seeing something out there and there are actors in the world who act, sometimes against me, there are things that feed me and things that kill me - but all of this is arising in the same place.+ + +++++ + + + +++ +Mind is wholly a matter of "contents." ++ +Note:#NB #quote mind is a matter of contents+ + +++++ + + + +++ + +(1) This or that kind of mind is formed by the use of objects which evoke this or that kind of reaction and which produce this or that arrangement among the reactions called out. The formation of mind is wholly a matter of the presentation of the proper educational materials. ++Note:+++++ + + + +++ + +Since the earlier presentations constitute the "apperceiving organs" which control the assimilation of new presentations, their character is all important. The effect of new presentations is to reinforce groupings previously formed. The business of the educator is, first, to select the proper material in order to fix the nature of the original reactions, and, secondly, to arrange the sequence of subsequent presentations on the basis of the store of ideas secured by prior transactions. The control is from behind, from the past, instead of, as in the unfolding conception, in the ultimate goal. ++Note:+++++ + + + +++ +The exercise of thought is, in the literal sense of that word, inference; by it one thing carries us over to the idea of, and belief in, another thing. It involves a jump, a leap, a going beyond what is surely known to something else accepted on its warrant. ++ +Note:The central role of #inference - knowledge requires a leap - you have to make a connection from one thing to another+ + +++++ + + + +++ + +Not until a thing has been tried—"tried out," in colloquial language—do we know its true worth. Till then it may be pretense, a bluff. But the thing that has come out victorious in a test or trial of strength carries its credentials with it; it is approved, because it has been proved. ++Note:+++++ + + + +++ +wrong. What is important, is that every inference shall be a tested inference; or (since often this is not possible) that we shall discriminate between beliefs that rest upon tested evidence and those that do not, and shall be accordingly on our guard as to the kind and degree of assent yielded ++ +Note:Once tested, test them again - new conditions, new time and all that - context etc.+ + ++ + + + + + + ++++++++
Would you like to take some notes?
+ + You haven’t created any notes for this book yet. You can add or remove bookmarks, highlights, and notes at any location in a Kindle book. + + ++Sorry, we''ve experienced a problem. Please try again.++ + + + + + ++ Once you delete this highlight, it will be removed from all of your devices. +
+ +++++ Sorry, we''ve experienced a problem. Please try again. +++ + + + ++ Once you delete this note, it will be removed from all of your devices. +
+ +++++ Sorry, we''ve experienced a problem. Please try again. ++ ++ + ++ + + ++ + +++++ Sorry, we''ve experienced a problem. Please try again. ++++++
+- + + + +
+- + + + +
++ + + ++++++ Sorry, we''ve experienced a problem. Please try again. ++++++
+- + + + +
+- + + + +
+](https://www.buymeacoffee.com/hadynz) - -[](https://github.com/sponsors/hadynz) - -## License - -[MIT](LICENSE) - -[1]: https://obsidian.md -[2]: https://mozilla.github.io/nunjucks -[3]: https://github.com/pjeby/hot-reload -[4]: https://read.amazon.com/notebook -[5]: https://help.readwise.io/article/47-why-are-my-kindle-highlights-truncated-ellipses#:~:text=Publishers%20require%20Amazon%20to%20place,the%20book%20will%20be%20truncated. -[6]: https://brian.carnell.com/articles/2018/route-around-amazon-kindles-ridiculous-limits-on-highlights-exporting-with-bookcision/ +# Obsidian Kindle Plugin + + + + +Sync (and resync) your Kindle notes and highlights directly into your [Obsidian][1] vault. You +can choose to sync using one of two methods: + +### Amazon's Kindle Reader + +Sync from the cloud any ebooks that you've purchased directly from Amazon. The plugin will +screen scrape your highlights from [Amazon's Kindle Reader][4] and continuously keep them in sync. + +This method will not work for highlights from books, articles, PDFs, and personal documents +not purchased from Amazon (see next method). + +### Kindle Device (My Clippings) + +Sync your highlights by uploading your `My Clippings.txt` file stored on your Kindle device. +This file includes highlights, bookmarks and notes for any book on your Kindle regardless +if it has been purchased via Amazon. + +You can extract your `My Clippings.txt` file by plugging it into your computer using USB. + + + +## Features + +- **Continuous, automatic syncing** — One button press to sync your highlights using your Amazon account via [Amazon's Kindle Reader][4]. + + Subsequent syncing will do an intelligent diff and bring in any new highlights without impacting any edits that you've done to your highlights file. + +- **Sync non-Amazon books** — Sync your highlights by uploading your `My Clippings.txt` file from your Kindle device + +- **Enriched metadata** — Enrich your notes by downloading extra metadata information about your book from Amazon.com + +- **Powerful, flexible templating with preview** — Customise your highlights and file names to your liking by configuring your own template using ([Nunjucks][2]) templating language with live preview + +## Mission statement + +Inspired by Obsidian's principle of "your data sitting in a local folder" and "never leaving +you're life's work held hostage in the cloud again", this plugin tries to do exactly that +with your precious Kindle notes and highlights. Why should you struggle in accessing your own +data, or paying for a third party service to access information that you own? + +## Known considerations + +### Security + +If you choose to sync your highlights via Amazon's online Kindle Reader, it is important to note +that by logging in to your Amazon account via Obsidian your Amazon session becomes available to +any other plugin across your vaults until your session expires. + +You can mitigate this risk by logging out after every sync (from settings) or using the offline +method of syncing by uploading your `My Clippings.txt` file instead. + +### Export limits + +For several reasons (see [here][5] and [here][6]) the Kindle platform can sometimes limit the amount +of highlighted text that can be exported from a particular book. This limit varies from book to book, purchased from Amazon or have DRM protection. There is currently no known alternative to work around this. + +## Say Thanks + +If you like this plugin and would like to buy me a coffee, you can! + +[
](https://www.buymeacoffee.com/hadynz) + +[](https://github.com/sponsors/hadynz) + +## License + +[MIT](LICENSE) + +[1]: https://obsidian.md +[2]: https://mozilla.github.io/nunjucks +[3]: https://github.com/pjeby/hot-reload +[4]: https://read.amazon.com/notebook +[5]: https://help.readwise.io/article/47-why-are-my-kindle-highlights-truncated-ellipses#:~:text=Publishers%20require%20Amazon%20to%20place,the%20book%20will%20be%20truncated. +[6]: https://brian.carnell.com/articles/2018/route-around-amazon-kindles-ridiculous-limits-on-highlights-exporting-with-bookcision/ diff --git a/jest.config.js b/jest.config.js index c4383f5..69cccec 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,13 +1,13 @@ -module.exports = { - transform: { - '^.+\\.tsx?$': 'ts-jest', - '^.+\\.njk?$': 'jest-text-transformer', - }, - moduleNameMapper: { - '^~/(.*)': '
/src/$1', - }, - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], - testRegex: '(/(tests|src)/.*.(test|spec))\\.(ts|js)x?$', - coverageDirectory: 'coverage', - collectCoverageFrom: ['src/**/*.test.{ts,tsx,js,jsx}', '!src/**/*.d.ts'], -}; +module.exports = { + transform: { + '^.+\\.tsx?$': 'ts-jest', + '^.+\\.njk?$': 'jest-text-transformer', + }, + moduleNameMapper: { + '^~/(.*)': ' /src/$1', + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + testRegex: '(/(tests|src)/.*.(test|spec))\\.(ts|js)x?$', + coverageDirectory: 'coverage', + collectCoverageFrom: ['src/**/*.test.{ts,tsx,js,jsx}', '!src/**/*.d.ts'], +}; diff --git a/manifest.json b/manifest.json index 8fa9f9a..266951b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ -{ - "id": "obsidian-kindle-plugin", - "name": "Kindle Highlights", - "version": "1.9.2", - "description": "Sync your Kindle book highlights using your Amazon login or uploading your My Clippings file", - "minAppVersion": "0.10.2", - "author": "Hady Osman", - "authorUrl": "https://hady.geek.nz", - "isDesktopOnly": true -} +{ + "id": "obsidian-kindle-plugin", + "name": "Kindle Highlights", + "version": "1.9.2", + "description": "Sync your Kindle book highlights using your Amazon login or uploading your My Clippings file", + "minAppVersion": "0.10.2", + "author": "Hady Osman", + "authorUrl": "https://hady.geek.nz", + "isDesktopOnly": true +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..53a7b7e --- /dev/null +++ b/package-lock.json @@ -0,0 +1,9703 @@ +{ + "name": "obsidian-kindle-plugin", + "version": "1.9.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "obsidian-kindle-plugin", + "version": "1.9.2", + "license": "MIT", + "dependencies": { + "@electron/remote": "^2.1.3", + "@hadynz/kindle-clippings": "^2.0.9", + "cheerio": "1.1.2", + "fletcher": "0.0.3", + "gray-matter": "^4.0.3", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "nunjucks": "^3.2.4", + "nunjucks-date-filter": "^0.1.1", + "sanitize-filename": "^1.6.3", + "svelte-loading-spinners": "^0.3.6", + "typed-emitter": "^2.1.0" + }, + "devDependencies": { + "@tsconfig/svelte": "^5.0.4", + "@types/faker": "^6.6.11", + "@types/jest": "^30.0.0", + "@types/js-yaml": "^4.0.9", + "@types/lodash": "^4.17.20", + "@types/nunjucks": "^3.2.6", + "@types/webpack": "^5.28.5", + "@typescript-eslint/eslint-plugin": "^8.40.0", + "@typescript-eslint/parser": "^8.40.0", + "babel-loader": "^10.0.0", + "copy-webpack-plugin": "^13.0.1", + "dotenv": "^17.2.1", + "electron": "^37.3.1", + "eslint": "^9.33.0", + "eslint-plugin-simple-import-sort": "^12.1.1", + "faker": "^5.5.3", + "husky": "^9.1.7", + "jest": "^30.0.5", + "jest-text-transformer": "^1.0.4", + "lint-staged": "^16.1.5", + "moment": "^2.30.1", + "obsidian": "^1.8.7", + "prettier": "^3.6.2", + "prettier-plugin-svelte": "^3.4.0", + "rimraf": "^6.0.1", + "svelte": "^5.38.2", + "svelte-check": "^4.3.1", + "svelte-loader": "^3.2.4", + "svelte-preprocess": "^6.0.3", + "terser-webpack-plugin": "^5.3.14", + "ts-jest": "^29.4.1", + "ts-loader": "^9.5.2", + "ts-node": "^10.9.2", + "typescript": "^5.9.2", + "uglify-js": "^3.19.3", + "webpack": "^5.101.3", + "webpack-cli": "^6.0.1", + "webpack-node-externals": "^3.0.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", + "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.3", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", + "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", + "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@codemirror/state": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", + "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.38.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.1.tgz", + "integrity": "sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@codemirror/state": "^6.5.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", + "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.17.0" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/remote": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@electron/remote/-/remote-2.1.3.tgz", + "integrity": "sha512-XlpxC8S4ttj/v2d+PKp9na/3Ev8bV7YWNL7Cw5b9MAWgTphEml7iYgbc7V0r9D6yDOfOkj06bchZgOZdlWJGNA==", + "license": "MIT", + "peerDependencies": { + "electron": ">= 13.0.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", + "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.4", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", + "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", + "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@hadynz/kindle-clippings": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@hadynz/kindle-clippings/-/kindle-clippings-2.0.9.tgz", + "integrity": "sha512-A2iZiw3/qw3N+3/WafJWuhdTH+oNzwlcXRCsVEXdHVpadx7N8g5dLQi6JB9RxXfmkqrfSQG+j6PP1cRpm2WmcA==", + "license": "MIT", + "dependencies": { + "eslint-plugin-simple-import-sort": "^10.0.0", + "lodash": "^4.17.21", + "tslib": "^2.3.1" + }, + "peerDependencies": { + "moment": "2.x" + } + }, + "node_modules/@hadynz/kindle-clippings/node_modules/eslint-plugin-simple-import-sort": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz", + "integrity": "sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==", + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.0.5.tgz", + "integrity": "sha512-xY6b0XiL0Nav3ReresUarwl2oIz1gTnxGbGpho9/rbUWsLH0f1OD/VT84xs8c7VmH7MChnLb0pag6PhZhAdDiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/core": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.0.5.tgz", + "integrity": "sha512-fKD0OulvRsXF1hmaFgHhVJzczWzA1RXMMo9LTPuFXo9q/alDbME3JIyWYqovWsUBWSoBcsHaGPSLF9rz4l9Qeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.0.5", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.0.5", + "jest-config": "30.0.5", + "jest-haste-map": "30.0.5", + "jest-message-util": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.5", + "jest-resolve-dependencies": "30.0.5", + "jest-runner": "30.0.5", + "jest-runtime": "30.0.5", + "jest-snapshot": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "jest-watcher": "30.0.5", + "micromatch": "^4.0.8", + "pretty-format": "30.0.5", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.5.tgz", + "integrity": "sha512-aRX7WoaWx1oaOkDQvCWImVQ8XNtdv5sEWgk4gxR6NXb7WBUnL5sRak4WRzIQRZ1VTWPvV4VI4mgGjNL9TeKMYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "jest-mock": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.5.tgz", + "integrity": "sha512-6udac8KKrtTtC+AXZ2iUN/R7dp7Ydry+Fo6FPFnDG54wjVMnb6vW/XNlf7Xj8UDjAE3aAVAsR4KFyKk3TCXmTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "30.0.5", + "jest-snapshot": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.5.tgz", + "integrity": "sha512-F3lmTT7CXWYywoVUGTCmom0vXq3HTTkaZyTAzIy+bXSBizB7o5qzlC9VCtq0arOa8GqmNsbg/cE9C6HLn7Szew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.5.tgz", + "integrity": "sha512-ZO5DHfNV+kgEAeP3gK3XlpJLL4U3Sz6ebl/n68Uwt64qFFs5bv4bfEEjyRGK5uM0C90ewooNgFuKMdkbEoMEXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.1.tgz", + "integrity": "sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.5.tgz", + "integrity": "sha512-7oEJT19WW4oe6HR7oLRvHxwlJk2gev0U9px3ufs8sX9PoD1Eza68KF0/tlN7X0dq/WVsBScXQGgCldA1V9Y/jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.5", + "@jest/expect": "30.0.5", + "@jest/types": "30.0.5", + "jest-mock": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.0.5.tgz", + "integrity": "sha512-mafft7VBX4jzED1FwGC1o/9QUM2xebzavImZMeqnsklgcyxBto8mV4HzNSzUrryJ+8R9MFOM3HgYuDradWR+4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "jest-worker": "30.0.5", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.5.tgz", + "integrity": "sha512-XcCQ5qWHLvi29UUrowgDFvV4t7ETxX91CbDczMnoqXPOIcZOxyNdSjm6kV5XMc8+HkxfRegU/MUmnTbJRzGrUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.0.5.tgz", + "integrity": "sha512-wPyztnK0gbDMQAJZ43tdMro+qblDHH1Ru/ylzUo21TBKqt88ZqnKKK2m30LKmLLoKtR2lxdpCC/P3g1vfKcawQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.0.5", + "@jest/types": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.0.5.tgz", + "integrity": "sha512-Aea/G1egWoIIozmDD7PBXUOxkekXl7ueGzrsGGi1SbeKgQqCYCIf+wfbflEbf2LiPxL8j2JZGLyrzZagjvW4YQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.0.5", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.5.tgz", + "integrity": "sha512-Vk8amLQCmuZyy6GbBht1Jfo9RSdBtg7Lks+B0PecnjI8J+PCLQPGh7uI8Q/2wwpW2gLdiAfiHNsmekKlywULqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.0.5", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.5", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/types": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.5.tgz", + "integrity": "sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.40", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.40.tgz", + "integrity": "sha512-gwBNIP8ZAYev/ORDWW0QvxdwPXwxBtLsdsJgSc7eDIRt8ubP+rxUBzPsrwnu16fgEF8Bx4lh/+mvQvJzcTM6Kw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", + "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^8.9.0" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/svelte": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-5.0.4.tgz", + "integrity": "sha512-BV9NplVgLmSi4mwKzD8BD/NQ8erOY/nUE/GpgWe2ckx+wIQF5RyRirn/QsSSCPeulVpc3RA/iJt6DpfTIZps0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/codemirror": { + "version": "5.60.8", + "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz", + "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/tern": "*" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/faker": { + "version": "6.6.11", + "resolved": "https://registry.npmjs.org/@types/faker/-/faker-6.6.11.tgz", + "integrity": "sha512-/m/YZdfPXeM3dnSBz4JDbbYXelBm+onjsX2+LZV1XPJjIOpdhoc8ngws67iyXdLJwLiigOcejBufaDdjuVWy3Q==", + "deprecated": "This is a stub types definition. faker provides its own type definitions, so you do not need this installed.", + "dev": true, + "license": "MIT", + "dependencies": { + "faker": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", + "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/nunjucks": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz", + "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/tern": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", + "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/webpack": { + "version": "5.28.5", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.5.tgz", + "integrity": "sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "tapable": "^2.2.0", + "webpack": "^5" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz", + "integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/type-utils": "8.40.0", + "@typescript-eslint/utils": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.40.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.40.0.tgz", + "integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.40.0.tgz", + "integrity": "sha512-/A89vz7Wf5DEXsGVvcGdYKbVM9F7DyFXj52lNYUDS1L9yJfqjW/fIp5PgMuEJL/KeqVTe2QSbXAGUZljDUpArw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.40.0", + "@typescript-eslint/types": "^8.40.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.40.0.tgz", + "integrity": "sha512-y9ObStCcdCiZKzwqsE8CcpyuVMwRouJbbSrNuThDpv16dFAj429IkM6LNb1dZ2m7hK5fHyzNcErZf7CEeKXR4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.40.0.tgz", + "integrity": "sha512-jtMytmUaG9d/9kqSl/W3E3xaWESo4hFDxAIHGVW/WKKtQhesnRIJSAJO6XckluuJ6KDB5woD1EiqknriCtAmcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz", + "integrity": "sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0", + "@typescript-eslint/utils": "8.40.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.40.0.tgz", + "integrity": "sha512-ETdbFlgbAmXHyFPwqUIYrfc12ArvpBhEVgGAxVYSwli26dn8Ko+lIo4Su9vI9ykTZdJn+vJprs/0eZU0YMAEQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.40.0.tgz", + "integrity": "sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.40.0", + "@typescript-eslint/tsconfig-utils": "8.40.0", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/visitor-keys": "8.40.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.40.0.tgz", + "integrity": "sha512-Cgzi2MXSZyAUOY+BFwGs17s7ad/7L+gKt6Y8rAVVWS+7o6wrjeFN4nVfTpbE25MNcxyJ+iYUXflbs2xR9h4UBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.40.0", + "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/typescript-estree": "8.40.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.40.0.tgz", + "integrity": "sha512-8CZ47QwalyRjsypfwnbI3hKy5gJDPmrkLjkgMxhi0+DZZ2QNx2naS6/hWoVYUHU7LU2zleF68V9miaVZvhFfTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.40.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-3.0.1.tgz", + "integrity": "sha512-u8d0pJ5YFgneF/GuvEiDA61Tf1VDomHHYMjv/wc9XzYj7nopltpG96nXN5dJRstxZhcNpV1g+nT6CydO7pHbjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "webpack": "^5.82.0", + "webpack-cli": "6.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-3.0.1.tgz", + "integrity": "sha512-coEmDzc2u/ffMvuW9aCjoRzNSPDl/XLuhPdlFRpT9tZHmJ/039az33CE7uH+8s0uL1j5ZNtfdv0HkfaKRBGJsQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "webpack": "^5.82.0", + "webpack-cli": "6.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-3.0.1.tgz", + "integrity": "sha512-sbgw03xQaCLiT6gcY/6u3qBDn01CWw/nbaXl3gTdTFuJJ75Gffv3E3DBpgvY2fkkrdS1fpjaXNOmJlnbtKauKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "webpack": "^5.82.0", + "webpack-cli": "6.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-jest": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.5.tgz", + "integrity": "sha512-mRijnKimhGDMsizTvBTWotwNpzrkHr+VvZUQBof2AufXKB8NXrL1W69TG20EvOz7aevx6FTJIaBuBkYxS8zolg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "30.0.5", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.0", + "babel-preset-jest": "30.0.1", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/babel-loader": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-10.0.0.tgz", + "integrity": "sha512-z8jt+EdS61AMw22nSfoNJAZ0vrtmhPRVi6ghL3rCeRZI8cdNYFiV5xeV3HbE7rlZZNmGH8BVccwWt8/ED0QOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": "^18.20.0 || ^20.10.0 || >=22.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5.61.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz", + "integrity": "sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz", + "integrity": "sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.0.1", + "babel-preset-current-node-syntax": "^1.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.3.tgz", + "integrity": "sha512-cDGv1kkDI4/0e5yON9yM5G/0A5u8sf5TnmdX5C9qHzI9PPu++sQ9zjm1k9NiOrf3riY4OkK0zSGqfvJyJsgCBQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001735", + "electron-to-chromium": "^1.5.204", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001736", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001736.tgz", + "integrity": "sha512-ImpN5gLEY8gWeqfLUyEF4b7mYWcYoR2Si1VhnrbM4JizRFmfGaAQ12PhNykq6nvI4XvKLrsp8Xde74D5phJOSw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/cheerio": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz", + "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==", + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.0.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.12.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", + "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-webpack-plugin": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.1.tgz", + "integrity": "sha512-J+YV3WfhY6W/Xf9h+J1znYuqTye2xkBUIGyTPWuBAT27qajBa5mR4f8WBmfDY3YjRftT2kqZZiLi1qf0H+UOFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-parent": "^6.0.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.2.0", + "serialize-javascript": "^6.0.2", + "tinyglobby": "^0.2.12" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT", + "optional": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz", + "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron": { + "version": "37.3.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-37.3.1.tgz", + "integrity": "sha512-7DhktRLqhe6OJh/Bo75bTI0puUYEmIwSzMinocgO63mx3MVjtIn2tYMzLmAleNIlud2htkjpsMG2zT4PiTCloA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^22.7.7", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.207", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.207.tgz", + "integrity": "sha512-mryFrrL/GXDTmAtIVMVf+eIXM09BBPlO5IQ7lUyKmK8d+A4VpRGG+M3ofoVef6qyF8s60rJei8ymlJxjUA8Faw==", + "dev": true, + "license": "ISC" + }, + "node_modules/electron/node_modules/@types/node": { + "version": "22.17.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.17.2.tgz", + "integrity": "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/electron/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "license": "MIT", + "optional": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", + "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.33.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz", + "integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/esm-env": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrap": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.0.tgz", + "integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.5.tgz", + "integrity": "sha512-P0te2pt+hHI5qLJkIR+iMvS+lYUZml8rKKsohVHAGY+uClp9XVbdyYNJOIjSRpHVp8s8YqxJCiHUkSYZGr8rtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/faker": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", + "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "license": "ISC" + }, + "node_modules/fletcher": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/fletcher/-/fletcher-0.0.3.tgz", + "integrity": "sha512-cyn1RJWoQDCM9A7CLVbYTN0TcQZ7GoN5hMDZAoIaRXD6PO0UjvRlQbrNzAbAJb7MX7rgUGNx5PMMexKL6gD/eQ==" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/gray-matter/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/htmlparser2": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.1", + "entities": "^6.0.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-reference": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.6" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.0.5.tgz", + "integrity": "sha512-y2mfcJywuTUkvLm2Lp1/pFX8kTgMO5yyQGq/Sk/n2mN7XWYp4JsCZ/QXW34M8YScgk8bPZlREH04f6blPnoHnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.0.5", + "@jest/types": "30.0.5", + "import-local": "^3.2.0", + "jest-cli": "30.0.5" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.5.tgz", + "integrity": "sha512-bGl2Ntdx0eAwXuGpdLdVYVr5YQHnSZlQ0y9HVDu565lCUAe9sj6JOtBbMmBBikGIegne9piDDIOeiLVoqTkz4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.0.5", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.0.5.tgz", + "integrity": "sha512-h/sjXEs4GS+NFFfqBDYT7y5Msfxh04EwWLhQi0F8kuWpe+J/7tICSlswU8qvBqumR3kFgHbfu7vU6qruWWBPug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.5", + "@jest/expect": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.0.5", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-runtime": "30.0.5", + "jest-snapshot": "30.0.5", + "jest-util": "30.0.5", + "p-limit": "^3.1.0", + "pretty-format": "30.0.5", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-cli": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.0.5.tgz", + "integrity": "sha512-Sa45PGMkBZzF94HMrlX4kUyPOwUpdZasaliKN3mifvDmkhLYqLLg8HQTzn6gq7vJGahFYMQjXgyJWfYImKZzOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/types": "30.0.5", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.0.5.tgz", + "integrity": "sha512-aIVh+JNOOpzUgzUnPn5FLtyVnqc3TQHVMupYtyeURSb//iLColiMIR8TxCIDKyx9ZgjKnXGucuW68hCxgbrwmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/get-type": "30.0.1", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.0.5", + "@jest/types": "30.0.5", + "babel-jest": "30.0.5", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.0.5", + "jest-docblock": "30.0.1", + "jest-environment-node": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.5", + "jest-runner": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.0.5", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.5.tgz", + "integrity": "sha512-1UIqE9PoEKaHcIKvq2vbibrCog4Y8G0zmOxgQUVEiTqwR5hJVMCoDsN1vFvI5JvwD37hjueZ1C4l2FyGnfpE0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.0.1.tgz", + "integrity": "sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-each": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.0.5.tgz", + "integrity": "sha512-dKjRsx1uZ96TVyejD3/aAWcNKy6ajMaN531CwWIsrazIqIoXI9TnnpPlkrEYku/8rkS3dh2rbH+kMOyiEIv0xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.5", + "chalk": "^4.1.2", + "jest-util": "30.0.5", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.0.5.tgz", + "integrity": "sha512-ppYizXdLMSvciGsRsMEnv/5EFpvOdXBaXRBzFUDPWrsfmog4kYrOGWXarLllz6AXan6ZAA/kYokgDWuos1IKDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.5", + "@jest/fake-timers": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "jest-mock": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.5.tgz", + "integrity": "sha512-dkmlWNlsTSR0nH3nRfW5BKbqHefLZv0/6LCccG0xFCTWcJu8TuEwG+5Cm75iBfjVoockmO6J35o5gxtFSn5xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.5", + "jest-worker": "30.0.5", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" + } + }, + "node_modules/jest-leak-detector": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.0.5.tgz", + "integrity": "sha512-3Uxr5uP8jmHMcsOtYMRB/zf1gXN3yUIc+iPorhNETG54gErFIiUhLvyY/OggYpSMOEYqsmRxmuU4ZOoX5jpRFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.5.tgz", + "integrity": "sha512-uQgGWt7GOrRLP1P7IwNWwK1WAQbq+m//ZY0yXygyfWp0rJlksMSLQAA4wYQC3b6wl3zfnchyTx+k3HZ5aPtCbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.5", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.5.tgz", + "integrity": "sha512-NAiDOhsK3V7RU0Aa/HnrQo+E4JlbarbmI3q6Pi4KcxicdtjV82gcIUrejOtczChtVQR4kddu1E1EJlW6EN9IyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.5", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.5", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.5.tgz", + "integrity": "sha512-Od7TyasAAQX/6S+QCbN6vZoWOMwlTtzzGuxJku1GhGanAjz9y+QsQkpScDmETvdc9aSXyJ/Op4rhpMYBWW91wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "jest-util": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.0.5.tgz", + "integrity": "sha512-d+DjBQ1tIhdz91B79mywH5yYu76bZuE96sSbxj8MkjWVx5WNdt1deEFRONVL4UkKLSrAbMkdhb24XN691yDRHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.5.tgz", + "integrity": "sha512-/xMvBR4MpwkrHW4ikZIWRttBBRZgWK4d6xt3xW1iRDSKt4tXzYkMkyPfBnSCgv96cpkrctfXs6gexeqMYqdEpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.0.5.tgz", + "integrity": "sha512-JcCOucZmgp+YuGgLAXHNy7ualBx4wYSgJVWrYMRBnb79j9PD0Jxh0EHvR5Cx/r0Ce+ZBC4hCdz2AzFFLl9hCiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.0.5", + "@jest/environment": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.0.1", + "jest-environment-node": "30.0.5", + "jest-haste-map": "30.0.5", + "jest-leak-detector": "30.0.5", + "jest-message-util": "30.0.5", + "jest-resolve": "30.0.5", + "jest-runtime": "30.0.5", + "jest-util": "30.0.5", + "jest-watcher": "30.0.5", + "jest-worker": "30.0.5", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.5.tgz", + "integrity": "sha512-7oySNDkqpe4xpX5PPiJTe5vEa+Ak/NnNz2bGYZrA1ftG3RL3EFlHaUkA1Cjx+R8IhK0Vg43RML5mJedGTPNz3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.5", + "@jest/fake-timers": "30.0.5", + "@jest/globals": "30.0.5", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.5", + "jest-snapshot": "30.0.5", + "jest-util": "30.0.5", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.5.tgz", + "integrity": "sha512-T00dWU/Ek3LqTp4+DcW6PraVxjk28WY5Ua/s+3zUKSERZSNyxTqhDXCWKG5p2HAJ+crVQ3WJ2P9YVHpj1tkW+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "@jest/snapshot-utils": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.5", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.5", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "pretty-format": "30.0.5", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-text-transformer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/jest-text-transformer/-/jest-text-transformer-1.0.4.tgz", + "integrity": "sha512-Qi3FpWP6EFxZimSD05Zlmd/WER8l/3agVG7e5voHgdnM2vTs45sxS/i8qMWMO/dBkoxajndrGXfJTvhEENnjqw==", + "dev": true, + "license": "ISC", + "dependencies": { + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=9.5.0", + "npm": ">=5.8.0" + } + }, + "node_modules/jest-util": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.5.tgz", + "integrity": "sha512-pvyPWssDZR0FlfMxCBoc0tvM8iUEskaRFALUtGQYzVEAqisAztmy+R8LnU14KT4XA0H/a5HMVTXat1jLne010g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.5.tgz", + "integrity": "sha512-ouTm6VFHaS2boyl+k4u+Qip4TSH7Uld5tyD8psQ8abGgt2uYYB8VwVfAHWHjHc0NWmGGbwO5h0sCPOGHHevefw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.5", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.0.5.tgz", + "integrity": "sha512-z9slj/0vOwBDBjN3L4z4ZYaA+pG56d6p3kTUhFRYGvXbXMWhXmb/FIxREZCD06DYUwDKKnj2T80+Pb71CQ0KEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.0.5", + "string-length": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.5.tgz", + "integrity": "sha512-ojRXsWzEP16NdUuBw/4H/zkZdHOa7MMYCk4E430l+8fELeLg/mqmMlRhjL7UNZvQrDmnovWZV4DxX03fZF48fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.5", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lint-staged": { + "version": "16.1.5", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.1.5.tgz", + "integrity": "sha512-uAeQQwByI6dfV7wpt/gVqg+jAPaSp8WwOA8kKC/dv1qw14oGpnpAisY65ibGHUGDUv0rYaZ8CAJZ/1U8hUvC2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.5.0", + "commander": "^14.0.0", + "debug": "^4.4.1", + "lilconfig": "^3.1.3", + "listr2": "^9.0.1", + "micromatch": "^4.0.8", + "nano-spawn": "^1.0.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.8.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/listr2": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.2.tgz", + "integrity": "sha512-VVd7cS6W+vLJu2wmq4QmfVj14Iep7cz4r/OWNk36Aq5ZOY7G8/BfCrQFexcwB1OIxB3yERiePfE/REBjEFulag==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT" + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nano-spawn": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.2.tgz", + "integrity": "sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", + "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "license": "MIT" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "license": "BSD-2-Clause", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/nunjucks-date-filter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/nunjucks-date-filter/-/nunjucks-date-filter-0.1.1.tgz", + "integrity": "sha512-xKIMGB+UH1mRnk1/ofAVpU+6Fm52KQWfkCCjMWYohuBTj/Id/qy8zIVuE5lpwtavPyHz96sW2dCawNdPPhn0SQ==", + "dependencies": { + "moment": "^2.9.0" + } + }, + "node_modules/nunjucks/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/obsidian": { + "version": "1.8.7", + "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.8.7.tgz", + "integrity": "sha512-h4bWwNFAGRXlMlMAzdEiIM2ppTGlrh7uGOJS6w4gClrsjc+ei/3YAtU2VdFUlCiPuTHpY4aBpFJJW75S1Tl/JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/codemirror": "5.60.8", + "moment": "2.29.4" + }, + "peerDependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, + "node_modules/obsidian/node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-svelte": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.4.0.tgz", + "integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": "^3.0.0", + "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" + } + }, + "node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/lru-cache": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/schema-utils": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-mod": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svelte": { + "version": "5.38.2", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.38.2.tgz", + "integrity": "sha512-iAcp/oFAWauVSGILdD67n7DiwgLHXZzWZIdzl7araRxu72jUr7PFAo2Iie7gXt0IbnlYvhxCb9GT3ZJUquO3PA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@sveltejs/acorn-typescript": "^1.0.5", + "@types/estree": "^1.0.5", + "acorn": "^8.12.1", + "aria-query": "^5.3.1", + "axobject-query": "^4.1.0", + "clsx": "^2.1.1", + "esm-env": "^1.2.1", + "esrap": "^2.1.0", + "is-reference": "^3.0.3", + "locate-character": "^3.0.0", + "magic-string": "^0.30.11", + "zimmerframe": "^1.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/svelte-check": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.3.1.tgz", + "integrity": "sha512-lkh8gff5gpHLjxIV+IaApMxQhTGnir2pNUAqcNgeKkvK5bT/30Ey/nzBxNLDlkztCH4dP7PixkMt9SWEKFPBWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "chokidar": "^4.0.1", + "fdir": "^6.2.0", + "picocolors": "^1.0.0", + "sade": "^1.7.4" + }, + "bin": { + "svelte-check": "bin/svelte-check" + }, + "engines": { + "node": ">= 18.0.0" + }, + "peerDependencies": { + "svelte": "^4.0.0 || ^5.0.0-next.0", + "typescript": ">=5.0.0" + } + }, + "node_modules/svelte-check/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/svelte-check/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/svelte-check/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/svelte-dev-helper": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/svelte-dev-helper/-/svelte-dev-helper-1.1.9.tgz", + "integrity": "sha512-oU+Xv7Dl4kRU2kdFjsoPLfJfnt5hUhsFUZtuzI3Ku/f2iAFZqBoEuXOqK3N9ngD4dxQOmN4OKWPHVi3NeAeAfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/svelte-hmr": { + "version": "0.14.12", + "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.12.tgz", + "integrity": "sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.20 || ^14.13.1 || >= 16" + }, + "peerDependencies": { + "svelte": ">=3.19.0" + } + }, + "node_modules/svelte-loader": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/svelte-loader/-/svelte-loader-3.2.4.tgz", + "integrity": "sha512-e0HdDnkYH/MDx4/IfTSka5AOFg9yYJcPuoZJB5x0l60fkHjVjNvrrxr+rJegDG9J7ZymmdHt00/hdLw+QF299w==", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.4", + "svelte-dev-helper": "^1.1.9", + "svelte-hmr": "^0.14.2" + }, + "peerDependencies": { + "svelte": "^3.0.0 || ^4.0.0-next.0 || ^5.0.0-next.1" + } + }, + "node_modules/svelte-loading-spinners": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/svelte-loading-spinners/-/svelte-loading-spinners-0.3.6.tgz", + "integrity": "sha512-mthHQ2TwiwzTWzbFry3CBnVEfzqPOD9WkVw84OfSYzHRq6N9wgQ+yv37u81uPeuLU/ZOIPqhujpXquB1aol5ZQ==", + "license": "MIT" + }, + "node_modules/svelte-preprocess": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-6.0.3.tgz", + "integrity": "sha512-PLG2k05qHdhmRG7zR/dyo5qKvakhm8IJ+hD2eFRQmMLHp7X3eJnjeupUtvuRpbNiF31RjVw45W+abDwHEmP5OA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.10.2", + "coffeescript": "^2.5.1", + "less": "^3.11.3 || ^4.0.0", + "postcss": "^7 || ^8", + "postcss-load-config": ">=3", + "pug": "^3.0.0", + "sass": "^1.26.8", + "stylus": ">=0.55", + "sugarss": "^2.0.0 || ^3.0.0 || ^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.100 || ^5.0.0", + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "coffeescript": { + "optional": true + }, + "less": { + "optional": true + }, + "postcss": { + "optional": true + }, + "postcss-load-config": { + "optional": true + }, + "pug": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.43.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.14.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-jest": { + "version": "29.4.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.1.tgz", + "integrity": "sha512-SaeUtjfpg9Uqu8IbeDKtdaS0g8lS6FT6OzM3ezrDfErPJPHNDo/Ey+VFGP1bQIDfagYDLyRpd7O15XpG1Es2Uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.2", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ts-loader": { + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz", + "integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz", + "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==", + "license": "MIT", + "optionalDependencies": { + "rxjs": "*" + } + }, + "node_modules/typescript": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undici": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", + "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "license": "(WTFPL OR MIT)" + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.101.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz", + "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.3", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.2", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.11", + "watchpack": "^2.4.1", + "webpack-sources": "^3.3.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", + "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "^0.6.1", + "@webpack-cli/configtest": "^3.0.1", + "@webpack-cli/info": "^3.0.1", + "@webpack-cli/serve": "^3.0.1", + "colorette": "^2.0.14", + "commander": "^12.1.0", + "cross-spawn": "^7.0.3", + "envinfo": "^7.14.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^6.0.1" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.82.0" + }, + "peerDependenciesMeta": { + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zimmerframe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", + "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json index 31f9101..446b7ad 100644 --- a/package.json +++ b/package.json @@ -1,83 +1,86 @@ -{ - "name": "obsidian-kindle-plugin", - "version": "1.9.2", - "description": "Sync your Kindle book highlights using your Amazon login or uploading your My Clippings file", - "main": "src/index.ts", - "repository": { - "type": "git", - "url": "https://github.com/hadynz/obsidian-kindle-highlights.git" - }, - "keywords": [], - "author": { - "name": "Hady Osman", - "email": "hadyos@gmail.com", - "url": "https://hady.geek.nz" - }, - "license": "MIT", - "scripts": { - "prettier": "prettier --write '**/*.{ts,js,css,html}'", - "lint": "tsc --noemit && svelte-check && eslint . --ext .ts", - "clean": "rimraf dist main.js*", - "test": "jest", - "test-verbose": "jest --verbose", - "test-watch": "jest --watch", - "dev": "NODE_ENV=development webpack && cp ./dist/main.js* .", - "build": "NODE_ENV=production webpack", - "prepare": "husky install" - }, - "dependencies": { - "@hadynz/kindle-clippings": "^2.0.0", - "cheerio": "1.0.0-rc.6", - "fletcher": "0.0.3", - "gray-matter": "^4.0.3", - "lodash": "^4.17.21", - "nunjucks": "^3.2.3", - "nunjucks-date-filter": "^0.1.1", - "sanitize-filename": "^1.6.3", - "svelte-loading-spinners": "^0.1.4", - "typed-emitter": "^1.4.0" - }, - "devDependencies": { - "@tsconfig/svelte": "^1.0.10", - "@types/faker": "^5.5.8", - "@types/jest": "^26.0.22", - "@types/lodash": "^4.14.175", - "@types/nunjucks": "^3.1.4", - "@types/webpack": "^5.28.0", - "@typescript-eslint/eslint-plugin": "^4.22.0", - "@typescript-eslint/parser": "^4.22.0", - "babel-loader": "^8.2.2", - "copy-webpack-plugin": "^10.0.0", - "dotenv": "^16.0.1", - "electron": "^12.0.4", - "eslint": "^7.24.0", - "eslint-plugin-simple-import-sort": "^7.0.0", - "faker": "^5.5.3", - "husky": "^7.0.4", - "jest": "^26.6.3", - "jest-text-transformer": "^1.0.4", - "lint-staged": "^11.2.4", - "moment": "^2.29.1", - "obsidian": "^0.12.0", - "prettier": "^2.2.1", - "prettier-plugin-svelte": "^2.2.0", - "rimraf": "^3.0.2", - "svelte": "^3.44.2", - "svelte-check": "^1.6.0", - "svelte-loader": "^3.1.2", - "svelte-preprocess": "^4.9.8", - "terser-webpack-plugin": "^5.2.5", - "ts-jest": "^26.5.4", - "ts-loader": "^8.1.0", - "ts-node": "^10.4.0", - "typescript": "^4.2.3", - "uglify-js": "^3.14.3", - "webpack": "^5.30.0", - "webpack-cli": "^4.6.0", - "webpack-node-externals": "^2.5.2" - }, - "lint-staged": { - "*.ts": "eslint --cache --fix", - "*.{js,css,md}": "prettier --write" - } -} +{ + "name": "obsidian-kindle-plugin", + "version": "1.9.2", + "description": "Sync your Kindle book highlights using your Amazon login or uploading your My Clippings file", + "main": "src/index.ts", + "repository": { + "type": "git", + "url": "https://github.com/hadynz/obsidian-kindle-highlights.git" + }, + "keywords": [], + "author": { + "name": "Hady Osman", + "email": "hadyos@gmail.com", + "url": "https://hady.geek.nz" + }, + "license": "MIT", + "scripts": { + "prettier": "prettier --write '**/*.{ts,js,css,html}'", + "lint": "tsc --noemit && svelte-check && eslint . --ext .ts", + "clean": "rimraf dist main.js*", + "test": "jest", + "test-verbose": "jest --verbose", + "test-watch": "jest --watch", + "dev": "NODE_ENV=development webpack && cp ./dist/main.js* .", + "build": "cross-env NODE_ENV=production webpack", + "prepare": "husky install" + }, + "dependencies": { + "@hadynz/kindle-clippings": "^2.0.0", + "cheerio": "1.0.0-rc.6", + "fletcher": "0.0.3", + "gray-matter": "^4.0.3", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "nunjucks": "^3.2.3", + "nunjucks-date-filter": "^0.1.1", + "sanitize-filename": "^1.6.3", + "svelte-loading-spinners": "^0.1.4", + "typed-emitter": "^1.4.0" + }, + "devDependencies": { + "@tsconfig/svelte": "^1.0.10", + "@types/faker": "^5.5.8", + "@types/jest": "^26.0.22", + "@types/js-yaml": "^4.0.5", + "@types/lodash": "^4.14.175", + "@types/nunjucks": "^3.1.4", + "@types/webpack": "^5.28.0", + "@typescript-eslint/eslint-plugin": "^4.22.0", + "@typescript-eslint/parser": "^4.22.0", + "babel-loader": "^8.2.2", + "copy-webpack-plugin": "^10.0.0", + "cross-env": "^10.0.0", + "dotenv": "^16.0.1", + "electron": "^12.0.4", + "eslint": "^7.24.0", + "eslint-plugin-simple-import-sort": "^7.0.0", + "faker": "^5.5.3", + "husky": "^7.0.4", + "jest": "^26.6.3", + "jest-text-transformer": "^1.0.4", + "lint-staged": "^11.2.4", + "moment": "^2.29.1", + "obsidian": "^0.12.0", + "prettier": "^2.2.1", + "prettier-plugin-svelte": "^2.2.0", + "rimraf": "^3.0.2", + "svelte": "^3.44.2", + "svelte-check": "^1.6.0", + "svelte-loader": "^3.1.2", + "svelte-preprocess": "^4.9.8", + "terser-webpack-plugin": "^5.2.5", + "ts-jest": "^26.5.4", + "ts-loader": "^8.1.0", + "ts-node": "^10.4.0", + "typescript": "^4.2.3", + "uglify-js": "^3.14.3", + "webpack": "^5.30.0", + "webpack-cli": "^4.6.0", + "webpack-node-externals": "^2.5.2" + }, + "lint-staged": { + "*.ts": "eslint --cache --fix", + "*.{js,css,md}": "prettier --write" + } +} diff --git a/src/amazonRegion.ts b/src/amazonRegion.ts index 1547227..f20321a 100644 --- a/src/amazonRegion.ts +++ b/src/amazonRegion.ts @@ -1,71 +1,71 @@ -import _ from 'lodash'; -import { get } from 'svelte/store'; - -import type { AmazonAccount, AmazonAccountRegion } from '~/models'; -import { settingsStore } from '~/store'; - -export const AmazonRegions: Record = { - global: { - name: 'Global', - hostname: 'amazon.com', - kindleReaderUrl: 'https://read.amazon.com', - notebookUrl: 'https://read.amazon.com/notebook', - }, - india: { - name: 'India', - hostname: 'amazon.in', - kindleReaderUrl: 'https://read.amazon.in', - notebookUrl: 'https://read.amazon.in/notebook', - }, - japan: { - name: 'Japan', - hostname: 'amazon.co.jp', - kindleReaderUrl: 'https://read.amazon.co.jp', - notebookUrl: 'https://read.amazon.co.jp/notebook', - }, - spain: { - name: 'Spain', - hostname: 'amazon.es', - kindleReaderUrl: 'https://leer.amazon.es', - notebookUrl: 'https://leer.amazon.es/notebook', - }, - germany: { - name: 'Germany/Swiss/Austria', - hostname: 'amazon.de', - kindleReaderUrl: 'https://lesen.amazon.de', - notebookUrl: 'https://lesen.amazon.de/notebook', - }, - italy: { - name: 'Italy', - hostname: 'amazon.it', - kindleReaderUrl: 'https://leggi.amazon.it', - notebookUrl: 'https://leggi.amazon.it/notebook', - }, - UK: { - name: 'UK', - hostname: 'amazon.co.uk', - kindleReaderUrl: 'https://read.amazon.co.uk', - notebookUrl: 'https://read.amazon.co.uk/notebook', - }, - france: { - name: 'France', - hostname: 'amazon.fr', - kindleReaderUrl: 'https://lire.amazon.fr', - notebookUrl: 'https://lire.amazon.fr/notebook', - }, -}; - -export const currentAmazonRegion = (): AmazonAccount => { - const selectedRegion = get(settingsStore).amazonRegion; - return AmazonRegions[selectedRegion]; -}; - -export const orderedAmazonRegions = (): AmazonAccountRegion[] => { - const keys = Object.keys(AmazonRegions) as AmazonAccountRegion[]; - - // Remove 'global' as we will add it manually again top of the list - _.remove(keys, (key) => key === 'global'); - - const orderedKeys = _.orderBy(keys, (key) => key.toLowerCase(), 'asc'); - return ['global', ...orderedKeys]; -}; +import _ from 'lodash'; +import { get } from 'svelte/store'; + +import type { AmazonAccount, AmazonAccountRegion } from '~/models'; +import { settingsStore } from '~/store'; + +export const AmazonRegions: Record = { + global: { + name: 'Global', + hostname: 'amazon.com', + kindleReaderUrl: 'https://read.amazon.com', + notebookUrl: 'https://read.amazon.com/notebook', + }, + india: { + name: 'India', + hostname: 'amazon.in', + kindleReaderUrl: 'https://read.amazon.in', + notebookUrl: 'https://read.amazon.in/notebook', + }, + japan: { + name: 'Japan', + hostname: 'amazon.co.jp', + kindleReaderUrl: 'https://read.amazon.co.jp', + notebookUrl: 'https://read.amazon.co.jp/notebook', + }, + spain: { + name: 'Spain', + hostname: 'amazon.es', + kindleReaderUrl: 'https://leer.amazon.es', + notebookUrl: 'https://leer.amazon.es/notebook', + }, + germany: { + name: 'Germany/Swiss/Austria', + hostname: 'amazon.de', + kindleReaderUrl: 'https://lesen.amazon.de', + notebookUrl: 'https://lesen.amazon.de/notebook', + }, + italy: { + name: 'Italy', + hostname: 'amazon.it', + kindleReaderUrl: 'https://leggi.amazon.it', + notebookUrl: 'https://leggi.amazon.it/notebook', + }, + UK: { + name: 'UK', + hostname: 'amazon.co.uk', + kindleReaderUrl: 'https://read.amazon.co.uk', + notebookUrl: 'https://read.amazon.co.uk/notebook', + }, + france: { + name: 'France', + hostname: 'amazon.fr', + kindleReaderUrl: 'https://lire.amazon.fr', + notebookUrl: 'https://lire.amazon.fr/notebook', + }, +}; + +export const currentAmazonRegion = (): AmazonAccount => { + const selectedRegion = get(settingsStore).amazonRegion; + return AmazonRegions[selectedRegion]; +}; + +export const orderedAmazonRegions = (): AmazonAccountRegion[] => { + const keys = Object.keys(AmazonRegions) as AmazonAccountRegion[]; + + // Remove 'global' as we will add it manually again top of the list + _.remove(keys, (key) => key === 'global'); + + const orderedKeys = _.orderBy(keys, (key) => key.toLowerCase(), 'asc'); + return ['global', ...orderedKeys]; +}; diff --git a/src/assets/amazonIcon.svg b/src/assets/amazonIcon.svg index 48ea293..f34ffff 100644 --- a/src/assets/amazonIcon.svg +++ b/src/assets/amazonIcon.svg @@ -1,5 +1,5 @@ - + diff --git a/src/assets/circleExclamation.svg b/src/assets/circleExclamation.svg index b4140fe..e4111dc 100644 --- a/src/assets/circleExclamation.svg +++ b/src/assets/circleExclamation.svg @@ -1,6 +1,6 @@ - + diff --git a/src/assets/circleTick.svg b/src/assets/circleTick.svg index 97daf94..ab0cd9e 100644 --- a/src/assets/circleTick.svg +++ b/src/assets/circleTick.svg @@ -1,6 +1,6 @@ - + diff --git a/src/assets/clippingsIcon.svg b/src/assets/clippingsIcon.svg index 7b37eea..1bc65eb 100644 --- a/src/assets/clippingsIcon.svg +++ b/src/assets/clippingsIcon.svg @@ -1,3 +1,3 @@ - + diff --git a/src/assets/fileSyncIcon.svg b/src/assets/fileSyncIcon.svg index 929ee77..de691e3 100644 --- a/src/assets/fileSyncIcon.svg +++ b/src/assets/fileSyncIcon.svg @@ -1,30 +1,30 @@ - - - - + + + + diff --git a/src/assets/hashIcon.svg b/src/assets/hashIcon.svg index d8eaae1..1b4008d 100644 --- a/src/assets/hashIcon.svg +++ b/src/assets/hashIcon.svg @@ -1,7 +1,7 @@ - + diff --git a/src/assets/kindleIcon.svg b/src/assets/kindleIcon.svg index bacab63..4256f94 100644 --- a/src/assets/kindleIcon.svg +++ b/src/assets/kindleIcon.svg @@ -1,3 +1,3 @@ - + diff --git a/src/components/amazonLoginModal/index.ts b/src/components/amazonLoginModal/index.ts index 4d1a4dd..efea9ec 100644 --- a/src/components/amazonLoginModal/index.ts +++ b/src/components/amazonLoginModal/index.ts @@ -1,61 +1,61 @@ -import { BrowserWindow, remote } from 'electron'; - -import { currentAmazonRegion } from '~/amazonRegion'; -import type { AmazonAccount } from '~/models'; -import { settingsStore } from '~/store'; - -const { BrowserWindow: RemoteBrowserWindow } = remote; - -export default class AmazonLoginModal { - private modal: BrowserWindow; - private waitForSignIn: Promise ; - private resolvePromise!: (success: boolean) => void; - private region: AmazonAccount; - - constructor() { - this.region = currentAmazonRegion(); - - this.waitForSignIn = new Promise( - (resolve: (success: boolean) => void) => (this.resolvePromise = resolve) - ); - - this.modal = new RemoteBrowserWindow({ - parent: remote.getCurrentWindow(), - width: 450, - height: 730, - show: false, - }); - - // We can only change title after page is loaded since HTML page has its own title - this.modal.once('ready-to-show', () => { - this.modal.setTitle('Connect your Amazon account to Obsidian'); - this.modal.show(); - }); - - // If user is on the read.amazon.com url, we can safely assume they are logged in - this.modal.webContents.on('did-navigate', (_event, url) => { - if (url.startsWith(this.region.kindleReaderUrl)) { - this.modal.close(); - - settingsStore.actions.login(); - - this.resolvePromise(true); - } - }); - - this.modal.on('closed', () => { - this.resolvePromise(false); - }); - } - - async doLogin(): Promise { - try { - await this.modal.loadURL(this.region.notebookUrl); - } catch (error) { - // Swallow error. `loadUrl` is interrupted on successful - // login as we immediately redirect if user is logged in - } - - return this.waitForSignIn; - } -} +import { BrowserWindow, remote } from 'electron'; + +import { currentAmazonRegion } from '~/amazonRegion'; +import type { AmazonAccount } from '~/models'; +import { settingsStore } from '~/store'; + +const { BrowserWindow: RemoteBrowserWindow } = remote; + +export default class AmazonLoginModal { + private modal: BrowserWindow; + private waitForSignIn: Promise ; + private resolvePromise!: (success: boolean) => void; + private region: AmazonAccount; + + constructor() { + this.region = currentAmazonRegion(); + + this.waitForSignIn = new Promise( + (resolve: (success: boolean) => void) => (this.resolvePromise = resolve) + ); + + this.modal = new RemoteBrowserWindow({ + parent: remote.getCurrentWindow(), + width: 450, + height: 730, + show: false, + }); + + // We can only change title after page is loaded since HTML page has its own title + this.modal.once('ready-to-show', () => { + this.modal.setTitle('Connect your Amazon account to Obsidian'); + this.modal.show(); + }); + + // If user is on the read.amazon.com url, we can safely assume they are logged in + this.modal.webContents.on('did-navigate', (_event, url) => { + if (url.startsWith(this.region.kindleReaderUrl)) { + this.modal.close(); + + settingsStore.actions.login(); + + this.resolvePromise(true); + } + }); + + this.modal.on('closed', () => { + this.resolvePromise(false); + }); + } + + async doLogin(): Promise { + try { + await this.modal.loadURL(this.region.notebookUrl); + } catch (error) { + // Swallow error. `loadUrl` is interrupted on successful + // login as we immediately redirect if user is logged in + } + + return this.waitForSignIn; + } +} diff --git a/src/components/amazonLogoutModal/index.ts b/src/components/amazonLogoutModal/index.ts index b36417a..c07f547 100644 --- a/src/components/amazonLogoutModal/index.ts +++ b/src/components/amazonLogoutModal/index.ts @@ -1,39 +1,39 @@ -import { BrowserWindow, remote } from 'electron'; - -const { BrowserWindow: RemoteBrowserWindow } = remote; - -export default class AmazonLogoutModal { - private modal: BrowserWindow; - private url: string; - private waitForSignIn: Promise ; - private resolvePromise!: () => void; - - constructor(targetUrl: string) { - this.url = targetUrl; - - this.waitForSignIn = new Promise((resolve: () => void) => (this.resolvePromise = resolve)); - - this.modal = new RemoteBrowserWindow({ - parent: remote.getCurrentWindow(), - width: 450, - height: 730, - show: false, - }); - - this.modal.once('ready-to-show', () => { - this.modal.show(); - }); - - this.modal.webContents.on('did-navigate', (_event, url) => { - if (url.contains('signin')) { - this.modal.destroy(); - this.resolvePromise(); - } - }); - } - - async doLogout(): Promise { - await this.modal.loadURL(this.url); - return this.waitForSignIn; - } -} +import { BrowserWindow, remote } from 'electron'; + +const { BrowserWindow: RemoteBrowserWindow } = remote; + +export default class AmazonLogoutModal { + private modal: BrowserWindow; + private url: string; + private waitForSignIn: Promise ; + private resolvePromise!: () => void; + + constructor(targetUrl: string) { + this.url = targetUrl; + + this.waitForSignIn = new Promise((resolve: () => void) => (this.resolvePromise = resolve)); + + this.modal = new RemoteBrowserWindow({ + parent: remote.getCurrentWindow(), + width: 450, + height: 730, + show: false, + }); + + this.modal.once('ready-to-show', () => { + this.modal.show(); + }); + + this.modal.webContents.on('did-navigate', (_event, url) => { + if (url.contains('signin')) { + this.modal.destroy(); + this.resolvePromise(); + } + }); + } + + async doLogout(): Promise { + await this.modal.loadURL(this.url); + return this.waitForSignIn; + } +} diff --git a/src/components/syncModal/SyncModalContent.svelte b/src/components/syncModal/SyncModalContent.svelte index c978b45..416a788 100644 --- a/src/components/syncModal/SyncModalContent.svelte +++ b/src/components/syncModal/SyncModalContent.svelte @@ -1,29 +1,29 @@ - - -{#if $store.status === 'idle'} - { - store.update((p) => ({ ...p, status: 'choose-sync-method' })); - }} - /> -{:else if $store.status.startsWith('sync:')} - -{:else if $store.status === 'choose-sync-method'} - -{:else if $store.status === 'upgrade-warning'} - -{:else if $store.status === 'first-time'} - -{/if} + + +{#if $store.status === 'idle'} + { + store.update((p) => ({ ...p, status: 'choose-sync-method' })); + }} + /> +{:else if $store.status.startsWith('sync:')} + +{:else if $store.status === 'choose-sync-method'} + +{:else if $store.status === 'upgrade-warning'} + +{:else if $store.status === 'first-time'} + +{/if} diff --git a/src/components/syncModal/index.ts b/src/components/syncModal/index.ts index e4de8f8..e52c7b9 100644 --- a/src/components/syncModal/index.ts +++ b/src/components/syncModal/index.ts @@ -1,68 +1,68 @@ -import { App, Modal } from 'obsidian'; - -import type { SyncMode } from '~/models'; -import { settingsStore } from '~/store'; - -import { store, SyncModalState } from './store'; -import SyncModalContent from './SyncModalContent.svelte'; - -const SyncModalTitle: Record = { - 'upgrade-warning': 'Breaking change notice', - 'first-time': '', - idle: 'Your Kindle highlights', - 'sync:fetching-books': 'Syncing data...', - 'sync:login': 'Syncing data...', - 'sync:syncing': 'Syncing data...', - 'choose-sync-method': 'Choose a sync method...', -}; - -type SyncModalProps = { - onOnlineSync: () => void; - onMyClippingsSync: () => void; -}; - -export default class SyncModal extends Modal { - private modalContent: SyncModalContent; - - constructor(app: App, private props: SyncModalProps) { - super(app); - } - - public async show(): Promise { - // TODO: Remove after proliferation of v1.0.0 - const isLegacy = await settingsStore.isLegacy(); - const initialState: SyncModalState['status'] = isLegacy ? 'upgrade-warning' : 'idle'; - store.update((state) => ({ ...state, status: initialState })); - - this.modalContent = new SyncModalContent({ - target: this.contentEl, - props: { - onDone: () => { - this.close(); - }, - onClick: (mode: SyncMode) => { - if (mode === 'amazon') { - this.props.onOnlineSync(); - } else { - this.props.onMyClippingsSync(); - } - }, - onUpgrade: async () => { - await settingsStore.actions.upgradeStoreState(); - store.update((state) => ({ ...state, status: 'idle' })); - }, - }, - }); - - store.subscribe((state) => { - this.titleEl.innerText = SyncModalTitle[state.status]; - }); - - this.open(); - } - - onClose(): void { - super.onClose(); - this.modalContent.$destroy(); - } -} +import { App, Modal } from 'obsidian'; + +import type { SyncMode } from '~/models'; +import { settingsStore } from '~/store'; + +import { store, SyncModalState } from './store'; +import SyncModalContent from './SyncModalContent.svelte'; + +const SyncModalTitle: Record = { + 'upgrade-warning': 'Breaking change notice', + 'first-time': '', + idle: 'Your Kindle highlights', + 'sync:fetching-books': 'Syncing data...', + 'sync:login': 'Syncing data...', + 'sync:syncing': 'Syncing data...', + 'choose-sync-method': 'Choose a sync method...', +}; + +type SyncModalProps = { + onOnlineSync: () => void; + onMyClippingsSync: () => void; +}; + +export default class SyncModal extends Modal { + private modalContent: SyncModalContent; + + constructor(app: App, private props: SyncModalProps) { + super(app); + } + + public async show(): Promise { + // TODO: Remove after proliferation of v1.0.0 + const isLegacy = await settingsStore.isLegacy(); + const initialState: SyncModalState['status'] = isLegacy ? 'upgrade-warning' : 'idle'; + store.update((state) => ({ ...state, status: initialState })); + + this.modalContent = new SyncModalContent({ + target: this.contentEl, + props: { + onDone: () => { + this.close(); + }, + onClick: (mode: SyncMode) => { + if (mode === 'amazon') { + this.props.onOnlineSync(); + } else { + this.props.onMyClippingsSync(); + } + }, + onUpgrade: async () => { + await settingsStore.actions.upgradeStoreState(); + store.update((state) => ({ ...state, status: 'idle' })); + }, + }, + }); + + store.subscribe((state) => { + this.titleEl.innerText = SyncModalTitle[state.status]; + }); + + this.open(); + } + + onClose(): void { + super.onClose(); + this.modalContent.$destroy(); + } +} diff --git a/src/components/syncModal/store.ts b/src/components/syncModal/store.ts index 9f12e9d..009b9f9 100644 --- a/src/components/syncModal/store.ts +++ b/src/components/syncModal/store.ts @@ -1,108 +1,108 @@ -import { writable } from 'svelte/store'; - -import { ee } from '~/eventEmitter'; -import type { Book, KindleFile, SyncMode } from '~/models'; - -type Job = { - book: Book; -}; - -type JobError = { - book: Book; - reason: string; -}; - -export type SyncModalState = { - status: - | 'upgrade-warning' - | 'first-time' - | 'idle' - | 'choose-sync-method' - | 'sync:login' - | 'sync:fetching-books' - | 'sync:syncing'; - syncMode?: SyncMode; - currentJob?: { book: Book; index: number }; - syncError: string | undefined; - jobs?: Job[] | undefined; - erroredJobs: JobError[]; -}; - -const InitialState: SyncModalState = { - status: 'idle', - syncError: undefined, - erroredJobs: [], -}; - -const createSyncModalStore = () => { - const store = writable(InitialState); - - const syncing = (status: SyncModalState['status']) => { - store.update((state) => ({ ...state, status })); - }; - - ee.on('startLogin', () => syncing('sync:login')); - - ee.on('fetchingBooks', () => syncing('sync:fetching-books')); - - ee.on('fetchingBooksSuccess', (booksToSync: Book[]) => { - store.update((state) => ({ - ...state, - status: 'sync:fetching-books', - jobs: booksToSync.map((book) => ({ book, status: 'idle' })), - })); - }); - - ee.on('syncSessionStart', (mode: SyncMode) => { - store.set({ ...InitialState, status: 'sync:syncing', syncMode: mode }); - }); - - ee.on('syncBook', (book: Book, index: number) => { - store.update((state) => ({ - ...state, - status: 'sync:syncing', - currentJob: { book, index }, - })); - }); - - ee.on('resyncBook', (file: KindleFile) => { - store.set({ - ...InitialState, - status: 'sync:syncing', - currentJob: { book: file.book, index: 0 }, - }); - }); - - ee.on('syncSessionSuccess', () => { - store.set(InitialState); - }); - - ee.on('resyncComplete', () => syncing('idle')); - - ee.on('syncSessionFailure', (message: string) => { - store.update((state) => ({ - ...state, - status: 'idle', - syncError: message, - })); - }); - - ee.on('resyncFailure', (file: KindleFile, message: string) => { - store.update((state) => ({ - ...state, - status: 'idle', - erroredJobs: [{ book: file.book, reason: message }], - })); - }); - - ee.on('syncBookFailure', (book: Book, message: string) => { - store.update((state) => ({ - ...state, - erroredJobs: [...state.erroredJobs, { book, reason: message }], - })); - }); - - return store; -}; - -export const store = createSyncModalStore(); +import { writable } from 'svelte/store'; + +import { ee } from '~/eventEmitter'; +import type { Book, KindleFile, SyncMode } from '~/models'; + +type Job = { + book: Book; +}; + +type JobError = { + book: Book; + reason: string; +}; + +export type SyncModalState = { + status: + | 'upgrade-warning' + | 'first-time' + | 'idle' + | 'choose-sync-method' + | 'sync:login' + | 'sync:fetching-books' + | 'sync:syncing'; + syncMode?: SyncMode; + currentJob?: { book: Book; index: number }; + syncError: string | undefined; + jobs?: Job[] | undefined; + erroredJobs: JobError[]; +}; + +const InitialState: SyncModalState = { + status: 'idle', + syncError: undefined, + erroredJobs: [], +}; + +const createSyncModalStore = () => { + const store = writable(InitialState); + + const syncing = (status: SyncModalState['status']) => { + store.update((state) => ({ ...state, status })); + }; + + ee.on('startLogin', () => syncing('sync:login')); + + ee.on('fetchingBooks', () => syncing('sync:fetching-books')); + + ee.on('fetchingBooksSuccess', (booksToSync: Book[]) => { + store.update((state) => ({ + ...state, + status: 'sync:fetching-books', + jobs: booksToSync.map((book) => ({ book, status: 'idle' })), + })); + }); + + ee.on('syncSessionStart', (mode: SyncMode) => { + store.set({ ...InitialState, status: 'sync:syncing', syncMode: mode }); + }); + + ee.on('syncBook', (book: Book, index: number) => { + store.update((state) => ({ + ...state, + status: 'sync:syncing', + currentJob: { book, index }, + })); + }); + + ee.on('resyncBook', (file: KindleFile) => { + store.set({ + ...InitialState, + status: 'sync:syncing', + currentJob: { book: file.book, index: 0 }, + }); + }); + + ee.on('syncSessionSuccess', () => { + store.set(InitialState); + }); + + ee.on('resyncComplete', () => syncing('idle')); + + ee.on('syncSessionFailure', (message: string) => { + store.update((state) => ({ + ...state, + status: 'idle', + syncError: message, + })); + }); + + ee.on('resyncFailure', (file: KindleFile, message: string) => { + store.update((state) => ({ + ...state, + status: 'idle', + erroredJobs: [{ book: file.book, reason: message }], + })); + }); + + ee.on('syncBookFailure', (book: Book, message: string) => { + store.update((state) => ({ + ...state, + erroredJobs: [...state.erroredJobs, { book, reason: message }], + })); + }); + + return store; +}; + +export const store = createSyncModalStore(); diff --git a/src/components/syncModal/views/FirstTimeView.svelte b/src/components/syncModal/views/FirstTimeView.svelte index ce80ca4..fb91fe8 100644 --- a/src/components/syncModal/views/FirstTimeView.svelte +++ b/src/components/syncModal/views/FirstTimeView.svelte @@ -1,49 +1,49 @@ - - - -- - + + +--Let's Get Started
-- Liberate your Kindle highlights and [[connect]] them to your second brain in Obsidian -
---- ++ + diff --git a/src/components/syncModal/views/IdleView.svelte b/src/components/syncModal/views/IdleView.svelte index ee51320..5cc06d5 100644 --- a/src/components/syncModal/views/IdleView.svelte +++ b/src/components/syncModal/views/IdleView.svelte @@ -1,10 +1,10 @@ - - -++Let's Get Started
++ Liberate your Kindle highlights and [[connect]] them to your second brain in Obsidian +
++++ - - -+ + ++ + +diff --git a/src/components/syncModal/views/SyncButtons.svelte b/src/components/syncModal/views/SyncButtons.svelte index 1072209..af1c988 100644 --- a/src/components/syncModal/views/SyncButtons.svelte +++ b/src/components/syncModal/views/SyncButtons.svelte @@ -1,88 +1,88 @@ - - - - -- -- - + + + + ++ ++ + diff --git a/src/components/syncModal/views/SyncStats.svelte b/src/components/syncModal/views/SyncStats.svelte index 8d6d22b..27782bf 100644 --- a/src/components/syncModal/views/SyncStats.svelte +++ b/src/components/syncModal/views/SyncStats.svelte @@ -1,58 +1,58 @@ - - --- - + + +----Books-{numberWithCommas($fileStore.fileCount)}---Highlights-{numberWithCommas($fileStore.highlightCount)}-- Last sync {moment($settingsStore.lastSyncDate).fromNow()} --++ + diff --git a/src/components/syncModal/views/SyncingView.svelte b/src/components/syncModal/views/SyncingView.svelte index 6951a51..32644ed 100644 --- a/src/components/syncModal/views/SyncingView.svelte +++ b/src/components/syncModal/views/SyncingView.svelte @@ -1,105 +1,105 @@ - - -{#if $store.erroredJobs.length > 0} -++++Books+{numberWithCommas($fileStore.fileCount)}+++Highlights+{numberWithCommas($fileStore.highlightCount)}++ Last sync {moment($settingsStore.lastSyncDate).fromNow()} ++- {`${$store.erroredJobs.length} books(s) could not be synced because of errors`} --- --{:else} --- -- - - {#if $store.currentJob} - - {$store.currentJob.index + 1} - - / {total} --- Syncing - - {shortenTitle($store.currentJob.book.title)} - -- {:else} - - {/if} -- --{/if} - - + + +{#if $store.erroredJobs.length > 0} ++ {`${$store.erroredJobs.length} books(s) could not be synced because of errors`} +++ ++{:else} +++ ++ + + {#if $store.currentJob} + + {$store.currentJob.index + 1} + + / {total} +++ Syncing + + {shortenTitle($store.currentJob.book.title)} + ++ {:else} + + {/if} ++ ++{/if} + + diff --git a/src/components/syncModal/views/UpgradeView.svelte b/src/components/syncModal/views/UpgradeView.svelte index 84253af..d970f50 100644 --- a/src/components/syncModal/views/UpgradeView.svelte +++ b/src/components/syncModal/views/UpgradeView.svelte @@ -1,56 +1,56 @@ - - --- - + + +- ----- This new version of the Kindle plugin introduces the highly requested feature of - resyncing. The plugin will detect any new annotations that you've made on your Kindle and - intelligently insert it in the right place in your Obsidian highlight file. -
-- Implementation of this feature required a breaking change in how the plugin writes Kindle highlights — (a) use of frontmatter to store sync state - information and (b) block references for every synced highlight. -
-- You will need to re-run sync to download all your Kindle annotations which will result in double ups – You will manually need to manage this to remove them. This is a one-time process. Future - updates for the plugin are not planned to introduce anymore breaking changes. -
-- --++ + diff --git a/src/custom.d.ts b/src/custom.d.ts index 5933caf..83e52ac 100644 --- a/src/custom.d.ts +++ b/src/custom.d.ts @@ -1,45 +1,45 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - -declare module '*.njk' { - const content: string; - export default content; -} - -declare module '*.html' { - const content: any; - export default content; -} - -declare module '*.svg' { - const content: any; - export default content; -} - -declare module 'svelte-loading-spinners' { - import { SvelteComponent } from 'svelte'; - - export class Jumper extends SvelteComponent { - color: string; - size: string; - duration: string; - } -} - -declare module 'fletcher' { - const fletcher16: (buffer: Buffer) => number; - export default fletcher16; -} - -declare module '*.json' { - const file: any; - export default file; -} - -declare module 'nunjucks-date-filter' { - interface NunjucksDateFilter { - (date: Date, format: string): void; - setDefaultFormat: (format: string) => void; - } - const module: NunjucksDateFilter; - export default module; -} +/* eslint-disable @typescript-eslint/no-explicit-any */ + +declare module '*.njk' { + const content: string; + export default content; +} + +declare module '*.html' { + const content: any; + export default content; +} + +declare module '*.svg' { + const content: any; + export default content; +} + +declare module 'svelte-loading-spinners' { + import { SvelteComponent } from 'svelte'; + + export class Jumper extends SvelteComponent { + color: string; + size: string; + duration: string; + } +} + +declare module 'fletcher' { + const fletcher16: (buffer: Buffer) => number; + export = fletcher16; +} + +declare module '*.json' { + const file: any; + export default file; +} + +declare module 'nunjucks-date-filter' { + interface NunjucksDateFilter { + (date: Date, format: string): void; + setDefaultFormat: (format: string) => void; + } + const module: NunjucksDateFilter; + export default module; +} diff --git a/src/eventEmitter.ts b/src/eventEmitter.ts index 085100d..647719d 100644 --- a/src/eventEmitter.ts +++ b/src/eventEmitter.ts @@ -1,26 +1,26 @@ -import EventEmitter from 'events'; -import type TypedEmitter from 'typed-emitter'; - -import type { Book, Highlight, KindleFile, SyncMode } from '~/models'; - -interface MessageEvents { - obsidianReady: () => void; - startLogin: () => void; - loginComplete: (success: boolean) => void; - startLogout: () => void; - logoutSuccess: () => void; - logoutFailure: () => void; - fetchingBooks: () => void; - fetchingBooksSuccess: (booksToSync: Book[], remoteBooks: Book[]) => void; - syncSessionStart: (mode: SyncMode) => void; - syncSessionSuccess: () => void; - syncSessionFailure: (message: string) => void; - syncBook: (book: Book, index: number) => void; - syncBookSuccess: (book: Book, highlights: Highlight[]) => void; - syncBookFailure: (book: Book, message: string) => void; - resyncBook: (file: KindleFile) => void; - resyncComplete: (file: KindleFile, diffCount: number) => void; - resyncFailure: (file: KindleFile, message: string) => void; -} - -export const ee = new EventEmitter() as TypedEmitter+ +++++ This new version of the Kindle plugin introduces the highly requested feature of + resyncing. The plugin will detect any new annotations that you've made on your Kindle and + intelligently insert it in the right place in your Obsidian highlight file. +
++ Implementation of this feature required a breaking change in how the plugin writes Kindle highlights — (a) use of frontmatter to store sync state + information and (b) block references for every synced highlight. +
++ You will need to re-run sync to download all your Kindle annotations which will result in double ups – You will manually need to manage this to remove them. This is a one-time process. Future + updates for the plugin are not planned to introduce anymore breaking changes. +
++ ++; +import EventEmitter from 'events'; +import type TypedEmitter from 'typed-emitter'; + +import type { Book, Highlight, KindleFile, SyncMode } from '~/models'; + +interface MessageEvents { + obsidianReady: () => void; + startLogin: () => void; + loginComplete: (success: boolean) => void; + startLogout: () => void; + logoutSuccess: () => void; + logoutFailure: () => void; + fetchingBooks: () => void; + fetchingBooksSuccess: (booksToSync: Book[], remoteBooks: Book[]) => void; + syncSessionStart: (mode: SyncMode) => void; + syncSessionSuccess: () => void; + syncSessionFailure: (message: string) => void; + syncBook: (book: Book, index: number) => void; + syncBookSuccess: (book: Book, highlights: Highlight[]) => void; + syncBookFailure: (book: Book, message: string) => void; + resyncBook: (file: KindleFile) => void; + resyncComplete: (file: KindleFile, diffCount: number) => void; + resyncFailure: (file: KindleFile, message: string) => void; +} + +export const ee = new EventEmitter() as TypedEmitter ; diff --git a/src/fileManager/index.ts b/src/fileManager/index.ts index c95e8ab..28af49a 100644 --- a/src/fileManager/index.ts +++ b/src/fileManager/index.ts @@ -1,109 +1,109 @@ -import { MetadataCache, normalizePath, TAbstractFile, TFile, TFolder, Vault } from 'obsidian'; - -import type { Book, KindleFile, KindleFrontmatter } from '~/models'; -import { mergeFrontmatter } from '~/utils'; - -import { bookFilePath, bookToFrontMatter, frontMatterToBook } from './mappers'; - -const SyncingStateKey = 'kindle-sync'; - -export default class FileManager { - constructor(private vault: Vault, private metadataCache: MetadataCache) {} - - public async readFile(file: KindleFile): Promise { - return await this.vault.cachedRead(file.file); - } - - public getKindleFile(book: Book): KindleFile | undefined { - const allSyncedFiles = this.getKindleFiles(); - - const kindleFile = allSyncedFiles.find((file) => file.frontmatter.bookId === book.id); - - return kindleFile == null ? undefined : { ...kindleFile, book }; - } - - public mapToKindleFile(fileOrFolder: TAbstractFile): KindleFile | undefined { - if (fileOrFolder instanceof TFolder) { - return undefined; - } - - const file = fileOrFolder as TFile; - - const fileCache = this.metadataCache.getFileCache(file); - - // File cache can be undefined if this file was just created and not yet cached by Obsidian - const kindleFrontmatter = fileCache?.frontmatter?.[SyncingStateKey] as KindleFrontmatter; - - if (kindleFrontmatter == null) { - return undefined; - } - - const book = frontMatterToBook(kindleFrontmatter); - - return { file, frontmatter: kindleFrontmatter, book }; - } - - public getKindleFiles(): KindleFile[] { - return this.vault - .getMarkdownFiles() - .map((file) => this.mapToKindleFile(file)) - .filter((file) => file != null); - } - - public async createFile( - book: Book, - content: string, - highlightsCount: number - ): Promise { - const filePath = this.generateUniqueFilePath(book); - const frontmatterContent = this.generateBookContent(book, content, highlightsCount); - - try { - await this.vault.create(filePath, frontmatterContent); - } catch (error) { - console.error(`Error writing new file (path="${filePath})"`); - throw error; - } - } - - public async updateFile( - kindleFile: KindleFile, - remoteBook: Book, - content: string, - highlightsCount: number - ): Promise { - const frontmatterContent = this.generateBookContent(remoteBook, content, highlightsCount); - - try { - await this.vault.modify(kindleFile.file, frontmatterContent); - } catch (error) { - console.error(`Error modifying e file (path="${kindleFile.file.path})"`); - throw error; - } - } - - /** - * Generate book content by combining both book (a) book markdown and - * (b) rendered book highlights - */ - private generateBookContent(book: Book, content: string, highlightsCount: number): string { - return mergeFrontmatter(content, { - [SyncingStateKey]: bookToFrontMatter(book, highlightsCount), - }); - } - - private generateUniqueFilePath(book: Book): string { - const filePath = bookFilePath(book); - - const isDuplicate = this.vault - .getMarkdownFiles() - .some((v) => v.path === normalizePath(filePath)); - - if (isDuplicate) { - const currentTime = new Date().getTime().toString(); - return filePath.replace('.md', `-${currentTime}.md`); - } - - return filePath; - } -} +import { MetadataCache, normalizePath, TAbstractFile, TFile, TFolder, Vault } from 'obsidian'; + +import type { Book, KindleFile, KindleFrontmatter } from '~/models'; +import { mergeFrontmatter } from '~/utils'; + +import { bookFilePath, bookToFrontMatter, frontMatterToBook } from './mappers'; + +const SyncingStateKey = 'kindle-sync'; + +export default class FileManager { + constructor(private vault: Vault, private metadataCache: MetadataCache) {} + + public async readFile(file: KindleFile): Promise { + return await this.vault.cachedRead(file.file); + } + + public getKindleFile(book: Book): KindleFile | undefined { + const allSyncedFiles = this.getKindleFiles(); + + const kindleFile = allSyncedFiles.find((file) => file.frontmatter.bookId === book.id); + + return kindleFile == null ? undefined : { ...kindleFile, book }; + } + + public mapToKindleFile(fileOrFolder: TAbstractFile): KindleFile | undefined { + if (fileOrFolder instanceof TFolder) { + return undefined; + } + + const file = fileOrFolder as TFile; + + const fileCache = this.metadataCache.getFileCache(file); + + // File cache can be undefined if this file was just created and not yet cached by Obsidian + const kindleFrontmatter = fileCache?.frontmatter?.[SyncingStateKey] as KindleFrontmatter; + + if (kindleFrontmatter == null) { + return undefined; + } + + const book = frontMatterToBook(kindleFrontmatter); + + return { file, frontmatter: kindleFrontmatter, book }; + } + + public getKindleFiles(): KindleFile[] { + return this.vault + .getMarkdownFiles() + .map((file) => this.mapToKindleFile(file)) + .filter((file) => file != null); + } + + public async createFile( + book: Book, + content: string, + highlightsCount: number + ): Promise { + const filePath = this.generateUniqueFilePath(book); + const frontmatterContent = this.generateBookContent(book, content, highlightsCount); + + try { + await this.vault.create(filePath, frontmatterContent); + } catch (error) { + console.error(`Error writing new file (path="${filePath})"`); + throw error; + } + } + + public async updateFile( + kindleFile: KindleFile, + remoteBook: Book, + content: string, + highlightsCount: number + ): Promise { + const frontmatterContent = this.generateBookContent(remoteBook, content, highlightsCount); + + try { + await this.vault.modify(kindleFile.file, frontmatterContent); + } catch (error) { + console.error(`Error modifying e file (path="${kindleFile.file.path})"`); + throw error; + } + } + + /** + * Generate book content by combining both book (a) book markdown and + * (b) rendered book highlights + */ + private generateBookContent(book: Book, content: string, highlightsCount: number): string { + return mergeFrontmatter(content, { + [SyncingStateKey]: bookToFrontMatter(book, highlightsCount), + }); + } + + private generateUniqueFilePath(book: Book): string { + const filePath = bookFilePath(book); + + const isDuplicate = this.vault + .getMarkdownFiles() + .some((v) => v.path === normalizePath(filePath)); + + if (isDuplicate) { + const currentTime = new Date().getTime().toString(); + return filePath.replace('.md', `-${currentTime}.md`); + } + + return filePath; + } +} diff --git a/src/fileManager/mappers.ts b/src/fileManager/mappers.ts index a85aab0..421033e 100644 --- a/src/fileManager/mappers.ts +++ b/src/fileManager/mappers.ts @@ -1,44 +1,44 @@ -import moment from 'moment'; -import path from 'path'; -import { get } from 'svelte/store'; - -import type { Book, KindleFrontmatter } from '~/models'; -import { getRenderers } from '~/rendering'; -import { settingsStore } from '~/store'; - -/** - * Returns a file path for a given book relative to the current Obsidian - * vault directory. - */ -export const bookFilePath = (book: Book): string => { - const fileName = getRenderers().fileNameRenderer.render(book); - return path.join(get(settingsStore).highlightsFolder, fileName); -}; - -export const bookToFrontMatter = (book: Book, highlightsCount: number): KindleFrontmatter => { - return { - bookId: book.id, - title: book.title, - author: book.author, - asin: book.asin, - lastAnnotatedDate: book.lastAnnotatedDate - ? moment(book.lastAnnotatedDate).format('YYYY-MM-DD') - : null, - bookImageUrl: book.imageUrl, - highlightsCount, - }; -}; - -export const frontMatterToBook = (frontmatter: KindleFrontmatter): Book => { - const formats = ['MMM DD, YYYY', 'YYYY-MM-DD']; - return { - id: frontmatter.bookId, - title: frontmatter.title, - author: frontmatter.author, - asin: frontmatter.asin, - lastAnnotatedDate: frontmatter.lastAnnotatedDate - ? moment(frontmatter.lastAnnotatedDate, formats).toDate() - : null, - imageUrl: frontmatter.bookImageUrl, - }; -}; +import moment from 'moment'; +import path from 'path'; +import { get } from 'svelte/store'; + +import type { Book, KindleFrontmatter } from '~/models'; +import { getRenderers } from '~/rendering'; +import { settingsStore } from '~/store'; + +/** + * Returns a file path for a given book relative to the current Obsidian + * vault directory. + */ +export const bookFilePath = (book: Book): string => { + const fileName = getRenderers().fileNameRenderer.render(book); + return path.join(get(settingsStore).highlightsFolder, fileName); +}; + +export const bookToFrontMatter = (book: Book, highlightsCount: number): KindleFrontmatter => { + return { + bookId: book.id, + title: book.title, + author: book.author, + asin: book.asin, + lastAnnotatedDate: book.lastAnnotatedDate + ? moment(book.lastAnnotatedDate).format('YYYY-MM-DD') + : null, + bookImageUrl: book.imageUrl, + highlightsCount, + }; +}; + +export const frontMatterToBook = (frontmatter: KindleFrontmatter): Book => { + const formats = ['MMM DD, YYYY', 'YYYY-MM-DD']; + return { + id: frontmatter.bookId, + title: frontmatter.title, + author: frontmatter.author, + asin: frontmatter.asin, + lastAnnotatedDate: frontmatter.lastAnnotatedDate + ? moment(frontmatter.lastAnnotatedDate, formats).toDate() + : null, + imageUrl: frontmatter.bookImageUrl, + }; +}; diff --git a/src/index.ts b/src/index.ts index 287aa94..93dea60 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,93 +1,93 @@ -import { addIcon, Plugin } from 'obsidian'; -import { get } from 'svelte/store'; - -import kindleIcon from '~/assets/kindleIcon.svg'; -import SyncModal from '~/components/syncModal'; -import { ee } from '~/eventEmitter'; -import FileManager from '~/fileManager'; -import { registerNotifications } from '~/notifications'; -import { SettingsTab } from '~/settings'; -import { initializeStores, settingsStore } from '~/store'; -import { SyncAmazon, SyncClippings, SyncManager } from '~/sync'; - -addIcon('kindle', kindleIcon); - -export default class KindlePlugin extends Plugin { - private fileManager!: FileManager; - private syncAmazon!: SyncAmazon; - private syncClippings!: SyncClippings; - - public async onload(): Promise { - console.log('Kindle Highlights plugin: loading plugin', new Date().toLocaleString()); - - this.fileManager = new FileManager(this.app.vault, this.app.metadataCache); - const syncManager = new SyncManager(this.fileManager); - - await initializeStores(this, this.fileManager); - - this.syncAmazon = new SyncAmazon(syncManager); - this.syncClippings = new SyncClippings(syncManager); - - this.addRibbonIcon('kindle', 'Sync your Kindle highlights', async () => { - await this.showSyncModal(); - }); - - this.addCommand({ - id: 'kindle-sync', - name: 'Sync highlights', - callback: async () => { - await this.showSyncModal(); - }, - }); - - this.addSettingTab(new SettingsTab(this.app, this, this.fileManager)); - - registerNotifications(); - this.registerEvents(); - - if (get(settingsStore).syncOnBoot) { - await this.startAmazonSync(); - } - } - - private registerEvents(): void { - this.registerEvent( - this.app.workspace.on('file-menu', (menu, file) => { - const kindleFile = this.fileManager.mapToKindleFile(file); - if (kindleFile == null) { - return; - } - - menu.addItem((item) => { - item - .setTitle('Resync Kindle highlights in file') - .setIcon('kindle') - .setDisabled(kindleFile.book.asin == null) - .onClick(async () => { - await this.syncAmazon.resync(kindleFile); - }); - }); - }) - ); - - this.app.workspace.onLayoutReady(() => { - ee.emit('obsidianReady'); - }); - } - - private async showSyncModal(): Promise { - await new SyncModal(this.app, { - onOnlineSync: () => this.startAmazonSync(), - onMyClippingsSync: () => this.syncClippings.startSync(), - }).show(); - } - - private async startAmazonSync(): Promise { - await this.syncAmazon.startSync(); - } - - public onunload(): void { - ee.removeAllListeners(); - console.log('Kindle Highlights plugin: unloading plugin', new Date().toLocaleString()); - } -} +import { addIcon, Plugin } from 'obsidian'; +import { get } from 'svelte/store'; + +import kindleIcon from '~/assets/kindleIcon.svg'; +import SyncModal from '~/components/syncModal'; +import { ee } from '~/eventEmitter'; +import FileManager from '~/fileManager'; +import { registerNotifications } from '~/notifications'; +import { SettingsTab } from '~/settings'; +import { initializeStores, settingsStore } from '~/store'; +import { SyncAmazon, SyncClippings, SyncManager } from '~/sync'; + +addIcon('kindle', kindleIcon); + +export default class KindlePlugin extends Plugin { + private fileManager!: FileManager; + private syncAmazon!: SyncAmazon; + private syncClippings!: SyncClippings; + + public async onload(): Promise { + console.log('Kindle Highlights plugin: loading plugin', new Date().toLocaleString()); + + this.fileManager = new FileManager(this.app.vault, this.app.metadataCache); + const syncManager = new SyncManager(this.fileManager); + + await initializeStores(this, this.fileManager); + + this.syncAmazon = new SyncAmazon(syncManager); + this.syncClippings = new SyncClippings(syncManager); + + this.addRibbonIcon('kindle', 'Sync your Kindle highlights', async () => { + await this.showSyncModal(); + }); + + this.addCommand({ + id: 'kindle-sync', + name: 'Sync highlights', + callback: async () => { + await this.showSyncModal(); + }, + }); + + this.addSettingTab(new SettingsTab(this.app, this, this.fileManager)); + + registerNotifications(); + this.registerEvents(); + + if (get(settingsStore).syncOnBoot) { + await this.startAmazonSync(); + } + } + + private registerEvents(): void { + this.registerEvent( + this.app.workspace.on('file-menu', (menu, file) => { + const kindleFile = this.fileManager.mapToKindleFile(file); + if (kindleFile == null) { + return; + } + + menu.addItem((item) => { + item + .setTitle('Resync Kindle highlights in file') + .setIcon('kindle') + .setDisabled(kindleFile.book.asin == null) + .onClick(async () => { + await this.syncAmazon.resync(kindleFile); + }); + }); + }) + ); + + this.app.workspace.onLayoutReady(() => { + ee.emit('obsidianReady'); + }); + } + + private async showSyncModal(): Promise { + await new SyncModal(this.app, { + onOnlineSync: () => this.startAmazonSync(), + onMyClippingsSync: () => this.syncClippings.startSync(), + }).show(); + } + + private async startAmazonSync(): Promise { + await this.syncAmazon.startSync(); + } + + public onunload(): void { + ee.removeAllListeners(); + console.log('Kindle Highlights plugin: unloading plugin', new Date().toLocaleString()); + } +} diff --git a/src/models.ts b/src/models.ts index 9f98f67..068c9ba 100644 --- a/src/models.ts +++ b/src/models.ts @@ -1,70 +1,70 @@ -import type { TFile } from 'obsidian'; - -export type Book = { - id: string; - title: string; - author: string; - asin?: string; - url?: string; - imageUrl?: string; - lastAnnotatedDate?: Date; -}; - -export type Highlight = { - id: string; - text: string; - location?: string; - page?: string; - note?: string; - color?: 'pink' | 'blue' | 'yellow' | 'orange'; - createdDate?: Date; -}; - -export type BookHighlight = { - book: Book; - highlights: Highlight[]; - metadata?: BookMetadata; -}; - -export type BookMetadata = { - isbn?: string; - pages?: string; - publicationDate?: string; - publisher?: string; - authorUrl?: string; -}; - -export type SyncMode = 'amazon' | 'my-clippings'; - -export type AmazonAccountRegion = - | 'global' - | 'india' - | 'japan' - | 'spain' - | 'germany' - | 'italy' - | 'UK' - | 'france'; - -export type AmazonAccount = { - name: string; - hostname: string; - kindleReaderUrl: string; - notebookUrl: string; -}; - -export type KindleFrontmatter = { - bookId: string; - title: string; - author: string; - asin: string; - lastAnnotatedDate?: string; // Not set for My Clipping annotations - bookImageUrl: string; - highlightsCount: number; -}; - -export type KindleFile = { - file: TFile; - frontmatter: KindleFrontmatter; - book?: Book; -}; +import type { TFile } from 'obsidian'; + +export type Book = { + id: string; + title: string; + author: string; + asin?: string; + url?: string; + imageUrl?: string; + lastAnnotatedDate?: Date; +}; + +export type Highlight = { + id: string; + text: string; + location?: string; + page?: string; + note?: string; + color?: 'pink' | 'blue' | 'yellow' | 'orange'; + createdDate?: Date; +}; + +export type BookHighlight = { + book: Book; + highlights: Highlight[]; + metadata?: BookMetadata; +}; + +export type BookMetadata = { + isbn?: string; + pages?: string; + publicationDate?: string; + publisher?: string; + authorUrl?: string; +}; + +export type SyncMode = 'amazon' | 'my-clippings'; + +export type AmazonAccountRegion = + | 'global' + | 'india' + | 'japan' + | 'spain' + | 'germany' + | 'italy' + | 'UK' + | 'france'; + +export type AmazonAccount = { + name: string; + hostname: string; + kindleReaderUrl: string; + notebookUrl: string; +}; + +export type KindleFrontmatter = { + bookId: string; + title: string; + author: string; + asin: string; + lastAnnotatedDate?: string; // Not set for My Clipping annotations + bookImageUrl: string; + highlightsCount: number; +}; + +export type KindleFile = { + file: TFile; + frontmatter: KindleFrontmatter; + book?: Book; +}; diff --git a/src/notifications.ts b/src/notifications.ts index f31b3a7..43d813e 100644 --- a/src/notifications.ts +++ b/src/notifications.ts @@ -1,43 +1,43 @@ -import { Notice } from 'obsidian'; - -import { ee } from '~/eventEmitter'; -import type { KindleFile } from '~/models'; -import { shortenTitle } from '~/utils'; - -export const registerNotifications = (): void => { - ee.on('resyncBook', (kindleFile) => { - new Notice(`Resyncing "${shortenTitle(kindleFile.book.title)}" book highlights`); - }); - - ee.on('resyncComplete', (_kindleFile, diffCount) => { - let message = 'No new highlights to resync'; - - if (diffCount === 1) { - message = '1 new highlight imported'; - } else if (diffCount > 1) { - message = `${diffCount} highlights imported`; - } - - new Notice(message); - }); - - ee.on('syncSessionFailure', (message: string) => { - new Notice(message); - }); - - ee.on('resyncFailure', (_file: KindleFile, message: string) => { - new Notice(message); - }); - - ee.on('startLogout', () => { - new Notice('Signing out...'); - }); - - ee.on('logoutSuccess', () => { - new Notice('Signed out'); - }); - - ee.on('logoutFailure', () => { - new Notice('Error. Could not sign out'); - }); -}; +import { Notice } from 'obsidian'; + +import { ee } from '~/eventEmitter'; +import type { KindleFile } from '~/models'; +import { shortenTitle } from '~/utils'; + +export const registerNotifications = (): void => { + ee.on('resyncBook', (kindleFile) => { + new Notice(`Resyncing "${shortenTitle(kindleFile.book.title)}" book highlights`); + }); + + ee.on('resyncComplete', (_kindleFile, diffCount) => { + let message = 'No new highlights to resync'; + + if (diffCount === 1) { + message = '1 new highlight imported'; + } else if (diffCount > 1) { + message = `${diffCount} highlights imported`; + } + + new Notice(message); + }); + + ee.on('syncSessionFailure', (message: string) => { + new Notice(message); + }); + + ee.on('resyncFailure', (_file: KindleFile, message: string) => { + new Notice(message); + }); + + ee.on('startLogout', () => { + new Notice('Signing out...'); + }); + + ee.on('logoutSuccess', () => { + new Notice('Signed out'); + }); + + ee.on('logoutFailure', () => { + new Notice('Error. Could not sign out'); + }); +}; diff --git a/src/rendering/index.ts b/src/rendering/index.ts index 1b609b6..b9f24da 100644 --- a/src/rendering/index.ts +++ b/src/rendering/index.ts @@ -1,25 +1,25 @@ -import { get } from 'svelte/store'; - -import { settingsStore } from '~/store'; - -import bookTemplate from './templates/bookTemplate.njk'; -import defaultHighlightTemplate from './templates/defaultHighlightTemplate.njk'; -import { FileNameRenderer, FileRenderer, HighlightRenderer } from './renderer'; - -export const DefaultFileNameTemplate = '{{authorsLastNames}}-{{title}}'; -export const DefaultFileTemplate = bookTemplate; -export const DefaultHighlightTemplate = defaultHighlightTemplate; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export const getRenderers = () => { - const { fileNameTemplate, fileTemplate, highlightTemplate } = get(settingsStore); - const userFileNameTemplate = fileNameTemplate || DefaultFileNameTemplate; - const userFileTemplate = fileTemplate || DefaultFileTemplate; - const userHighlighTemplate = highlightTemplate || DefaultHighlightTemplate; - - return { - fileNameRenderer: new FileNameRenderer(userFileNameTemplate), - fileRenderer: new FileRenderer(userFileTemplate, userHighlighTemplate), - highlightRenderer: new HighlightRenderer(userHighlighTemplate), - }; -}; +import { get } from 'svelte/store'; + +import { settingsStore } from '~/store'; + +import bookTemplate from './templates/bookTemplate.njk'; +import defaultHighlightTemplate from './templates/defaultHighlightTemplate.njk'; +import { FileNameRenderer, FileRenderer, HighlightRenderer } from './renderer'; + +export const DefaultFileNameTemplate = '{{authorsLastNames}}-{{title}}'; +export const DefaultFileTemplate = bookTemplate; +export const DefaultHighlightTemplate = defaultHighlightTemplate; + +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export const getRenderers = () => { + const { fileNameTemplate, fileTemplate, highlightTemplate } = get(settingsStore); + const userFileNameTemplate = fileNameTemplate || DefaultFileNameTemplate; + const userFileTemplate = fileTemplate || DefaultFileTemplate; + const userHighlighTemplate = highlightTemplate || DefaultHighlightTemplate; + + return { + fileNameRenderer: new FileNameRenderer(userFileNameTemplate), + fileRenderer: new FileRenderer(userFileTemplate, userHighlighTemplate), + highlightRenderer: new HighlightRenderer(userHighlighTemplate), + }; +}; diff --git a/src/rendering/nunjucks.extensions.ts b/src/rendering/nunjucks.extensions.ts index 3ed33fb..7ce02db 100644 --- a/src/rendering/nunjucks.extensions.ts +++ b/src/rendering/nunjucks.extensions.ts @@ -1,131 +1,131 @@ -/* eslint-disable @typescript-eslint/restrict-plus-operands */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unsafe-call */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import nunjucks from 'nunjucks'; - -import { sb } from '~/utils'; - -import { HighlightIdBlockRefPrefix } from './renderer'; - -type SubClass = { - children?: SubClassValue[]; - colno: number; - lineno: number; -}; - -type SubClassValue = { - args?: SubClass; - name?: SubClassValue; - colno: number; - lineno: number; - value: string; -}; - -type ParsedSignature = { - children: SubClass[]; -}; - -type Context = { - ctx: Record ; -}; - -function TrimAllEmptyLinesExtension(): void { - this.tags = ['trim']; - - this.parse = function (parser, nodes) { - const tok = parser.nextToken(); // Get the tag token - - // Parse the args and move after the block end. - const args: ParsedSignature = parser.parseSignature(null, true); - parser.advanceAfterBlockEnd(tok.value); - - // Parse the body - const body: ParsedSignature = parser.parseUntilBlocks('trim', 'endtrim'); - parser.advanceAfterBlockEnd(); - - // Actually do work on block body and arguments - return new nodes.CallExtension(this, 'run', args, [body]); - }; - - this.run = function (_context, bodyCallback) { - const rawCode: string = bodyCallback(); - const rawCodeNoLines = rawCode.replace(/(^[ \t]*\n)/gm, '').trim(); - return new nunjucks.runtime.SafeString(rawCodeNoLines); - }; -} - -/** - * Recursively iterates through AST of a user template and find the value - * of every node. This is made complex by the fact that some AST nodes - * do not have values (e.g. if statement, nested blocks) - * @param subclass - * @returns - */ -const getRecursiveValue = (subclass: SubClass): string => { - const firstChild = subclass.children?.[0]; - - if (firstChild == null) { - return null; - } - - return firstChild.args == null ? firstChild.value : getRecursiveValue(firstChild.args); -}; - -/** - * // TODO: description goes here... - * {% blockref "text", "id" %} - * ... - * {% endblockref %} - */ -function BlockReferenceExtension(): void { - this.tags = ['blockref']; - - this.parse = function (parser, nodes) { - const tok = parser.nextToken(); // Get the tag token - - // Parse the args and move after the block end. - const args: SubClass = parser.parseSignature(null, true); - parser.advanceAfterBlockEnd(tok.value); - - // Parse the body - const body: ParsedSignature = parser.parseUntilBlocks('blockref', 'endblockref'); - parser.advanceAfterBlockEnd(); - - // Parse the name of the "needle" or template variable name that we will search for (e.g. "text" in `{% blockref "text", "id" %}`) - const needle = args.children[0].value; - - // Find line number of where our needle is located in template - const needleSubclass = body.children.find((c) => getRecursiveValue(c) === needle); - - this.lineNumber = needleSubclass?.lineno; - - // Actually do work on block body and arguments - return new nodes.CallExtension(this, 'run', args, [body]); - }; - - this.run = function ( - context: Context, - _needle: keyof Context['ctx'], - highlightId: keyof Context['ctx'], - bodyCallback: () => string - ) { - const renderedTemplate: string = bodyCallback(); - - // `lineNumber` can be undefined if highlight text ({{text}}) is not used in template - if (this.lineNumber == null) { - return renderedTemplate; - } - - const buffer = sb(renderedTemplate); - - const blockRef = `${HighlightIdBlockRefPrefix}${context.ctx[highlightId]}`; - const blockRefSuffixLine = `${buffer.getLine(this.lineNumber + 1)} ${blockRef}`; - - buffer.replace({ line: this.lineNumber, content: blockRefSuffixLine }); - return new nunjucks.runtime.SafeString(buffer.toString()); - }; -} - -export { BlockReferenceExtension, TrimAllEmptyLinesExtension }; +/* eslint-disable @typescript-eslint/restrict-plus-operands */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +import nunjucks from 'nunjucks'; + +import { sb } from '~/utils'; + +import { HighlightIdBlockRefPrefix } from './renderer'; + +type SubClass = { + children?: SubClassValue[]; + colno: number; + lineno: number; +}; + +type SubClassValue = { + args?: SubClass; + name?: SubClassValue; + colno: number; + lineno: number; + value: string; +}; + +type ParsedSignature = { + children: SubClass[]; +}; + +type Context = { + ctx: Record ; +}; + +function TrimAllEmptyLinesExtension(): void { + this.tags = ['trim']; + + this.parse = function (parser, nodes) { + const tok = parser.nextToken(); // Get the tag token + + // Parse the args and move after the block end. + const args: ParsedSignature = parser.parseSignature(null, true); + parser.advanceAfterBlockEnd(tok.value); + + // Parse the body + const body: ParsedSignature = parser.parseUntilBlocks('trim', 'endtrim'); + parser.advanceAfterBlockEnd(); + + // Actually do work on block body and arguments + return new nodes.CallExtension(this, 'run', args, [body]); + }; + + this.run = function (_context, bodyCallback) { + const rawCode: string = bodyCallback(); + const rawCodeNoLines = rawCode.replace(/(^[ \t]*\n)/gm, '').trim(); + return new nunjucks.runtime.SafeString(rawCodeNoLines); + }; +} + +/** + * Recursively iterates through AST of a user template and find the value + * of every node. This is made complex by the fact that some AST nodes + * do not have values (e.g. if statement, nested blocks) + * @param subclass + * @returns + */ +const getRecursiveValue = (subclass: SubClass): string => { + const firstChild = subclass.children?.[0]; + + if (firstChild == null) { + return null; + } + + return firstChild.args == null ? firstChild.value : getRecursiveValue(firstChild.args); +}; + +/** + * // TODO: description goes here... + * {% blockref "text", "id" %} + * ... + * {% endblockref %} + */ +function BlockReferenceExtension(): void { + this.tags = ['blockref']; + + this.parse = function (parser, nodes) { + const tok = parser.nextToken(); // Get the tag token + + // Parse the args and move after the block end. + const args: SubClass = parser.parseSignature(null, true); + parser.advanceAfterBlockEnd(tok.value); + + // Parse the body + const body: ParsedSignature = parser.parseUntilBlocks('blockref', 'endblockref'); + parser.advanceAfterBlockEnd(); + + // Parse the name of the "needle" or template variable name that we will search for (e.g. "text" in `{% blockref "text", "id" %}`) + const needle = args.children[0].value; + + // Find line number of where our needle is located in template + const needleSubclass = body.children.find((c) => getRecursiveValue(c) === needle); + + this.lineNumber = needleSubclass?.lineno; + + // Actually do work on block body and arguments + return new nodes.CallExtension(this, 'run', args, [body]); + }; + + this.run = function ( + context: Context, + _needle: keyof Context['ctx'], + highlightId: keyof Context['ctx'], + bodyCallback: () => string + ) { + const renderedTemplate: string = bodyCallback(); + + // `lineNumber` can be undefined if highlight text ({{text}}) is not used in template + if (this.lineNumber == null) { + return renderedTemplate; + } + + const buffer = sb(renderedTemplate); + + const blockRef = `${HighlightIdBlockRefPrefix}${context.ctx[highlightId]}`; + const blockRefSuffixLine = `${buffer.getLine(this.lineNumber + 1)} ${blockRef}`; + + buffer.replace({ line: this.lineNumber, content: blockRefSuffixLine }); + return new nunjucks.runtime.SafeString(buffer.toString()); + }; +} + +export { BlockReferenceExtension, TrimAllEmptyLinesExtension }; diff --git a/src/rendering/renderer/fileNameRenderer.spec.ts b/src/rendering/renderer/fileNameRenderer.spec.ts index 5b1ea60..54c8639 100644 --- a/src/rendering/renderer/fileNameRenderer.spec.ts +++ b/src/rendering/renderer/fileNameRenderer.spec.ts @@ -1,52 +1,52 @@ -import type { Book } from '~/models'; - -import FileNameRenderer from './fileNameRenderer'; - -describe('FileNameRenderer', () => { - describe('validate', () => { - it('should return true for valid template', () => { - const renderer = new FileNameRenderer(''); - expect(renderer.validate('{{shortTitle}}')).toBe(true); - }); - - it('should return false for invalid template', () => { - const renderer = new FileNameRenderer(''); - expect(renderer.validate('{{shortTitle')).toBe(false); - }); - - it.each([null, undefined])('should return true for %s template', (template) => { - const renderer = new FileNameRenderer(''); - expect(renderer.validate(template)).toBe(true); - }); - }); - - describe('render', () => { - it('File name with shortened book title', () => { - const book: Partial = { - title: 'Immunity to change: How to overcome it', - }; - - const renderer = new FileNameRenderer('{{shortTitle}}'); - expect(renderer.render(book)).toBe('Immunity to change.md'); - }); - - it('File name with book title as is', () => { - const book: Partial = { - title: 'Immunity to change: How to overcome it', - }; - - const renderer = new FileNameRenderer('{{longTitle}}'); - expect(renderer.render(book)).toBe('Immunity to change How to overcome it.md'); - }); - - it('File name with author', () => { - const book: Partial = { - title: 'Immunity to change: How to overcome it', - author: 'John Doe', - }; - - const renderer = new FileNameRenderer('{{author}}'); - expect(renderer.render(book)).toBe('John Doe.md'); - }); - }); -}); +import type { Book } from '~/models'; + +import FileNameRenderer from './fileNameRenderer'; + +describe('FileNameRenderer', () => { + describe('validate', () => { + it('should return true for valid template', () => { + const renderer = new FileNameRenderer(''); + expect(renderer.validate('{{shortTitle}}')).toBe(true); + }); + + it('should return false for invalid template', () => { + const renderer = new FileNameRenderer(''); + expect(renderer.validate('{{shortTitle')).toBe(false); + }); + + it.each([null, undefined])('should return true for %s template', (template) => { + const renderer = new FileNameRenderer(''); + expect(renderer.validate(template)).toBe(true); + }); + }); + + describe('render', () => { + it('File name with shortened book title', () => { + const book: Partial = { + title: 'Immunity to change: How to overcome it', + }; + + const renderer = new FileNameRenderer('{{shortTitle}}'); + expect(renderer.render(book)).toBe('Immunity to change.md'); + }); + + it('File name with book title as is', () => { + const book: Partial = { + title: 'Immunity to change: How to overcome it', + }; + + const renderer = new FileNameRenderer('{{longTitle}}'); + expect(renderer.render(book)).toBe('Immunity to change How to overcome it.md'); + }); + + it('File name with author', () => { + const book: Partial = { + title: 'Immunity to change: How to overcome it', + author: 'John Doe', + }; + + const renderer = new FileNameRenderer('{{author}}'); + expect(renderer.render(book)).toBe('John Doe.md'); + }); + }); +}); diff --git a/src/rendering/renderer/fileNameRenderer.ts b/src/rendering/renderer/fileNameRenderer.ts index 70534bb..62a3ebc 100644 --- a/src/rendering/renderer/fileNameRenderer.ts +++ b/src/rendering/renderer/fileNameRenderer.ts @@ -1,31 +1,31 @@ -import nunjucks, { Environment } from 'nunjucks'; -import sanitize from 'sanitize-filename'; - -import type { Book } from '~/models'; - -import { fileNameTemplateVariables } from './templateVariables'; - -export default class FileNameRenderer { - private nunjucks: Environment; - - constructor(private template: string) { - this.nunjucks = new nunjucks.Environment(null, { autoescape: false }); - } - - public validate(template: string): boolean { - try { - this.nunjucks.renderString(template ?? '', {}); - return true; - } catch (error) { - return false; - } - } - - public render(book: Partial ): string { - const templateVariables = fileNameTemplateVariables(book); - - const fileName = this.nunjucks.renderString(this.template, templateVariables); - - return `${sanitize(fileName)}.md`; - } -} +import nunjucks, { Environment } from 'nunjucks'; +import sanitize from 'sanitize-filename'; + +import type { Book } from '~/models'; + +import { fileNameTemplateVariables } from './templateVariables'; + +export default class FileNameRenderer { + private nunjucks: Environment; + + constructor(private template: string) { + this.nunjucks = new nunjucks.Environment(null, { autoescape: false }); + } + + public validate(template: string): boolean { + try { + this.nunjucks.renderString(template ?? '', {}); + return true; + } catch (error) { + return false; + } + } + + public render(book: Partial ): string { + const templateVariables = fileNameTemplateVariables(book); + + const fileName = this.nunjucks.renderString(this.template, templateVariables); + + return `${sanitize(fileName)}.md`; + } +} diff --git a/src/rendering/renderer/fileRenderer.spec.ts b/src/rendering/renderer/fileRenderer.spec.ts index 5462f71..7e05ff1 100644 --- a/src/rendering/renderer/fileRenderer.spec.ts +++ b/src/rendering/renderer/fileRenderer.spec.ts @@ -1,182 +1,182 @@ -import faker from 'faker'; - -import type { BookHighlight } from '~/models'; - -import FileRenderer from './fileRenderer'; - -describe('FileRenderer', () => { - describe('validate', () => { - it.each([null, undefined])('should return true for %s template', (template) => { - const renderer = new FileRenderer('', ''); - expect(renderer.validate(template)).toBe(true); - }); - }); - - describe('render', () => { - describe('file template variables', () => { - const bookHighlight: BookHighlight = { - book: { - id: faker.random.alphaNumeric(4), - title: 'My book title: extended description', - author: faker.name.findName(), - asin: faker.random.alphaNumeric(4), - url: faker.internet.url(), - imageUrl: faker.image.imageUrl(), - lastAnnotatedDate: new Date(2022, 3, 4), - }, - metadata: { - isbn: faker.random.alphaNumeric(4), - pages: faker.datatype.number(100).toString(), - publicationDate: faker.date.past().toISOString(), - publisher: faker.company.companyName(), - authorUrl: faker.internet.url(), - }, - highlights: [ - { - id: faker.random.alphaNumeric(4), - text: 'highlighted text', - }, - ], - }; - - it.each([ - ['{{id}}', ''], - ['{{title}}', 'My book title'], - ['{{longTitle}}', 'My book title: extended description'], - ['{{asin}}', bookHighlight.book.asin], - ['{{url}}', bookHighlight.book.url], - ['{{imageUrl}}', bookHighlight.book.imageUrl], - ['{{lastAnnotatedDate}}', '2022-04-04'], - ['{{isbn}}', bookHighlight.metadata.isbn], - ['{{pages}}', bookHighlight.metadata.pages], - ['{{publicationDate}}', bookHighlight.metadata.publicationDate], - ['{{publisher}}', bookHighlight.metadata.publisher], - ['{{authorUrl}}', bookHighlight.metadata.authorUrl], - ['{{highlightsCount}}', '1'], - ])('template variable "%s" evaluated as "%s"', (template, expected) => { - const renderer = new FileRenderer(template, ''); - expect(renderer.render(bookHighlight)).toBe(expected); - }); - }); - - describe('file template variables works for null values', () => { - const bookHighlight: BookHighlight = { - book: { - id: faker.random.alphaNumeric(4), - title: 'My book title: extended description', - author: faker.name.findName(), - }, - metadata: {}, - highlights: [ - { - id: faker.random.alphaNumeric(4), - text: 'highlighted text', - }, - ], - }; - - it.each([ - ['{{asin}}', ''], - ['{{url}}', ''], - ['{{imageUrl}}', ''], - ['{{lastAnnotatedDate}}', ''], - ['{{isbn}}', ''], - ['{{pages}}', ''], - ['{{publicationDate}}', ''], - ['{{publisher}}', ''], - ['{{authorUrl}}', ''], - ['{{highlightsCount}}', '1'], - ])('template variable "%s" evaluated as "%s"', (template, expected) => { - const renderer = new FileRenderer(template, ''); - expect(renderer.render(bookHighlight)).toBe(expected); - }); - }); - - it('Simple render of a minimalist file template', () => { - const bookHighlight: BookHighlight = { - book: { - id: faker.random.alphaNumeric(4), - title: 'My book title: extended description', - author: faker.name.findName(), - }, - metadata: { - publisher: faker.company.companyName(), - }, - highlights: [ - { - id: 'H1', - text: 'highlighted text', - }, - { - id: 'H2', - text: 'another piece of text', - }, - ], - }; - - const fileTemplate = ` -# {{title}} - -## Metadata -- Author:: {{author}} -- Publisher:: {{publisher}} -- Highlights count:: {{highlightsCount}} - -## Highlights -{{highlights}} -`; - - const renderedContent = ` -# My book title - -## Metadata -- Author:: ${bookHighlight.book.author} -- Publisher:: ${bookHighlight.metadata.publisher} -- Highlights count:: 2 - -## Highlights -- highlighted text ^ref-H1 -- another piece of text ^ref-H2 -`; - - const renderer = new FileRenderer(fileTemplate, '- {{text}}'); - expect(renderer.render(bookHighlight)).toBe(renderedContent); - }); - - it('Simple render works without optional metadata', () => { - const bookHighlight: BookHighlight = { - book: { - id: faker.random.alphaNumeric(4), - title: 'My book title: extended description', - author: faker.name.findName(), - }, - highlights: [], - }; - - const fileTemplate = ` -# {{title}} - -## Metadata -- Author:: {{author}} -- Publisher:: {{publisher}}. - -## Highlights -{{highlights}} -`; - - const renderedContent = ` -# My book title - -## Metadata -- Author:: ${bookHighlight.book.author} -- Publisher:: . - -## Highlights - -`; - - const renderer = new FileRenderer(fileTemplate, '- {{text}}'); - expect(renderer.render(bookHighlight)).toBe(renderedContent); - }); - }); -}); +import faker from 'faker'; + +import type { BookHighlight } from '~/models'; + +import FileRenderer from './fileRenderer'; + +describe('FileRenderer', () => { + describe('validate', () => { + it.each([null, undefined])('should return true for %s template', (template) => { + const renderer = new FileRenderer('', ''); + expect(renderer.validate(template)).toBe(true); + }); + }); + + describe('render', () => { + describe('file template variables', () => { + const bookHighlight: BookHighlight = { + book: { + id: faker.random.alphaNumeric(4), + title: 'My book title: extended description', + author: faker.name.findName(), + asin: faker.random.alphaNumeric(4), + url: faker.internet.url(), + imageUrl: faker.image.imageUrl(), + lastAnnotatedDate: new Date(2022, 3, 4), + }, + metadata: { + isbn: faker.random.alphaNumeric(4), + pages: faker.datatype.number(100).toString(), + publicationDate: faker.date.past().toISOString(), + publisher: faker.company.companyName(), + authorUrl: faker.internet.url(), + }, + highlights: [ + { + id: faker.random.alphaNumeric(4), + text: 'highlighted text', + }, + ], + }; + + it.each([ + ['{{id}}', ''], + ['{{title}}', 'My book title'], + ['{{longTitle}}', 'My book title: extended description'], + ['{{asin}}', bookHighlight.book.asin], + ['{{url}}', bookHighlight.book.url], + ['{{imageUrl}}', bookHighlight.book.imageUrl], + ['{{lastAnnotatedDate}}', '2022-04-04'], + ['{{isbn}}', bookHighlight.metadata.isbn], + ['{{pages}}', bookHighlight.metadata.pages], + ['{{publicationDate}}', bookHighlight.metadata.publicationDate], + ['{{publisher}}', bookHighlight.metadata.publisher], + ['{{authorUrl}}', bookHighlight.metadata.authorUrl], + ['{{highlightsCount}}', '1'], + ])('template variable "%s" evaluated as "%s"', (template, expected) => { + const renderer = new FileRenderer(template, ''); + expect(renderer.render(bookHighlight)).toBe(expected); + }); + }); + + describe('file template variables works for null values', () => { + const bookHighlight: BookHighlight = { + book: { + id: faker.random.alphaNumeric(4), + title: 'My book title: extended description', + author: faker.name.findName(), + }, + metadata: {}, + highlights: [ + { + id: faker.random.alphaNumeric(4), + text: 'highlighted text', + }, + ], + }; + + it.each([ + ['{{asin}}', ''], + ['{{url}}', ''], + ['{{imageUrl}}', ''], + ['{{lastAnnotatedDate}}', ''], + ['{{isbn}}', ''], + ['{{pages}}', ''], + ['{{publicationDate}}', ''], + ['{{publisher}}', ''], + ['{{authorUrl}}', ''], + ['{{highlightsCount}}', '1'], + ])('template variable "%s" evaluated as "%s"', (template, expected) => { + const renderer = new FileRenderer(template, ''); + expect(renderer.render(bookHighlight)).toBe(expected); + }); + }); + + it('Simple render of a minimalist file template', () => { + const bookHighlight: BookHighlight = { + book: { + id: faker.random.alphaNumeric(4), + title: 'My book title: extended description', + author: faker.name.findName(), + }, + metadata: { + publisher: faker.company.companyName(), + }, + highlights: [ + { + id: 'H1', + text: 'highlighted text', + }, + { + id: 'H2', + text: 'another piece of text', + }, + ], + }; + + const fileTemplate = ` +# {{title}} + +## Metadata +- Author:: {{author}} +- Publisher:: {{publisher}} +- Highlights count:: {{highlightsCount}} + +## Highlights +{{highlights}} +`; + + const renderedContent = ` +# My book title + +## Metadata +- Author:: ${bookHighlight.book.author} +- Publisher:: ${bookHighlight.metadata.publisher} +- Highlights count:: 2 + +## Highlights +- highlighted text ^ref-H1 +- another piece of text ^ref-H2 +`; + + const renderer = new FileRenderer(fileTemplate, '- {{text}}'); + expect(renderer.render(bookHighlight)).toBe(renderedContent); + }); + + it('Simple render works without optional metadata', () => { + const bookHighlight: BookHighlight = { + book: { + id: faker.random.alphaNumeric(4), + title: 'My book title: extended description', + author: faker.name.findName(), + }, + highlights: [], + }; + + const fileTemplate = ` +# {{title}} + +## Metadata +- Author:: {{author}} +- Publisher:: {{publisher}}. + +## Highlights +{{highlights}} +`; + + const renderedContent = ` +# My book title + +## Metadata +- Author:: ${bookHighlight.book.author} +- Publisher:: . + +## Highlights + +`; + + const renderer = new FileRenderer(fileTemplate, '- {{text}}'); + expect(renderer.render(bookHighlight)).toBe(renderedContent); + }); + }); +}); diff --git a/src/rendering/renderer/fileRenderer.ts b/src/rendering/renderer/fileRenderer.ts index a6fc048..ae24c8e 100644 --- a/src/rendering/renderer/fileRenderer.ts +++ b/src/rendering/renderer/fileRenderer.ts @@ -1,41 +1,41 @@ -import { Environment } from 'nunjucks'; - -import type { BookHighlight } from '~/models'; - -import { TrimAllEmptyLinesExtension } from '../nunjucks.extensions'; - -import HighlightRenderer from './highlightRenderer'; -import { fileTemplateVariables } from './templateVariables'; - -export default class FileRenderer { - private nunjucks: Environment; - private highlightRenderer: HighlightRenderer; - - constructor(private fileTemplate: string, highlightTemplate: string) { - this.nunjucks = new Environment(null, { autoescape: false }); - this.nunjucks.addExtension('Trim', new TrimAllEmptyLinesExtension()); - - this.highlightRenderer = new HighlightRenderer(highlightTemplate); - } - - public validate(template: string): boolean { - try { - this.nunjucks.renderString(template ?? '', { text: '' }); - return true; - } catch (error) { - return false; - } - } - - public render(entry: BookHighlight): string { - const { book, highlights } = entry; - - const renderedHighlights = highlights - .map((h) => this.highlightRenderer.render(h, book)) - .join('\n'); - - const templateVariables = fileTemplateVariables(entry, renderedHighlights); - - return this.nunjucks.renderString(this.fileTemplate, templateVariables); - } -} +import { Environment } from 'nunjucks'; + +import type { BookHighlight } from '~/models'; + +import { TrimAllEmptyLinesExtension } from '../nunjucks.extensions'; + +import HighlightRenderer from './highlightRenderer'; +import { fileTemplateVariables } from './templateVariables'; + +export default class FileRenderer { + private nunjucks: Environment; + private highlightRenderer: HighlightRenderer; + + constructor(private fileTemplate: string, highlightTemplate: string) { + this.nunjucks = new Environment(null, { autoescape: false }); + this.nunjucks.addExtension('Trim', new TrimAllEmptyLinesExtension()); + + this.highlightRenderer = new HighlightRenderer(highlightTemplate); + } + + public validate(template: string): boolean { + try { + this.nunjucks.renderString(template ?? '', { text: '' }); + return true; + } catch (error) { + return false; + } + } + + public render(entry: BookHighlight): string { + const { book, highlights } = entry; + + const renderedHighlights = highlights + .map((h) => this.highlightRenderer.render(h, book)) + .join('\n'); + + const templateVariables = fileTemplateVariables(entry, renderedHighlights); + + return this.nunjucks.renderString(this.fileTemplate, templateVariables); + } +} diff --git a/src/rendering/renderer/highlightRenderer.spec.ts b/src/rendering/renderer/highlightRenderer.spec.ts index fc28798..a350fee 100644 --- a/src/rendering/renderer/highlightRenderer.spec.ts +++ b/src/rendering/renderer/highlightRenderer.spec.ts @@ -1,136 +1,136 @@ -import faker from 'faker'; - -import type { Book, Highlight } from '~/models'; - -import HighlightRenderer from './highlightRenderer'; - -describe('HighlightRenderer', () => { - describe('validate', () => { - it('should return true for valid template', () => { - const renderer = new HighlightRenderer(''); - expect(renderer.validate('{{note}}')).toBe(true); - }); - - it('should return false for invalid template', () => { - const renderer = new HighlightRenderer(''); - expect(renderer.validate('{{note')).toBe(false); - }); - - it.each([null, undefined])('should return true for %s template', (template) => { - const renderer = new HighlightRenderer(''); - expect(renderer.validate(template)).toBe(true); - }); - }); - - describe('render', () => { - const book: Book = { - id: faker.datatype.uuid(), - title: 'Book title', - author: faker.name.findName(), - }; - - describe('highlight template variables', () => { - const highlight: Highlight = { - id: '123', - text: 'highlighted text', - location: '110', - page: '3', - note: 'my smart note', - color: 'pink', - }; - - it.each([ - ['{{text}}', 'highlighted text ^ref-123'], - ['{{location}}', '110'], - ['{{page}}', '3'], - ['{{note}}', 'my smart note'], - ['{{color}}', 'pink'], - ['{{createdDate}}', ''], - ['{{title}}', 'Book title'], - ['{{longTitle}}', 'Book title'], - ])('template variable "%s" evaluated as "%s"', (template, expected) => { - const renderer = new HighlightRenderer(template); - expect(renderer.render(highlight, book)).toBe(expected); - }); - - it.each([ - [new Date('2019-11-29T18:00:13Z'), '{{createdDate | date}}', '29-11-2019'], - [ - new Date('2016-04-18T07:28:27Z'), - '{{createdDate | date("LLL")}}', - 'April 18, 2016 7:28 AM', - ], - ])( - 'createdDate template variable is set when highlight creation date is set', - (createdDate: Date, template: string, expected: string) => { - const highlight: Highlight = { - id: faker.datatype.uuid(), - text: faker.lorem.sentence(), - createdDate, - }; - - const renderer = new HighlightRenderer(template); - expect(renderer.render(highlight, book)).toBe(expected); - } - ); - }); - - it('appLink template variable is set when a book has an ASIN value', () => { - const myBook: Book = { ...book, asin: 'A1234' }; - const highlight: Highlight = { - id: faker.datatype.uuid(), - text: 'highlighted text', - }; - - const renderer = new HighlightRenderer('{{text}} - {{appLink}}'); - expect(renderer.render(highlight, myBook)).toMatch( - new RegExp('^highlighted text - kindle://(.*) \\^ref-.*$') - ); - }); - - it('appLink template variable is undefined when a book is missing an ASIN value', () => { - const highlight: Highlight = { - id: faker.datatype.uuid(), - text: 'highlighted text', - }; - - const renderer = new HighlightRenderer('{{text}} - {{appLink}}'); - - expect(renderer.render(highlight, book)).toMatch( - // eslint-disable-next-line no-regex-spaces - new RegExp('^highlighted text - \\^ref-.*$') - ); - }); - - it('Only leading and trailing lines in a template are always trimmed', () => { - const templateWithTrailingLines = '\n\n{{text}}\n\n{{location}}\n\n'; - const highlight: Highlight = { - id: faker.datatype.uuid(), - text: 'highlighted text', - location: '110', - }; - - const renderer = new HighlightRenderer(templateWithTrailingLines); - - expect(renderer.render(highlight, book)).toMatch( - new RegExp('^highlighted text \\^ref-.*\\n\\n110$') - ); - }); - - it('Highlight template starting with if statement renders as expected', () => { - const template = `{% if note %}{{note}}{% endif %} -{{ text }}`; - - const highlight: Highlight = { - id: faker.datatype.uuid(), - text: 'highlighted text', - }; - - const renderer = new HighlightRenderer(template); - - expect(renderer.render(highlight, book)).toMatch( - new RegExp(/highlighted text \^ref-.*/) - ); - }); - }); -}); +import faker from 'faker'; + +import type { Book, Highlight } from '~/models'; + +import HighlightRenderer from './highlightRenderer'; + +describe('HighlightRenderer', () => { + describe('validate', () => { + it('should return true for valid template', () => { + const renderer = new HighlightRenderer(''); + expect(renderer.validate('{{note}}')).toBe(true); + }); + + it('should return false for invalid template', () => { + const renderer = new HighlightRenderer(''); + expect(renderer.validate('{{note')).toBe(false); + }); + + it.each([null, undefined])('should return true for %s template', (template) => { + const renderer = new HighlightRenderer(''); + expect(renderer.validate(template)).toBe(true); + }); + }); + + describe('render', () => { + const book: Book = { + id: faker.datatype.uuid(), + title: 'Book title', + author: faker.name.findName(), + }; + + describe('highlight template variables', () => { + const highlight: Highlight = { + id: '123', + text: 'highlighted text', + location: '110', + page: '3', + note: 'my smart note', + color: 'pink', + }; + + it.each([ + ['{{text}}', 'highlighted text ^ref-123'], + ['{{location}}', '110'], + ['{{page}}', '3'], + ['{{note}}', 'my smart note'], + ['{{color}}', 'pink'], + ['{{createdDate}}', ''], + ['{{title}}', 'Book title'], + ['{{longTitle}}', 'Book title'], + ])('template variable "%s" evaluated as "%s"', (template, expected) => { + const renderer = new HighlightRenderer(template); + expect(renderer.render(highlight, book)).toBe(expected); + }); + + it.each([ + [new Date('2019-11-29T18:00:13Z'), '{{createdDate | date}}', '29-11-2019'], + [ + new Date('2016-04-18T07:28:27Z'), + '{{createdDate | date("LLL")}}', + 'April 18, 2016 7:28 AM', + ], + ])( + 'createdDate template variable is set when highlight creation date is set', + (createdDate: Date, template: string, expected: string) => { + const highlight: Highlight = { + id: faker.datatype.uuid(), + text: faker.lorem.sentence(), + createdDate, + }; + + const renderer = new HighlightRenderer(template); + expect(renderer.render(highlight, book)).toBe(expected); + } + ); + }); + + it('appLink template variable is set when a book has an ASIN value', () => { + const myBook: Book = { ...book, asin: 'A1234' }; + const highlight: Highlight = { + id: faker.datatype.uuid(), + text: 'highlighted text', + }; + + const renderer = new HighlightRenderer('{{text}} - {{appLink}}'); + expect(renderer.render(highlight, myBook)).toMatch( + new RegExp('^highlighted text - kindle://(.*) \\^ref-.*$') + ); + }); + + it('appLink template variable is undefined when a book is missing an ASIN value', () => { + const highlight: Highlight = { + id: faker.datatype.uuid(), + text: 'highlighted text', + }; + + const renderer = new HighlightRenderer('{{text}} - {{appLink}}'); + + expect(renderer.render(highlight, book)).toMatch( + // eslint-disable-next-line no-regex-spaces + new RegExp('^highlighted text - \\^ref-.*$') + ); + }); + + it('Only leading and trailing lines in a template are always trimmed', () => { + const templateWithTrailingLines = '\n\n{{text}}\n\n{{location}}\n\n'; + const highlight: Highlight = { + id: faker.datatype.uuid(), + text: 'highlighted text', + location: '110', + }; + + const renderer = new HighlightRenderer(templateWithTrailingLines); + + expect(renderer.render(highlight, book)).toMatch( + new RegExp('^highlighted text \\^ref-.*\\n\\n110$') + ); + }); + + it('Highlight template starting with if statement renders as expected', () => { + const template = `{% if note %}{{note}}{% endif %} +{{ text }}`; + + const highlight: Highlight = { + id: faker.datatype.uuid(), + text: 'highlighted text', + }; + + const renderer = new HighlightRenderer(template); + + expect(renderer.render(highlight, book)).toMatch( + new RegExp(/highlighted text \^ref-.*/) + ); + }); + }); +}); diff --git a/src/rendering/renderer/highlightRenderer.ts b/src/rendering/renderer/highlightRenderer.ts index 4506094..ec2783b 100644 --- a/src/rendering/renderer/highlightRenderer.ts +++ b/src/rendering/renderer/highlightRenderer.ts @@ -1,43 +1,43 @@ -import { Environment } from 'nunjucks'; -import dateFilter from 'nunjucks-date-filter'; - -import type { Book, Highlight } from '~/models'; -import highlightTemplateWrapper from '~/rendering//templates/highlightTemplateWrapper.njk'; - -import { BlockReferenceExtension } from '../nunjucks.extensions'; - -import { highlightTemplateVariables } from './templateVariables'; -import { trimMultipleLines } from './utils'; - -export const HighlightIdBlockRefPrefix = '^ref-'; - -dateFilter.setDefaultFormat('DD-MM-YYYY'); - -export default class HighlightRenderer { - private nunjucks: Environment; - - constructor(private template: string) { - this.nunjucks = new Environment(null, { autoescape: false }); - this.nunjucks.addExtension('BlockRef', new BlockReferenceExtension()); - this.nunjucks.addFilter('date', dateFilter); - } - - public validate(template: string): boolean { - try { - this.nunjucks.renderString(template ?? '', { text: '' }); - return true; - } catch (error) { - return false; - } - } - - public render(highlight: Highlight, book: Book): string { - const templateVariables = highlightTemplateVariables(highlight, book); - - const highlightTemplate = highlightTemplateWrapper.replace('{{ content }}', this.template); - - const renderedHighlight = this.nunjucks.renderString(highlightTemplate, templateVariables); - - return trimMultipleLines(renderedHighlight); - } -} +import { Environment } from 'nunjucks'; +import dateFilter from 'nunjucks-date-filter'; + +import type { Book, Highlight } from '~/models'; +import highlightTemplateWrapper from '~/rendering//templates/highlightTemplateWrapper.njk'; + +import { BlockReferenceExtension } from '../nunjucks.extensions'; + +import { highlightTemplateVariables } from './templateVariables'; +import { trimMultipleLines } from './utils'; + +export const HighlightIdBlockRefPrefix = '^ref-'; + +dateFilter.setDefaultFormat('DD-MM-YYYY'); + +export default class HighlightRenderer { + private nunjucks: Environment; + + constructor(private template: string) { + this.nunjucks = new Environment(null, { autoescape: false }); + this.nunjucks.addExtension('BlockRef', new BlockReferenceExtension()); + this.nunjucks.addFilter('date', dateFilter); + } + + public validate(template: string): boolean { + try { + this.nunjucks.renderString(template ?? '', { text: '' }); + return true; + } catch (error) { + return false; + } + } + + public render(highlight: Highlight, book: Book): string { + const templateVariables = highlightTemplateVariables(highlight, book); + + const highlightTemplate = highlightTemplateWrapper.replace('{{ content }}', this.template); + + const renderedHighlight = this.nunjucks.renderString(highlightTemplate, templateVariables); + + return trimMultipleLines(renderedHighlight); + } +} diff --git a/src/rendering/renderer/index.ts b/src/rendering/renderer/index.ts index 7ce4524..53b73ef 100644 --- a/src/rendering/renderer/index.ts +++ b/src/rendering/renderer/index.ts @@ -1,3 +1,3 @@ -export { default as FileNameRenderer } from './fileNameRenderer'; -export { default as FileRenderer } from './fileRenderer'; -export { default as HighlightRenderer, HighlightIdBlockRefPrefix } from './highlightRenderer'; +export { default as FileNameRenderer } from './fileNameRenderer'; +export { default as FileRenderer } from './fileRenderer'; +export { default as HighlightRenderer, HighlightIdBlockRefPrefix } from './highlightRenderer'; diff --git a/src/rendering/renderer/templateVariables.spec.ts b/src/rendering/renderer/templateVariables.spec.ts index 50c7cef..f464111 100644 --- a/src/rendering/renderer/templateVariables.spec.ts +++ b/src/rendering/renderer/templateVariables.spec.ts @@ -1,41 +1,41 @@ -import { AuthorsTemplateVariables, authorsTemplateVariables } from './templateVariables'; - -describe('authorsTemplateVariables', () => { - it('Breaks one author correctly', () => { - const variables = authorsTemplateVariables('Michael Port'); - expect(variables).toEqual ({ - author: 'Michael Port', - authorsLastNames: 'Port', - firstAuthorFirstName: 'Michael', - firstAuthorLastName: 'Port', - secondAuthorFirstName: undefined, - secondAuthorLastName: undefined, - }); - }); - - it('Breaks two authors correctly', () => { - const variables = authorsTemplateVariables('Robert Kegan and Lisa Laskow Lahey'); - expect(variables).toEqual ({ - author: 'Robert Kegan and Lisa Laskow Lahey', - authorsLastNames: 'Kegan-Lahey', - firstAuthorFirstName: 'Robert', - firstAuthorLastName: 'Kegan', - secondAuthorFirstName: 'Lisa', - secondAuthorLastName: 'Lahey', - }); - }); - - it('Breaks three authors correctly', () => { - const variables = authorsTemplateVariables( - 'Vicki Robin, Joe Dominguez, And Mr. Money Mustache' - ); - expect(variables).toEqual ({ - author: 'Vicki Robin, Joe Dominguez, And Mr. Money Mustache', - authorsLastNames: 'Robin_et_al', - firstAuthorFirstName: 'Vicki', - firstAuthorLastName: 'Robin', - secondAuthorFirstName: 'Joe', - secondAuthorLastName: 'Dominguez', - }); - }); -}); +import { AuthorsTemplateVariables, authorsTemplateVariables } from './templateVariables'; + +describe('authorsTemplateVariables', () => { + it('Breaks one author correctly', () => { + const variables = authorsTemplateVariables('Michael Port'); + expect(variables).toEqual ({ + author: 'Michael Port', + authorsLastNames: 'Port', + firstAuthorFirstName: 'Michael', + firstAuthorLastName: 'Port', + secondAuthorFirstName: undefined, + secondAuthorLastName: undefined, + }); + }); + + it('Breaks two authors correctly', () => { + const variables = authorsTemplateVariables('Robert Kegan and Lisa Laskow Lahey'); + expect(variables).toEqual ({ + author: 'Robert Kegan and Lisa Laskow Lahey', + authorsLastNames: 'Kegan-Lahey', + firstAuthorFirstName: 'Robert', + firstAuthorLastName: 'Kegan', + secondAuthorFirstName: 'Lisa', + secondAuthorLastName: 'Lahey', + }); + }); + + it('Breaks three authors correctly', () => { + const variables = authorsTemplateVariables( + 'Vicki Robin, Joe Dominguez, And Mr. Money Mustache' + ); + expect(variables).toEqual ({ + author: 'Vicki Robin, Joe Dominguez, And Mr. Money Mustache', + authorsLastNames: 'Robin_et_al', + firstAuthorFirstName: 'Vicki', + firstAuthorLastName: 'Robin', + secondAuthorFirstName: 'Joe', + secondAuthorLastName: 'Dominguez', + }); + }); +}); diff --git a/src/rendering/renderer/templateVariables.ts b/src/rendering/renderer/templateVariables.ts index 12a617e..c032971 100644 --- a/src/rendering/renderer/templateVariables.ts +++ b/src/rendering/renderer/templateVariables.ts @@ -1,120 +1,120 @@ -import moment from 'moment'; - -import type { Book, BookHighlight, Highlight } from '~/models'; -import { parseAuthors, shortenTitle } from '~/utils'; - -import { generateAppLink } from './utils'; - -export type AuthorsTemplateVariables = { - author: string; - authorsLastNames: string; - firstAuthorFirstName?: string; - firstAuthorLastName: string; - secondAuthorFirstName?: string; - secondAuthorLastName?: string; -}; - -type CommonTemplateVariables = AuthorsTemplateVariables & { - title: string; - longTitle: string; -}; - -type FileNameTemplateVariables = CommonTemplateVariables & { - shortTitle: string; // TODO: Eventually deprecate -}; - -type FileTemplateVariables = CommonTemplateVariables & { - asin?: string; - url?: string; - imageUrl?: string; - lastAnnotatedDate?: string; - appLink?: string; - isbn?: string; - pages: string; - publicationDate: string; - publisher: string; - authorUrl: string; - highlightsCount: number; - highlights: string; -}; - -type HighlightTemplateVariables = CommonTemplateVariables & { - id: string; - text: string; - location?: string; - page?: string; - note?: string; - color?: 'pink' | 'blue' | 'yellow' | 'orange'; - createdDate?: Date; - appLink?: string; -}; - -export const authorsTemplateVariables = (author: string): AuthorsTemplateVariables => { - const authors = parseAuthors(author); - - let authorsLastNames = authors[0].lastName; - - if (authors.length == 2) { - authorsLastNames += `-${authors[1].lastName}`; - } else if (authors.length > 2) { - authorsLastNames += `_et_al`; - } - - return { - author: author, - authorsLastNames, - firstAuthorFirstName: authors[0].firstName, - firstAuthorLastName: authors[0].lastName, - secondAuthorFirstName: authors[1]?.firstName, - secondAuthorLastName: authors[1]?.lastName, - }; -}; - -export const commonTemplateVariables = (book: Partial ): FileNameTemplateVariables => { - return { - title: shortenTitle(book.title), - shortTitle: shortenTitle(book.title), - longTitle: book.title, - ...authorsTemplateVariables(book.author), - }; -}; - -export const fileNameTemplateVariables = (book: Partial ): FileNameTemplateVariables => { - return commonTemplateVariables(book); -}; - -export const highlightTemplateVariables = ( - highlight: Highlight, - book: Book -): HighlightTemplateVariables => { - return { - ...highlight, - ...commonTemplateVariables(book), - appLink: generateAppLink(book.asin, highlight), - }; -}; - -export const fileTemplateVariables = ( - entry: BookHighlight, - renderedHighlights: string -): FileTemplateVariables => { - const { book, highlights, metadata } = entry; - - return { - ...commonTemplateVariables(book), - asin: book.asin, - url: book.url, - imageUrl: book.imageUrl, - lastAnnotatedDate: book.lastAnnotatedDate - ? moment(book.lastAnnotatedDate).format('YYYY-MM-DD').toString() - : undefined, - appLink: generateAppLink(book.asin), - isbn: metadata?.isbn, - pages: metadata?.pages, - publicationDate: metadata?.publicationDate, - publisher: metadata?.publisher, - authorUrl: metadata?.authorUrl, - highlightsCount: highlights.length, - highlights: renderedHighlights, - }; -}; +import moment from 'moment'; + +import type { Book, BookHighlight, Highlight } from '~/models'; +import { parseAuthors, shortenTitle } from '~/utils'; + +import { generateAppLink } from './utils'; + +export type AuthorsTemplateVariables = { + author: string; + authorsLastNames: string; + firstAuthorFirstName?: string; + firstAuthorLastName: string; + secondAuthorFirstName?: string; + secondAuthorLastName?: string; +}; + +type CommonTemplateVariables = AuthorsTemplateVariables & { + title: string; + longTitle: string; +}; + +type FileNameTemplateVariables = CommonTemplateVariables & { + shortTitle: string; // TODO: Eventually deprecate +}; + +type FileTemplateVariables = CommonTemplateVariables & { + asin?: string; + url?: string; + imageUrl?: string; + lastAnnotatedDate?: string; + appLink?: string; + isbn?: string; + pages: string; + publicationDate: string; + publisher: string; + authorUrl: string; + highlightsCount: number; + highlights: string; +}; + +type HighlightTemplateVariables = CommonTemplateVariables & { + id: string; + text: string; + location?: string; + page?: string; + note?: string; + color?: 'pink' | 'blue' | 'yellow' | 'orange'; + createdDate?: Date; + appLink?: string; +}; + +export const authorsTemplateVariables = (author: string): AuthorsTemplateVariables => { + const authors = parseAuthors(author); + + let authorsLastNames = authors[0].lastName; + + if (authors.length == 2) { + authorsLastNames += `-${authors[1].lastName}`; + } else if (authors.length > 2) { + authorsLastNames += `_et_al`; + } + + return { + author: author, + authorsLastNames, + firstAuthorFirstName: authors[0].firstName, + firstAuthorLastName: authors[0].lastName, + secondAuthorFirstName: authors[1]?.firstName, + secondAuthorLastName: authors[1]?.lastName, + }; +}; + +export const commonTemplateVariables = (book: Partial ): FileNameTemplateVariables => { + return { + title: shortenTitle(book.title), + shortTitle: shortenTitle(book.title), + longTitle: book.title, + ...authorsTemplateVariables(book.author), + }; +}; + +export const fileNameTemplateVariables = (book: Partial ): FileNameTemplateVariables => { + return commonTemplateVariables(book); +}; + +export const highlightTemplateVariables = ( + highlight: Highlight, + book: Book +): HighlightTemplateVariables => { + return { + ...highlight, + ...commonTemplateVariables(book), + appLink: generateAppLink(book.asin, highlight), + }; +}; + +export const fileTemplateVariables = ( + entry: BookHighlight, + renderedHighlights: string +): FileTemplateVariables => { + const { book, highlights, metadata } = entry; + + return { + ...commonTemplateVariables(book), + asin: book.asin, + url: book.url, + imageUrl: book.imageUrl, + lastAnnotatedDate: book.lastAnnotatedDate + ? moment(book.lastAnnotatedDate).format('YYYY-MM-DD').toString() + : undefined, + appLink: generateAppLink(book.asin), + isbn: metadata?.isbn, + pages: metadata?.pages, + publicationDate: metadata?.publicationDate, + publisher: metadata?.publisher, + authorUrl: metadata?.authorUrl, + highlightsCount: highlights.length, + highlights: renderedHighlights, + }; +}; diff --git a/src/rendering/renderer/utils.ts b/src/rendering/renderer/utils.ts index aa32da4..d4422ed 100644 --- a/src/rendering/renderer/utils.ts +++ b/src/rendering/renderer/utils.ts @@ -1,15 +1,15 @@ -import type { Highlight } from '~/models'; - -export const trimMultipleLines = (content: string): string => { - return content.trim().replace(/(\n){3,}/, '\n\n'); -}; - -export const generateAppLink = (bookAsin: string, highlight?: Highlight): string => { - if (bookAsin == null) { - return null; - } - if (highlight?.location != null) { - return `kindle://book?action=open&asin=${bookAsin}&location=${highlight.location}`; - } - return `kindle://book?action=open&asin=${bookAsin}`; -}; +import type { Highlight } from '~/models'; + +export const trimMultipleLines = (content: string): string => { + return content.trim().replace(/(\n){3,}/, '\n\n'); +}; + +export const generateAppLink = (bookAsin: string, highlight?: Highlight): string => { + if (bookAsin == null) { + return null; + } + if (highlight?.location != null) { + return `kindle://book?action=open&asin=${bookAsin}&location=${highlight.location}`; + } + return `kindle://book?action=open&asin=${bookAsin}`; +}; diff --git a/src/rendering/templates/bookTemplate.njk b/src/rendering/templates/bookTemplate.njk index 2fa5ae4..3ca2909 100644 --- a/src/rendering/templates/bookTemplate.njk +++ b/src/rendering/templates/bookTemplate.njk @@ -1,19 +1,19 @@ -# {{title}} -## Metadata -{% trim %} -{% if authorUrl %} -* Author: [{{author}}]({{authorUrl}}) -{% elif author %} -* Author: [[{{author}}]] -{% endif %} -{% if asin %}* ASIN: {{asin}}{% endif %} -{% if isbn %}* ISBN: {{isbn}}{% endif %} -{% if pages %}* Pages: {{pages}}{% endif %} -{% if publication %}* Publication: {{publication}}{% endif %} -{% if publisher %}* Publisher: {{publisher}}{% endif %} -{% if url %}* Reference: {{url}}{% endif %} -{% if appLink %}* [Kindle link]({{appLink}}){% endif %} -{% endtrim %} - -## Highlights -{{highlights}} +# {{title}} +## Metadata +{% trim %} +{% if authorUrl %} +* Author: [{{author}}]({{authorUrl}}) +{% elif author %} +* Author: [[{{author}}]] +{% endif %} +{% if asin %}* ASIN: {{asin}}{% endif %} +{% if isbn %}* ISBN: {{isbn}}{% endif %} +{% if pages %}* Pages: {{pages}}{% endif %} +{% if publication %}* Publication: {{publication}}{% endif %} +{% if publisher %}* Publisher: {{publisher}}{% endif %} +{% if url %}* Reference: {{url}}{% endif %} +{% if appLink %}* [Kindle link]({{appLink}}){% endif %} +{% endtrim %} + +## Highlights +{{highlights}} diff --git a/src/rendering/templates/defaultHighlightTemplate.njk b/src/rendering/templates/defaultHighlightTemplate.njk index 51dca03..64234a7 100644 --- a/src/rendering/templates/defaultHighlightTemplate.njk +++ b/src/rendering/templates/defaultHighlightTemplate.njk @@ -1,5 +1,5 @@ -{{ text }} — location: [{{ location }}]({{ appLink }}) - -{% if note %}{{note}}{% endif %} - ---- +{{ text }} — location: [{{ location }}]({{ appLink }}) + +{% if note %}{{note}}{% endif %} + +--- diff --git a/src/rendering/templates/highlightTemplateWrapper.njk b/src/rendering/templates/highlightTemplateWrapper.njk index 185282c..5c58e49 100644 --- a/src/rendering/templates/highlightTemplateWrapper.njk +++ b/src/rendering/templates/highlightTemplateWrapper.njk @@ -1,3 +1,3 @@ -{% blockref "text", "id" %} -{{ content }} -{% endblockref %} +{% blockref "text", "id" %} +{{ content }} +{% endblockref %} diff --git a/src/scraper/headlessBrowser.ts b/src/scraper/headlessBrowser.ts new file mode 100644 index 0000000..4ce6157 --- /dev/null +++ b/src/scraper/headlessBrowser.ts @@ -0,0 +1,69 @@ +import cheerio, { Root } from 'cheerio'; +import { BrowserWindow, remote } from 'electron'; + +const { BrowserWindow: RemoteBrowserWindow } = remote; + +type DomResult = { + dom: Root; + didNavigateUrl: string; + didFinishLoadUrl: string; +}; + +export default class HeadlessBrowser { + private window: BrowserWindow; + + public launch(): void { + this.window = new RemoteBrowserWindow({ + width: 1000, + height: 600, + webPreferences: { + webSecurity: false, + nodeIntegration: false, + }, + show: false, + }); + } + + public close(): void { + this.window?.destroy(); + } + + public async loadDom(targetUrl: string, timeout = 0): Promise { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this.window.loadURL(targetUrl); + + return new Promise ((resolveWrapper) => { + let didNavigateUrl: string = null; + + this.window.webContents.on('did-navigate', (_event, url) => { + didNavigateUrl = url; + }); + + this.window.webContents.on('did-finish-load', (_event, url) => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + Promise.resolve() + .then(() => { + if (timeout > 0) { + return new Promise((resolve) => { + setTimeout(resolve, timeout); + }); + } + }) + .then(() => { + return this.window.webContents.executeJavaScript( + `document.querySelector('body').innerHTML` + ); + }) + .then((html) => { + const $ = cheerio.load(html); + + resolveWrapper({ + dom: $, + didNavigateUrl: didNavigateUrl, + didFinishLoadUrl: url as string, + }); + }); + }); + }); + } +} diff --git a/src/scraper/index.ts b/src/scraper/index.ts index 93836bf..9525ce7 100644 --- a/src/scraper/index.ts +++ b/src/scraper/index.ts @@ -1,6 +1,6 @@ -import scrapeHighlightsForBook from './scrapeBookHighlights'; -import scrapeBookMetadata from './scrapeBookMetadata'; -import scrapeBooks from './scrapeBooks'; -import scrapeLogoutUrl from './scrapeLogoutUrl'; - -export { scrapeHighlightsForBook, scrapeBookMetadata, scrapeBooks, scrapeLogoutUrl }; +import scrapeHighlightsForBook from './scrapeBookHighlights'; +import scrapeBookMetadata from './scrapeBookMetadata'; +import { scrapeBooks } from './scrapeBooks'; +import scrapeLogoutUrl from './scrapeLogoutUrl'; + +export { scrapeHighlightsForBook, scrapeBookMetadata, scrapeBooks, scrapeLogoutUrl }; diff --git a/src/scraper/loadRemoteDom.ts b/src/scraper/loadRemoteDom.ts index 675ca32..a9a64b7 100644 --- a/src/scraper/loadRemoteDom.ts +++ b/src/scraper/loadRemoteDom.ts @@ -1,61 +1,63 @@ -import cheerio, { Root } from 'cheerio'; -import { BrowserWindow, remote } from 'electron'; - -const { BrowserWindow: RemoteBrowserWindow } = remote; - -type DomResult = { - dom: Root; - didNavigateUrl: string; - didFinishLoadUrl: string; -}; - -export const loadRemoteDom = async (targetUrl: string, timeout = 0): Promise => { - const window: BrowserWindow = new RemoteBrowserWindow({ - width: 1000, - height: 600, - webPreferences: { - webSecurity: false, - nodeIntegration: false, - }, - show: false, - }); - - // eslint-disable-next-line @typescript-eslint/no-floating-promises - window.loadURL(targetUrl); - - return new Promise ((resolveWrapper) => { - let didNavigateUrl: string = null; - - window.webContents.on('did-navigate', (_event, url) => { - didNavigateUrl = url; - }); - - window.webContents.on('did-finish-load', (_event, url) => { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - Promise.resolve() - .then(() => { - if (timeout > 0) { - return new Promise((resolve) => { - setTimeout(resolve, timeout); - }); - } - }) - .then(() => { - return window.webContents.executeJavaScript( - `document.querySelector('body').innerHTML` - ); - }) - .then((html) => { - const $ = cheerio.load(html); - - window.destroy(); - - resolveWrapper({ - dom: $, - didNavigateUrl: didNavigateUrl, - didFinishLoadUrl: url as string, - }); - }); - }); - }); -}; +import * as cheerio from 'cheerio'; +import type { Root } from 'cheerio'; + +import { BrowserWindow, remote } from 'electron'; + +const { BrowserWindow: RemoteBrowserWindow } = remote; + +type DomResult = { + dom: Root; + didNavigateUrl: string; + didFinishLoadUrl: string; +}; + +export const loadRemoteDom = async (targetUrl: string, timeout = 0): Promise => { + const window: BrowserWindow = new RemoteBrowserWindow({ + width: 1000, + height: 600, + webPreferences: { + webSecurity: false, + nodeIntegration: false, + }, + show: false, + }); + + // eslint-disable-next-line @typescript-eslint/no-floating-promises + window.loadURL(targetUrl); + + return new Promise ((resolveWrapper) => { + let didNavigateUrl: string = null; + + window.webContents.on('did-navigate', (_event, url) => { + didNavigateUrl = url; + }); + + window.webContents.on('did-finish-load', (_event, url) => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + Promise.resolve() + .then(() => { + if (timeout > 0) { + return new Promise((resolve) => { + setTimeout(resolve, timeout); + }); + } + }) + .then(() => { + return window.webContents.executeJavaScript( + `document.querySelector('body').innerHTML` + ); + }) + .then((html) => { + const $ = cheerio.load(html); + + window.destroy(); + + resolveWrapper({ + dom: $, + didNavigateUrl: didNavigateUrl, + didFinishLoadUrl: url as string, + }); + }); + }); + }); +}; diff --git a/src/scraper/scrapeBookHighlights.spec.ts b/src/scraper/scrapeBookHighlights.spec.ts index d515752..2f98777 100644 --- a/src/scraper/scrapeBookHighlights.spec.ts +++ b/src/scraper/scrapeBookHighlights.spec.ts @@ -1,45 +1,45 @@ -import { mapTextToColor } from './scrapeBookHighlights'; - -jest.mock('electron', () => ({ - BrowserWindow: {}, - remote: {}, -})); - -describe('mapTextToColor', () => { - it('handles undefined values', () => { - expect(() => { - mapTextToColor(undefined); - }).not.toThrow(); - }); - - it('returns null when no color found', () => { - const actualColor = mapTextToColor('no-supported-color'); - expect(actualColor).toEqual(null); - }); - - describe('parses highlight colors correctly', () => { - const dataset = [ - [ - 'yellow', - 'a-row kp-notebook-highlight kp-notebook-selectable kp-notebook-highlight-yellow', - ], - [ - 'blue', - 'a-row kp-notebook-highlight kp-notebook-selectable kp-notebook-highlight-blue', - ], - [ - 'pink', - 'a-row kp-notebook-highlight kp-notebook-selectable kp-notebook-highlight-pink', - ], - [ - 'orange', - 'a-row kp-notebook-highlight kp-notebook-selectable kp-notebook-highlight-orange', - ], - ]; - - it.each(dataset)('parses %s highlights', (expectedColor, className) => { - const actualColor = mapTextToColor(className); - expect(actualColor).toEqual(expectedColor); - }); - }); -}); +import { mapTextToColor } from './scrapeBookHighlights'; + +jest.mock('electron', () => ({ + BrowserWindow: {}, + remote: {}, +})); + +describe('mapTextToColor', () => { + it('handles undefined values', () => { + expect(() => { + mapTextToColor(undefined); + }).not.toThrow(); + }); + + it('returns null when no color found', () => { + const actualColor = mapTextToColor('no-supported-color'); + expect(actualColor).toEqual(null); + }); + + describe('parses highlight colors correctly', () => { + const dataset = [ + [ + 'yellow', + 'a-row kp-notebook-highlight kp-notebook-selectable kp-notebook-highlight-yellow', + ], + [ + 'blue', + 'a-row kp-notebook-highlight kp-notebook-selectable kp-notebook-highlight-blue', + ], + [ + 'pink', + 'a-row kp-notebook-highlight kp-notebook-selectable kp-notebook-highlight-pink', + ], + [ + 'orange', + 'a-row kp-notebook-highlight kp-notebook-selectable kp-notebook-highlight-orange', + ], + ]; + + it.each(dataset)('parses %s highlights', (expectedColor, className) => { + const actualColor = mapTextToColor(className); + expect(actualColor).toEqual(expectedColor); + }); + }); +}); diff --git a/src/scraper/scrapeBookHighlights.ts b/src/scraper/scrapeBookHighlights.ts index f11e5da..d1bb866 100644 --- a/src/scraper/scrapeBookHighlights.ts +++ b/src/scraper/scrapeBookHighlights.ts @@ -1,82 +1,82 @@ -import type { Root } from 'cheerio'; - -import { currentAmazonRegion } from '~/amazonRegion'; -import type { Book, Highlight } from '~/models'; -import { br2ln, hash } from '~/utils'; - -import { loadRemoteDom } from './loadRemoteDom'; - -type NextPageState = { - token: string; - contentLimitState: string; -}; - -export const mapTextToColor = (highlightClasses: string): Highlight['color'] => { - const matches = /kp-notebook-highlight-(.*)/.exec(highlightClasses); - return matches ? (matches[1] as Highlight['color']) : null; -}; - -const highlightsUrl = (book: Book, state?: NextPageState): string => { - const region = currentAmazonRegion(); - return `${region.notebookUrl}?asin=${book.asin}&contentLimitState=${ - state?.contentLimitState ?? '' - }&token=${state?.token ?? ''}`; -}; - -const parseNextPageState = ($: Root): NextPageState | null => { - const contentLimitState = $('.kp-notebook-content-limit-state').val(); - const token = $('.kp-notebook-annotations-next-page-start').val(); - return token === undefined ? null : { contentLimitState, token }; -}; - -const parseHighlights = ($: Root): Highlight[] => { - const highlightsEl = $('.a-row.a-spacing-base').toArray(); - - return highlightsEl.map((highlightEl): Highlight => { - const pageMatch = /\d+$/.exec($('#annotationNoteHeader', highlightEl).text()); - - const highlightClasses = $('.kp-notebook-highlight', highlightEl).attr('class'); - const color = mapTextToColor(highlightClasses); - - const text = $('#highlight', highlightEl).text()?.trim(); - return { - id: hash(text), - text, - color, - location: $('#kp-annotation-location', highlightEl).val(), - page: pageMatch ? pageMatch[0] : null, - note: br2ln($('#note', highlightEl).html()), - }; - }); -}; - -const loadAndScrapeHighlights = async (book: Book, url: string) => { - const { dom } = await loadRemoteDom(url); - const nextPageState = parseNextPageState(dom); - - return { - highlights: parseHighlights(dom), - nextPageUrl: highlightsUrl(book, nextPageState), - hasNextPage: nextPageState !== null, - }; -}; - -const scrapeBookHighlights = async (book: Book): Promise => { - let results: Highlight[] = []; - - let url = highlightsUrl(book); - let hasNextPage = true; - - while (hasNextPage) { - const data = await loadAndScrapeHighlights(book, url); - - results = [...results, ...data.highlights]; - - url = data.nextPageUrl; - hasNextPage = data.hasNextPage; - } - - return results.filter((h) => h.text); -}; - -export default scrapeBookHighlights; +import type { Root } from 'cheerio'; + +import { currentAmazonRegion } from '~/amazonRegion'; +import type { Book, Highlight } from '~/models'; +import { br2ln, hash } from '~/utils'; + +import { loadRemoteDom } from './loadRemoteDom'; + +type NextPageState = { + token: string; + contentLimitState: string; +}; + +export const mapTextToColor = (highlightClasses: string): Highlight['color'] => { + const matches = /kp-notebook-highlight-(.*)/.exec(highlightClasses); + return matches ? (matches[1] as Highlight['color']) : null; +}; + +const highlightsUrl = (book: Book, state?: NextPageState): string => { + const region = currentAmazonRegion(); + return `${region.notebookUrl}?asin=${book.asin}&contentLimitState=${ + state?.contentLimitState ?? '' + }&token=${state?.token ?? ''}`; +}; + +const parseNextPageState = ($: Root): NextPageState | null => { + const contentLimitState = $('.kp-notebook-content-limit-state').val(); + const token = $('.kp-notebook-annotations-next-page-start').val(); + return token === undefined ? null : { contentLimitState, token }; +}; + +const parseHighlights = ($: Root): Highlight[] => { + const highlightsEl = $('.a-row.a-spacing-base').toArray(); + + return highlightsEl.map((highlightEl): Highlight => { + const pageMatch = /\d+$/.exec($('#annotationNoteHeader', highlightEl).text()); + + const highlightClasses = $('.kp-notebook-highlight', highlightEl).attr('class'); + const color = mapTextToColor(highlightClasses); + + const text = $('#highlight', highlightEl).text()?.trim(); + return { + id: hash(text), + text, + color, + location: $('#kp-annotation-location', highlightEl).val(), + page: pageMatch ? pageMatch[0] : null, + note: br2ln($('#note', highlightEl).html()), + }; + }); +}; + +const loadAndScrapeHighlights = async (book: Book, url: string) => { + const { dom } = await loadRemoteDom(url); + const nextPageState = parseNextPageState(dom); + + return { + highlights: parseHighlights(dom), + nextPageUrl: highlightsUrl(book, nextPageState), + hasNextPage: nextPageState !== null, + }; +}; + +const scrapeBookHighlights = async (book: Book): Promise => { + let results: Highlight[] = []; + + let url = highlightsUrl(book); + let hasNextPage = true; + + while (hasNextPage) { + const data = await loadAndScrapeHighlights(book, url); + + results = [...results, ...data.highlights]; + + url = data.nextPageUrl; + hasNextPage = data.hasNextPage; + } + + return results.filter((h) => h.text); +}; + +export default scrapeBookHighlights; diff --git a/src/scraper/scrapeBookMetadata.ts b/src/scraper/scrapeBookMetadata.ts index d0da261..b21d71c 100644 --- a/src/scraper/scrapeBookMetadata.ts +++ b/src/scraper/scrapeBookMetadata.ts @@ -1,81 +1,81 @@ -import type { Root } from 'cheerio'; - -import type { Book, BookMetadata } from '~/models'; - -import { loadRemoteDom } from './loadRemoteDom'; - -type AmazonDetailsList = { - [key: string]: string; -}; - -type PopoverData = { - inlineContent: string; -}; - -const parseDetailsList = ($: Root): Omit => { - const detailsListEl = $( - '#detailBullets_feature_div .detail-bullet-list:first-child li span.a-list-item' - ).toArray(); - - const result: AmazonDetailsList = detailsListEl.reduce((accumulator, currentEl) => { - const key = $('span:first-child', currentEl) - .text() - .replace(/[\n\r]+/g, '') - .replace(':', '') - .replace(/[^\w\s]/gi, ''); // Strip all chars except alpha numeric and spaces - - const value = $('span:nth-child(2)', currentEl).text(); - - return { ...accumulator, [key]: value }; - }, {}); - - return { - isbn: result['Page numbers source ISBN'], - pages: result['Print length'], - publicationDate: result['Publication date'], - publisher: result['Publisher'], - }; -}; - -const parseIsbn = ($: Root): string | null => { - // Attempt 1 - Try and fetch isbn from product information popover - const popoverData = $( - '#rich_product_information ol.a-carousel span[data-action=a-popover]' - ).data('a-popover') as PopoverData; - - const isbnMatches = popoverData?.inlineContent.match(/(?<=\bISBN\s)(\w+)/g); - - if (isbnMatches) { - return isbnMatches[0]; - } - - // Attempt 2 - Look for ISBN feature on page - const isbnFeature = $('#printEditionIsbn_feature_div .a-row:first-child span:nth-child(2)') - ?.text() - .trim(); - - return isbnFeature; -}; - -const parseAuthorUrl = ($: Root): string | null => { - const href = $('.contributorNameID').attr('href'); - return `https://www.amazon.com${href}`; -}; - -export const parseBookMetadata = ($: Root): BookMetadata => { - const metadata = parseDetailsList($); - - return { - ...metadata, - ...(metadata.isbn === undefined ? { isbn: parseIsbn($) } : {}), - authorUrl: parseAuthorUrl($), - }; -}; - -const scrapeBookMetadata = async (book: Book): Promise => { - const { dom } = await loadRemoteDom(`https://www.amazon.com/dp/${book.asin}`, 1000); - - return parseBookMetadata(dom); -}; - -export default scrapeBookMetadata; +import type { Root } from 'cheerio'; + +import type { Book, BookMetadata } from '~/models'; + +import { loadRemoteDom } from './loadRemoteDom'; + +type AmazonDetailsList = { + [key: string]: string; +}; + +type PopoverData = { + inlineContent: string; +}; + +const parseDetailsList = ($: Root): Omit => { + const detailsListEl = $( + '#detailBullets_feature_div .detail-bullet-list:first-child li span.a-list-item' + ).toArray(); + + const result: AmazonDetailsList = detailsListEl.reduce((accumulator, currentEl) => { + const key = $('span:first-child', currentEl) + .text() + .replace(/[\n\r]+/g, '') + .replace(':', '') + .replace(/[^\w\s]/gi, ''); // Strip all chars except alpha numeric and spaces + + const value = $('span:nth-child(2)', currentEl).text(); + + return { ...accumulator, [key]: value }; + }, {}); + + return { + isbn: result['Page numbers source ISBN'], + pages: result['Print length'], + publicationDate: result['Publication date'], + publisher: result['Publisher'], + }; +}; + +const parseIsbn = ($: Root): string | null => { + // Attempt 1 - Try and fetch isbn from product information popover + const popoverData = $( + '#rich_product_information ol.a-carousel span[data-action=a-popover]' + ).data('a-popover') as PopoverData; + + const isbnMatches = popoverData?.inlineContent.match(/(?<=\bISBN\s)(\w+)/g); + + if (isbnMatches) { + return isbnMatches[0]; + } + + // Attempt 2 - Look for ISBN feature on page + const isbnFeature = $('#printEditionIsbn_feature_div .a-row:first-child span:nth-child(2)') + ?.text() + .trim(); + + return isbnFeature; +}; + +const parseAuthorUrl = ($: Root): string | null => { + const href = $('.contributorNameID').attr('href'); + return `https://www.amazon.com${href}`; +}; + +export const parseBookMetadata = ($: Root): BookMetadata => { + const metadata = parseDetailsList($); + + return { + ...metadata, + ...(metadata.isbn === undefined ? { isbn: parseIsbn($) } : {}), + authorUrl: parseAuthorUrl($), + }; +}; + +const scrapeBookMetadata = async (book: Book): Promise => { + const { dom } = await loadRemoteDom(`https://www.amazon.com/dp/${book.asin}`, 1000); + + return parseBookMetadata(dom); +}; + +export default scrapeBookMetadata; diff --git a/src/scraper/scrapeBooks.spec.ts b/src/scraper/scrapeBooks.spec.ts index 9d5119f..b398a0e 100644 --- a/src/scraper/scrapeBooks.spec.ts +++ b/src/scraper/scrapeBooks.spec.ts @@ -1,40 +1,40 @@ -import { parseAuthor, parseToDateString } from './scrapeBooks'; - -jest.mock('electron', () => ({ - BrowserWindow: {}, - remote: {}, -})); - -describe('parseToDateString', () => { - it('Parses English last annotated date', () => { - const lastAnnotatedDate = parseToDateString('Monday November 15, 2021', 'global'); - expect(lastAnnotatedDate).toEqual(new Date(2021, 10, 15)); - }); - - it('Parses Japanese last annotated date', () => { - const lastAnnotatedDate = parseToDateString('2021年11月15日 月曜日', 'japan'); - expect(lastAnnotatedDate).toEqual(new Date(2021, 10, 15)); - }); - - it('Parses French last annotated date', () => { - const lastAnnotatedDate = parseToDateString('mardi août 30, 2022', 'france'); - expect(lastAnnotatedDate).toEqual(new Date(2022, 7, 30)); - }); -}); - -describe('parseAuthor', () => { - it('Parses scraped author (English)', () => { - const scrapedAuthor = parseAuthor('By: John Doe'); - expect(scrapedAuthor).toEqual('John Doe'); - }); - - it('Parses scraped author (French)', () => { - const scrapedAuthor = parseAuthor('Par: John Doe'); - expect(scrapedAuthor).toEqual('John Doe'); - }); - - it('Parses scraped author without a prefix (theoretical only)', () => { - const scrapedAuthor = parseAuthor('John Doe'); - expect(scrapedAuthor).toEqual('John Doe'); - }); -}); +import { parseAuthor, parseToDateString } from './scrapeBooks'; + +jest.mock('electron', () => ({ + BrowserWindow: {}, + remote: {}, +})); + +describe('parseToDateString', () => { + it('Parses English last annotated date', () => { + const lastAnnotatedDate = parseToDateString('Monday November 15, 2021', 'global'); + expect(lastAnnotatedDate).toEqual(new Date(2021, 10, 15)); + }); + + it('Parses Japanese last annotated date', () => { + const lastAnnotatedDate = parseToDateString('2021年11月15日 月曜日', 'japan'); + expect(lastAnnotatedDate).toEqual(new Date(2021, 10, 15)); + }); + + it('Parses French last annotated date', () => { + const lastAnnotatedDate = parseToDateString('mardi août 30, 2022', 'france'); + expect(lastAnnotatedDate).toEqual(new Date(2022, 7, 30)); + }); +}); + +describe('parseAuthor', () => { + it('Parses scraped author (English)', () => { + const scrapedAuthor = parseAuthor('By: John Doe'); + expect(scrapedAuthor).toEqual('John Doe'); + }); + + it('Parses scraped author (French)', () => { + const scrapedAuthor = parseAuthor('Par: John Doe'); + expect(scrapedAuthor).toEqual('John Doe'); + }); + + it('Parses scraped author without a prefix (theoretical only)', () => { + const scrapedAuthor = parseAuthor('John Doe'); + expect(scrapedAuthor).toEqual('John Doe'); + }); +}); diff --git a/src/scraper/scrapeBooks.ts b/src/scraper/scrapeBooks.ts index ebeeea8..1ac194e 100644 --- a/src/scraper/scrapeBooks.ts +++ b/src/scraper/scrapeBooks.ts @@ -34,20 +34,26 @@ export const parseAuthor = (scrapedAuthor: string): string => { }; export const parseBooks = ($: Root): Book[] => { - const booksEl = $('.kp-notebook-library-each-book').toArray(); + const booksEl = $('#kp-notebook-library > div[data-asin]').toArray(); return booksEl.map((bookEl): Book => { - const title = $('h2.kp-notebook-searchable', bookEl).text()?.trim(); + const title = $('h2.a-spacing-top-small', bookEl).text()?.trim(); + const scrapedAuthor = $('p.a-spacing-top-small', bookEl).text()?.trim(); + const scrapedLastAnnotatedDate = $( + '#kp-notebook-annotated-date', + bookEl + ) + .text() + ?.trim(); - const scrapedLastAnnotatedDate = $('[id^="kp-notebook-annotated-date"]', bookEl).val(); - const scrapedAuthor = $('p.kp-notebook-searchable', bookEl).text(); + const asin = $(bookEl).attr('data-asin'); return { id: hash(title), - asin: $(bookEl).attr('id'), + asin, title, author: parseAuthor(scrapedAuthor), - url: `https://www.amazon.com/dp/${$(bookEl).attr('id')}`, + url: `https://www.amazon.com/dp/${asin}`, imageUrl: $('.kp-notebook-cover-image', bookEl).attr('src'), lastAnnotatedDate: parseToDateString( scrapedLastAnnotatedDate, @@ -57,10 +63,8 @@ export const parseBooks = ($: Root): Book[] => { }); }; -const scrapeBooks = async (): Promise => { +export const scrapeBooks = async (): Promise => { const region = currentAmazonRegion(); const { dom } = await loadRemoteDom(region.notebookUrl, 1000); return parseBooks(dom); -}; - -export default scrapeBooks; +}; \ No newline at end of file diff --git a/src/scraper/scrapeLogoutUrl.ts b/src/scraper/scrapeLogoutUrl.ts index 5bbf022..bdb8e82 100644 --- a/src/scraper/scrapeLogoutUrl.ts +++ b/src/scraper/scrapeLogoutUrl.ts @@ -1,42 +1,42 @@ -import type { Root } from 'cheerio'; - -import { currentAmazonRegion } from '~/amazonRegion'; - -import { loadRemoteDom } from './loadRemoteDom'; - -export const parseSignoutLink = ($: Root): string => { - const signoutLinkEl = $('#settings-link-logout').attr('href'); - - if (signoutLinkEl) { - return signoutLinkEl; - } - - throw new Error('Could not parse logout link'); -}; - -type LogoutUrl = { - url: string; - isStillLoggedIn: boolean; -}; - -const scrapeLogoutUrl = async (): Promise => { - const region = currentAmazonRegion(); - const kindleReaderUrl = region.kindleReaderUrl; - - const { dom, didNavigateUrl } = await loadRemoteDom(kindleReaderUrl); - - let logoutUrl: string = null; - const isStillLoggedIn = !didNavigateUrl.contains('signin'); - - if (isStillLoggedIn) { - const signoutHrefUrl = parseSignoutLink(dom); - logoutUrl = `${kindleReaderUrl}${signoutHrefUrl}`; - } - - return { - url: logoutUrl, - isStillLoggedIn, - }; -}; - -export default scrapeLogoutUrl; +import type { Root } from 'cheerio'; + +import { currentAmazonRegion } from '~/amazonRegion'; + +import { loadRemoteDom } from './loadRemoteDom'; + +export const parseSignoutLink = ($: Root): string => { + const signoutLinkEl = $('#settings-link-logout').attr('href'); + + if (signoutLinkEl) { + return signoutLinkEl; + } + + throw new Error('Could not parse logout link'); +}; + +type LogoutUrl = { + url: string; + isStillLoggedIn: boolean; +}; + +const scrapeLogoutUrl = async (): Promise => { + const region = currentAmazonRegion(); + const kindleReaderUrl = region.kindleReaderUrl; + + const { dom, didNavigateUrl } = await loadRemoteDom(kindleReaderUrl); + + let logoutUrl: string = null; + const isStillLoggedIn = !didNavigateUrl.contains('signin'); + + if (isStillLoggedIn) { + const signoutHrefUrl = parseSignoutLink(dom); + logoutUrl = `${kindleReaderUrl}${signoutHrefUrl}`; + } + + return { + url: logoutUrl, + isStillLoggedIn, + }; +}; + +export default scrapeLogoutUrl; diff --git a/src/settings/index.ts b/src/settings/index.ts index 86f52e2..343f7f9 100644 --- a/src/settings/index.ts +++ b/src/settings/index.ts @@ -1,180 +1,180 @@ -import _ from 'lodash'; -import { App, PluginSettingTab, Setting } from 'obsidian'; -import { get } from 'svelte/store'; - -import type KindlePlugin from '~/.'; -import { AmazonRegions, orderedAmazonRegions } from '~/amazonRegion'; -import AmazonLogoutModal from '~/components/amazonLogoutModal'; -import { ee } from '~/eventEmitter'; -import type FileManager from '~/fileManager'; -import type { AmazonAccountRegion } from '~/models'; -import { scrapeLogoutUrl } from '~/scraper'; -import { settingsStore } from '~/store'; - -import TemplateEditorModal from './templateEditorModal'; - -const { moment } = window; - -type AdapterFile = { - type: 'folder' | 'file'; -}; - -export class SettingsTab extends PluginSettingTab { - constructor(app: App, plugin: KindlePlugin, private fileManager: FileManager) { - super(app, plugin); - this.app = app; - } - - public display(): void { - const { containerEl } = this; - - containerEl.empty(); - - if (get(settingsStore).isLoggedIn) { - this.logout(); - } - - this.templatesEditor(); - this.highlightsFolder(); - this.amazonRegion(); - this.downloadBookMetadata(); - this.syncOnBoot(); - this.sponsorMe(); - } - - private templatesEditor(): void { - new Setting(this.containerEl) - .setName('Templates') - .setDesc('Manage and edit templates for file names and highlight note content') - .addButton((button) => { - button - .setButtonText('Manage') - .onClick(() => { - new TemplateEditorModal(this.app).show(); - }); - }); - } - - private logout(): void { - const syncMessage = get(settingsStore).lastSyncDate - ? `Last sync ${moment(get(settingsStore).lastSyncDate).fromNow()}` - : 'Sync has never run'; - - const kindleFiles = this.fileManager.getKindleFiles(); - - const descFragment = document.createRange().createContextualFragment(` - ${kindleFiles.length} book(s) synced
- ${syncMessage} - `); - - new Setting(this.containerEl) - .setName('Logged in to Amazon Kindle Reader') - .setDesc(descFragment) - .addButton((button) => { - return button - .setButtonText('Sign out') - .setCta() - .onClick(async () => { - button.removeCta().setButtonText('Signing out...').setDisabled(true); - - ee.emit('startLogout'); - - try { - const signout = await scrapeLogoutUrl(); - - // User is still logged in - if (signout.isStillLoggedIn) { - const modal = new AmazonLogoutModal(signout.url); - await modal.doLogout(); - } - - settingsStore.actions.logout(); - } catch (error) { - console.error('Error when trying to logout', error); - ee.emit('logoutFailure'); - } - - ee.emit('logoutSuccess'); - - this.display(); // rerender - }); - }); - } - - private amazonRegion(): void { - new Setting(this.containerEl) - .setName('Amazon region') - .setDesc( - "Amazon's kindle reader is region specific. Choose your preferred country/region which has your highlights" - ) - .addDropdown((dropdown) => { - orderedAmazonRegions().forEach((region: AmazonAccountRegion) => { - const account = AmazonRegions[region]; - dropdown.addOption(region, `${account.name} (${account.hostname})`); - }); - - return dropdown - .setValue(get(settingsStore).amazonRegion) - .onChange((value: AmazonAccountRegion) => { - settingsStore.actions.setAmazonRegion(value); - }); - }); - } - - private highlightsFolder(): void { - new Setting(this.containerEl) - .setName('Highlights folder location') - .setDesc('Vault folder to use for writing book highlight notes') - .addDropdown((dropdown) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access - const files = (this.app.vault.adapter as any).files as AdapterFile[]; - const folders = _.pickBy(files, (val) => { - return val.type === 'folder'; - }); - - Object.keys(folders).forEach((val) => { - dropdown.addOption(val, val); - }); - return dropdown.setValue(get(settingsStore).highlightsFolder).onChange((value) => { - settingsStore.actions.setHighlightsFolder(value); - }); - }); - } - - private downloadBookMetadata(): void { - new Setting(this.containerEl) - .setName('Download book metadata') - .setDesc( - 'Download extra book metadata from Amazon.com (Amazon sync only). Switch off to speed sync' - ) - .addToggle((toggle) => - toggle.setValue(get(settingsStore).downloadBookMetadata).onChange((value) => { - settingsStore.actions.setDownloadBookMetadata(value); - }) - ); - } - - private syncOnBoot(): void { - new Setting(this.containerEl) - .setName('Sync on Startup') - .setDesc( - 'Automatically sync new Kindle highlights when Obsidian starts (Amazon sync only)' - ) - .addToggle((toggle) => - toggle.setValue(get(settingsStore).syncOnBoot).onChange((value) => { - settingsStore.actions.setSyncOnBoot(value); - }) - ); - } - - private sponsorMe(): void { - new Setting(this.containerEl) - .setName('Sponsor') - .setDesc( - 'Has this plugin enhanced your workflow? Say thanks as a one-time payment and buy me a coffee' - ) - .addButton((bt) => { - bt.buttonEl.outerHTML = ``; - }); - } -} +import _ from 'lodash'; +import { App, PluginSettingTab, Setting } from 'obsidian'; +import { get } from 'svelte/store'; + +import type KindlePlugin from '~/.'; +import { AmazonRegions, orderedAmazonRegions } from '~/amazonRegion'; +import AmazonLogoutModal from '~/components/amazonLogoutModal'; +import { ee } from '~/eventEmitter'; +import type FileManager from '~/fileManager'; +import type { AmazonAccountRegion } from '~/models'; +import { scrapeLogoutUrl } from '~/scraper'; +import { settingsStore } from '~/store'; + +import TemplateEditorModal from './templateEditorModal'; + +const { moment } = window; + +type AdapterFile = { + type: 'folder' | 'file'; +}; + +export class SettingsTab extends PluginSettingTab { + constructor(app: App, plugin: KindlePlugin, private fileManager: FileManager) { + super(app, plugin); + this.app = app; + } + + public display(): void { + const { containerEl } = this; + + containerEl.empty(); + + if (get(settingsStore).isLoggedIn) { + this.logout(); + } + + this.templatesEditor(); + this.highlightsFolder(); + this.amazonRegion(); + this.downloadBookMetadata(); + this.syncOnBoot(); + this.sponsorMe(); + } + + private templatesEditor(): void { + new Setting(this.containerEl) + .setName('Templates') + .setDesc('Manage and edit templates for file names and highlight note content') + .addButton((button) => { + button + .setButtonText('Manage') + .onClick(() => { + new TemplateEditorModal(this.app).show(); + }); + }); + } + + private logout(): void { + const syncMessage = get(settingsStore).lastSyncDate + ? `Last sync ${moment(get(settingsStore).lastSyncDate).fromNow()}` + : 'Sync has never run'; + + const kindleFiles = this.fileManager.getKindleFiles(); + + const descFragment = document.createRange().createContextualFragment(` + ${kindleFiles.length} book(s) synced
+ ${syncMessage} + `); + + new Setting(this.containerEl) + .setName('Logged in to Amazon Kindle Reader') + .setDesc(descFragment) + .addButton((button) => { + return button + .setButtonText('Sign out') + .setCta() + .onClick(async () => { + button.removeCta().setButtonText('Signing out...').setDisabled(true); + + ee.emit('startLogout'); + + try { + const signout = await scrapeLogoutUrl(); + + // User is still logged in + if (signout.isStillLoggedIn) { + const modal = new AmazonLogoutModal(signout.url); + await modal.doLogout(); + } + + settingsStore.actions.logout(); + } catch (error) { + console.error('Error when trying to logout', error); + ee.emit('logoutFailure'); + } + + ee.emit('logoutSuccess'); + + this.display(); // rerender + }); + }); + } + + private amazonRegion(): void { + new Setting(this.containerEl) + .setName('Amazon region') + .setDesc( + "Amazon's kindle reader is region specific. Choose your preferred country/region which has your highlights" + ) + .addDropdown((dropdown) => { + orderedAmazonRegions().forEach((region: AmazonAccountRegion) => { + const account = AmazonRegions[region]; + dropdown.addOption(region, `${account.name} (${account.hostname})`); + }); + + return dropdown + .setValue(get(settingsStore).amazonRegion) + .onChange((value: AmazonAccountRegion) => { + settingsStore.actions.setAmazonRegion(value); + }); + }); + } + + private highlightsFolder(): void { + new Setting(this.containerEl) + .setName('Highlights folder location') + .setDesc('Vault folder to use for writing book highlight notes') + .addDropdown((dropdown) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access + const files = (this.app.vault.adapter as any).files as AdapterFile[]; + const folders = _.pickBy(files, (val) => { + return val.type === 'folder'; + }); + + Object.keys(folders).forEach((val) => { + dropdown.addOption(val, val); + }); + return dropdown.setValue(get(settingsStore).highlightsFolder).onChange((value) => { + settingsStore.actions.setHighlightsFolder(value); + }); + }); + } + + private downloadBookMetadata(): void { + new Setting(this.containerEl) + .setName('Download book metadata') + .setDesc( + 'Download extra book metadata from Amazon.com (Amazon sync only). Switch off to speed sync' + ) + .addToggle((toggle) => + toggle.setValue(get(settingsStore).downloadBookMetadata).onChange((value) => { + settingsStore.actions.setDownloadBookMetadata(value); + }) + ); + } + + private syncOnBoot(): void { + new Setting(this.containerEl) + .setName('Sync on Startup') + .setDesc( + 'Automatically sync new Kindle highlights when Obsidian starts (Amazon sync only)' + ) + .addToggle((toggle) => + toggle.setValue(get(settingsStore).syncOnBoot).onChange((value) => { + settingsStore.actions.setSyncOnBoot(value); + }) + ); + } + + private sponsorMe(): void { + new Setting(this.containerEl) + .setName('Sponsor') + .setDesc( + 'Has this plugin enhanced your workflow? Say thanks as a one-time payment and buy me a coffee' + ) + .addButton((bt) => { + bt.buttonEl.outerHTML = ``; + }); + } +} diff --git a/src/settings/templateEditorModal/components/Modal/EditControls.svelte b/src/settings/templateEditorModal/components/Modal/EditControls.svelte index 97b9f6f..ffae610 100644 --- a/src/settings/templateEditorModal/components/Modal/EditControls.svelte +++ b/src/settings/templateEditorModal/components/Modal/EditControls.svelte @@ -1,37 +1,37 @@ - - -
- {#if $writableStore == null} - - {:else} - - {/if} - - -- - + + ++ {#if $writableStore == null} + + {:else} + + {/if} + + ++ + diff --git a/src/settings/templateEditorModal/components/Modal/Form.svelte b/src/settings/templateEditorModal/components/Modal/Form.svelte index 1742fd6..89325a1 100644 --- a/src/settings/templateEditorModal/components/Modal/Form.svelte +++ b/src/settings/templateEditorModal/components/Modal/Form.svelte @@ -1,104 +1,104 @@ - - -{#if $activeTab === 'file-name'} -- -{:else if $activeTab === 'file'} -- - .md --showTips('file-name')} - /> - - - -{:else if $activeTab === 'highlight'} -showTips('file')} - /> - - - -{/if} - - + + +{#if $activeTab === 'file-name'} +showTips('highlight')} - /> - + +{:else if $activeTab === 'file'} ++ + .md ++showTips('file-name')} + /> + + + +{:else if $activeTab === 'highlight'} +showTips('file')} + /> + + + +{/if} + + diff --git a/src/settings/templateEditorModal/components/Modal/Modal.svelte b/src/settings/templateEditorModal/components/Modal/Modal.svelte index b6d5967..ea0c78a 100644 --- a/src/settings/templateEditorModal/components/Modal/Modal.svelte +++ b/src/settings/templateEditorModal/components/Modal/Modal.svelte @@ -1,120 +1,120 @@ - - - -showTips('highlight')} + /> + -- - + + + +----Templates---activeTab.set('file-name')} - class="vertical-tab-nav-item" - > - File name --activeTab.set('file')} - class="vertical-tab-nav-item" - > - File content --activeTab.set('highlight')} - class="vertical-tab-nav-item" - > - Highlight ------ -- ----- ++ + diff --git a/src/settings/templateEditorModal/components/Modal/Preview.svelte b/src/settings/templateEditorModal/components/Modal/Preview.svelte index e6f9d98..744b9ea 100644 --- a/src/settings/templateEditorModal/components/Modal/Preview.svelte +++ b/src/settings/templateEditorModal/components/Modal/Preview.svelte @@ -1,73 +1,73 @@ - - -++++Templates+++activeTab.set('file-name')} + class="vertical-tab-nav-item" + > + File name ++activeTab.set('file')} + class="vertical-tab-nav-item" + > + File content ++activeTab.set('highlight')} + class="vertical-tab-nav-item" + > + Highlight ++++++ ++ +++++ -- - + + +--Live Preview
-Select a sample book- ---File name-{$renderedFileName}- -File markup-{$renderedFile}-++ + diff --git a/src/settings/templateEditorModal/components/Modal/SettingItem.svelte b/src/settings/templateEditorModal/components/Modal/SettingItem.svelte index 2fc0449..677cde6 100644 --- a/src/settings/templateEditorModal/components/Modal/SettingItem.svelte +++ b/src/settings/templateEditorModal/components/Modal/SettingItem.svelte @@ -1,25 +1,25 @@ - - -++Live Preview
+Select a sample book+ +++File name+{$renderedFileName}+ +File markup+{$renderedFile}+-- - + + +--{name}- {#if description !== ''} -{description}- {/if} -- ++ + diff --git a/src/settings/templateEditorModal/components/TipsModal/Chip.svelte b/src/settings/templateEditorModal/components/TipsModal/Chip.svelte index d65bd47..c2cee96 100644 --- a/src/settings/templateEditorModal/components/TipsModal/Chip.svelte +++ b/src/settings/templateEditorModal/components/TipsModal/Chip.svelte @@ -1,15 +1,15 @@ - - -++{name}+ {#if description !== ''} +{description}+ {/if} ++ - {`{{${title}}}`} -- - + + ++ {`{{${title}}}`} ++ + diff --git a/src/settings/templateEditorModal/components/TipsModal/CommonVariables.svelte b/src/settings/templateEditorModal/components/TipsModal/CommonVariables.svelte index b606eaa..de1faf4 100644 --- a/src/settings/templateEditorModal/components/TipsModal/CommonVariables.svelte +++ b/src/settings/templateEditorModal/components/TipsModal/CommonVariables.svelte @@ -1,40 +1,40 @@ - - -- -- Book title - short - (always set) -- -- Book title - full - (always set) -- -- Authors' names - (always set) -- -- Combined Authors' last names e.g. "Sanderson_et_al", Robin-Dominguez" - (always set) -- -- First name of first author - (always set) -- -- Last name of first author - (always set) -- -- First name of second author -- + + +- Last name of second author -+ ++ Book title - short - (always set) ++ ++ Book title - full - (always set) ++ ++ Authors' names - (always set) ++ ++ Combined Authors' last names e.g. "Sanderson_et_al", Robin-Dominguez" - (always set) ++ ++ First name of first author - (always set) ++ ++ Last name of first author - (always set) ++ ++ First name of second author ++ diff --git a/src/settings/templateEditorModal/components/TipsModal/InfoModal.ts b/src/settings/templateEditorModal/components/TipsModal/InfoModal.ts index f90e006..56b437d 100644 --- a/src/settings/templateEditorModal/components/TipsModal/InfoModal.ts +++ b/src/settings/templateEditorModal/components/TipsModal/InfoModal.ts @@ -1,32 +1,32 @@ -import { App, Modal as ObsidianModal } from 'obsidian'; - -import type { TemplateTab } from '../../types'; - -import Modal from './Modal.svelte'; - -export class InfoModal extends ObsidianModal { - private modal: Modal; - - constructor(app: App, private template: TemplateTab) { - super(app); - } - - public onOpen(): void { - const { contentEl } = this; - - this.modal = new Modal({ - target: contentEl, - props: { - template: this.template, - }, - }); - } - - public onClose(): void { - const { contentEl } = this; - - this.modal.$destroy(); - - contentEl.empty(); - } -} +import { App, Modal as ObsidianModal } from 'obsidian'; + +import type { TemplateTab } from '../../types'; + +import Modal from './Modal.svelte'; + +export class InfoModal extends ObsidianModal { + private modal: Modal; + + constructor(app: App, private template: TemplateTab) { + super(app); + } + + public onOpen(): void { + const { contentEl } = this; + + this.modal = new Modal({ + target: contentEl, + props: { + template: this.template, + }, + }); + } + + public onClose(): void { + const { contentEl } = this; + + this.modal.$destroy(); + + contentEl.empty(); + } +} diff --git a/src/settings/templateEditorModal/components/TipsModal/Modal.svelte b/src/settings/templateEditorModal/components/TipsModal/Modal.svelte index 74c2d97..3aaedeb 100644 --- a/src/settings/templateEditorModal/components/TipsModal/Modal.svelte +++ b/src/settings/templateEditorModal/components/TipsModal/Modal.svelte @@ -1,142 +1,142 @@ - - -+ Last name of second author +- {#if template === 'file-name'} -- - + + +- -
- {:else if template === 'file'} -- - - -
- {:else if template === 'highlight'} -- - -- Book ASIN -- -- Book Url on Amazon.com -- -- Book cover page Url -- -- Date of last book highlight -- -- Link to book in Kindle app -- -- ISBN -- -- Number of pages in book -- -- Publication date -- -- Name of publisher -- -- Author's page on Amazon.com -- -- Number of highlights - (always set) -- - -- Block of book highlights - (always set) -- -
- {/if} -- - -- Highlighted text- (always set) -- -- Location -- -- Page -- -- Your note annotation -- -- Highlighted color -- -- Highlight creation date. -
Use - moment's format strings - to format date e.g.- - - -- Link to highlighted text in Kindle app -+ {#if template === 'file-name'} ++ + diff --git a/src/settings/templateEditorModal/data.ts b/src/settings/templateEditorModal/data.ts index 85b71d1..3f8f562 100644 --- a/src/settings/templateEditorModal/data.ts +++ b/src/settings/templateEditorModal/data.ts @@ -1,69 +1,69 @@ -import type { BookHighlight } from '~/models'; - -const data: BookHighlight[] = [ - { - book: { - id: '1', - title: 'Animal Farm (Classics To Go)', - author: 'George Orwell', - }, - highlights: [ - { - id: '1-A', - text: 'Our labour tills the soil, our dung fertilises it, and yet there is not one of us that owns more than his bare skin', - }, - { - id: '1-B', - text: 'The pigs did not actually work, but directed and supervised the others. With their superior knowledge it was natural that they should assume the leadership', - }, - ], - }, - { - book: { - id: '2', - title: 'An Everyone Culture', - author: 'Robert Kegan and Lisa Laskow Lahey', - }, - highlights: [ - { - id: '2-A', - text: 'research shows that the single biggest cause of work burnout is not work overload, but working too long without experiencing your own personal development', - }, - { - id: '2-B', - text: 'Challenge existing processes Inspire a shared vision', - }, - { - id: '2-C', - text: 'higher level of independence, self-reliance, self-trust, and the capacity to exercise initiative', - }, - ], - }, - { - book: { - id: '3', - title: 'The Girl on the Train: A Novel', - author: 'Paula Hawkins', - }, - highlights: [ - { - id: '3-A', - text: 'I lived at number twenty-three Blenheim Road for five years, blissfully happy and utterly wretched', - }, - { - id: '3-B', - text: 'Life is not a paragraph, and death is no parenthesis', - }, - { - id: '3-C', - text: 'The street is clear—no sign of Tom or Anna—and the part of me that can’t resist a bit of drama is actually quite disappointed', - }, - { - id: '3-D', - text: 'but failure cloaked me like a mantle, it overwhelmed me, dragged me under, and I gave up hope', - }, - ], - }, -]; - -export default data; +import type { BookHighlight } from '~/models'; + +const data: BookHighlight[] = [ + { + book: { + id: '1', + title: 'Animal Farm (Classics To Go)', + author: 'George Orwell', + }, + highlights: [ + { + id: '1-A', + text: 'Our labour tills the soil, our dung fertilises it, and yet there is not one of us that owns more than his bare skin', + }, + { + id: '1-B', + text: 'The pigs did not actually work, but directed and supervised the others. With their superior knowledge it was natural that they should assume the leadership', + }, + ], + }, + { + book: { + id: '2', + title: 'An Everyone Culture', + author: 'Robert Kegan and Lisa Laskow Lahey', + }, + highlights: [ + { + id: '2-A', + text: 'research shows that the single biggest cause of work burnout is not work overload, but working too long without experiencing your own personal development', + }, + { + id: '2-B', + text: 'Challenge existing processes Inspire a shared vision', + }, + { + id: '2-C', + text: 'higher level of independence, self-reliance, self-trust, and the capacity to exercise initiative', + }, + ], + }, + { + book: { + id: '3', + title: 'The Girl on the Train: A Novel', + author: 'Paula Hawkins', + }, + highlights: [ + { + id: '3-A', + text: 'I lived at number twenty-three Blenheim Road for five years, blissfully happy and utterly wretched', + }, + { + id: '3-B', + text: 'Life is not a paragraph, and death is no parenthesis', + }, + { + id: '3-C', + text: 'The street is clear—no sign of Tom or Anna—and the part of me that can’t resist a bit of drama is actually quite disappointed', + }, + { + id: '3-D', + text: 'but failure cloaked me like a mantle, it overwhelmed me, dragged me under, and I gave up hope', + }, + ], + }, +]; + +export default data; diff --git a/src/settings/templateEditorModal/index.ts b/src/settings/templateEditorModal/index.ts index e564b08..30a5d24 100644 --- a/src/settings/templateEditorModal/index.ts +++ b/src/settings/templateEditorModal/index.ts @@ -1,80 +1,80 @@ -import { remote } from 'electron'; -import { App, Modal as ObsidianModal } from 'obsidian'; -import { get } from 'svelte/store'; - -import { settingsStore } from '~/store'; - -import Modal from './components/Modal/Modal.svelte'; -import { InfoModal } from './components/TipsModal/InfoModal'; -import store, { TemplateEditorModalStore } from './store'; -import type { TemplateTab } from './types'; - -const { dialog } = remote; - -const showUnsavedChangesWarningDialog = async () => { - const result = await dialog.showMessageBox(remote.getCurrentWindow(), { - title: 'Unsaved changes', - message: - 'Are you sure you want to close the template editor without saving? Your changes will be lost.', - type: 'warning', - buttons: ['Discard', 'Cancel'], - }); - - return result.response === 0 ? 'discard' : 'cancel'; -}; - -export default class TemplateEditorModal extends ObsidianModal { - private modalContent: Modal; - private modalStore: TemplateEditorModalStore; - - constructor(app: App) { - super(app); - this.modalStore = store(); - } - - public show(): void { - this.modalContent = new Modal({ - target: this.contentEl, - props: { - store: this.modalStore, - showTips: (template: TemplateTab) => { - new InfoModal(this.app, template).open(); - }, - onSave: () => { - const newFileName = get(this.modalStore.fileNameTemplateField); - const newFileTemplateField = get(this.modalStore.fileTemplateField); - const newHighlightTemplateField = get(this.modalStore.highlightTemplateField); - - settingsStore.actions.setFileNameTemplate(newFileName); - settingsStore.actions.setFileTemplate(newFileTemplateField); - settingsStore.actions.setHighlightTemplate(newHighlightTemplateField); - - // Show success message - }, - onClose: async () => { - const isDirty = get(this.modalStore.isDirty); - - if (isDirty) { - const result = await showUnsavedChangesWarningDialog(); - if (result === 'cancel') { - return; - } - } - - this.close(); - }, - }, - }); - - this.modalEl.classList.add('mod-settings', 'mod-sidebar-layout'); - this.modalEl.style.width = '85vw'; - this.modalEl.style.height = '60vw'; - - this.open(); - } - - onClose(): void { - super.onClose(); - this.modalContent.$destroy(); - } -} +import { remote } from 'electron'; +import { App, Modal as ObsidianModal } from 'obsidian'; +import { get } from 'svelte/store'; + +import { settingsStore } from '~/store'; + +import Modal from './components/Modal/Modal.svelte'; +import { InfoModal } from './components/TipsModal/InfoModal'; +import store, { TemplateEditorModalStore } from './store'; +import type { TemplateTab } from './types'; + +const { dialog } = remote; + +const showUnsavedChangesWarningDialog = async () => { + const result = await dialog.showMessageBox(remote.getCurrentWindow(), { + title: 'Unsaved changes', + message: + 'Are you sure you want to close the template editor without saving? Your changes will be lost.', + type: 'warning', + buttons: ['Discard', 'Cancel'], + }); + + return result.response === 0 ? 'discard' : 'cancel'; +}; + +export default class TemplateEditorModal extends ObsidianModal { + private modalContent: Modal; + private modalStore: TemplateEditorModalStore; + + constructor(app: App) { + super(app); + this.modalStore = store(); + } + + public show(): void { + this.modalContent = new Modal({ + target: this.contentEl, + props: { + store: this.modalStore, + showTips: (template: TemplateTab) => { + new InfoModal(this.app, template).open(); + }, + onSave: () => { + const newFileName = get(this.modalStore.fileNameTemplateField); + const newFileTemplateField = get(this.modalStore.fileTemplateField); + const newHighlightTemplateField = get(this.modalStore.highlightTemplateField); + + settingsStore.actions.setFileNameTemplate(newFileName); + settingsStore.actions.setFileTemplate(newFileTemplateField); + settingsStore.actions.setHighlightTemplate(newHighlightTemplateField); + + // Show success message + }, + onClose: async () => { + const isDirty = get(this.modalStore.isDirty); + + if (isDirty) { + const result = await showUnsavedChangesWarningDialog(); + if (result === 'cancel') { + return; + } + } + + this.close(); + }, + }, + }); + + this.modalEl.classList.add('mod-settings', 'mod-sidebar-layout'); + this.modalEl.style.width = '85vw'; + this.modalEl.style.height = '60vw'; + + this.open(); + } + + onClose(): void { + super.onClose(); + this.modalContent.$destroy(); + } +} diff --git a/src/settings/templateEditorModal/store.ts b/src/settings/templateEditorModal/store.ts index f970ac1..5fbcc7e 100644 --- a/src/settings/templateEditorModal/store.ts +++ b/src/settings/templateEditorModal/store.ts @@ -1,138 +1,138 @@ -import { derived, get, Readable, readable, Writable, writable } from 'svelte/store'; - -import type { BookHighlight } from '~/models'; -import { - DefaultFileNameTemplate, - DefaultFileTemplate, - DefaultHighlightTemplate, - getRenderers, -} from '~/rendering'; -import { FileNameRenderer, FileRenderer } from '~/rendering/renderer'; -import { settingsStore } from '~/store/settingsStore'; - -import data from './data'; -import type { TemplateTab } from './types'; - -const { fileNameRenderer, fileRenderer, highlightRenderer } = getRenderers(); - -const InvalidRender = 'not valid'; - -export type TemplateEditorModalStore = { - activeTab: Writable+ +
+ {:else if template === 'file'} ++ + + +
+ {:else if template === 'highlight'} ++ + ++ Book ASIN ++ ++ Book Url on Amazon.com ++ ++ Book cover page Url ++ ++ Date of last book highlight ++ ++ Link to book in Kindle app ++ ++ ISBN ++ ++ Number of pages in book ++ ++ Publication date ++ ++ Name of publisher ++ ++ Author's page on Amazon.com ++ ++ Number of highlights - (always set) ++ + ++ Block of book highlights - (always set) ++ +
+ {/if} ++ + ++ Highlighted text- (always set) ++ ++ Location ++ ++ Page ++ ++ Your note annotation ++ ++ Highlighted color ++ ++ Highlight creation date. +
Use + moment's format strings + to format date e.g.+ + + ++ Link to highlighted text in Kindle app +; - demoBooks: Readable ; - selectedBook: Writable ; - isDirty: Readable ; - fileNameTemplateField: Writable ; - fileNameTemplateFieldHasError: Writable ; - fileTemplateField: Writable ; - fileTemplateFieldHasError: Writable ; - highlightTemplateField: Writable ; - highlightTemplateFieldHasError: Writable ; - renderedFileName: Readable ; - renderedFile: Readable ; - hasErrors: Readable ; -}; - -export default (): TemplateEditorModalStore => { - const selectedBook = writable(data[0]); - - const fileNameTemplateField = writable(get(settingsStore).fileNameTemplate); - const fileNameTemplateFieldHasError = writable(false); - - const fileTemplateField = writable(get(settingsStore).fileTemplate); - const fileTemplateFieldHasError = writable(false); - - const highlightTemplateField = writable(get(settingsStore).highlightTemplate); - const highlightTemplateFieldHasError = writable(false); - - const renderedFileName = derived( - [selectedBook, fileNameTemplateField], - ([$selectedBook, $fileNameTemplateField]) => { - const fileNameTemplate = $fileNameTemplateField || DefaultFileNameTemplate; - try { - const renderer = new FileNameRenderer(fileNameTemplate); - return renderer.render($selectedBook.book); - } catch (error) { - return InvalidRender; - } - } - ); - - const renderedFile = derived( - [selectedBook, fileTemplateField, highlightTemplateField], - ([$selectedBook, $fileTemplateField, $highlightTemplateField]) => { - const fileTemplate = $fileTemplateField || DefaultFileTemplate; - const highlightTemplate = $highlightTemplateField || DefaultHighlightTemplate; - - try { - const renderer = new FileRenderer(fileTemplate, highlightTemplate); - return renderer.render($selectedBook); - } catch (error) { - return InvalidRender; - } - } - ); - - const isDirty = derived( - [fileNameTemplateField, fileTemplateField, highlightTemplateField, settingsStore.store], - ([ - $fileNameTemplateField, - $fileTemplateField, - $highlightTemplateField, - $settingsStore, - ]) => { - const { fileNameTemplate, fileTemplate, highlightTemplate } = $settingsStore; - return ( - fileNameTemplate !== $fileNameTemplateField || - fileTemplate !== $fileTemplateField || - highlightTemplate !== $highlightTemplateField - ); - } - ); - - fileNameTemplateField.subscribe((value) => { - const isValid = fileNameRenderer.validate(value); - fileNameTemplateFieldHasError.set(!isValid); - }); - - fileTemplateField.subscribe((value) => { - const isValid = fileRenderer.validate(value); - fileTemplateFieldHasError.set(!isValid); - }); - - highlightTemplateField.subscribe((value) => { - const isValid = highlightRenderer.validate(value); - highlightTemplateFieldHasError.set(!isValid); - }); - - const hasErrors = derived( - [fileNameTemplateFieldHasError, fileTemplateFieldHasError, highlightTemplateFieldHasError], - ([ - $fileNameTemplateFieldHasError, - $fileTemplateFieldHasError, - $highlightTemplateFieldHasError, - ]) => { - return ( - $fileNameTemplateFieldHasError || - $fileTemplateFieldHasError || - $highlightTemplateFieldHasError - ); - } - ); - - return { - activeTab: writable ('file-name'), - demoBooks: readable(data), - selectedBook, - isDirty, - fileNameTemplateField, - fileNameTemplateFieldHasError, - fileTemplateField, - fileTemplateFieldHasError, - highlightTemplateField, - highlightTemplateFieldHasError, - renderedFileName, - renderedFile, - hasErrors, - }; -}; +import { derived, get, Readable, readable, Writable, writable } from 'svelte/store'; + +import type { BookHighlight } from '~/models'; +import { + DefaultFileNameTemplate, + DefaultFileTemplate, + DefaultHighlightTemplate, + getRenderers, +} from '~/rendering'; +import { FileNameRenderer, FileRenderer } from '~/rendering/renderer'; +import { settingsStore } from '~/store/settingsStore'; + +import data from './data'; +import type { TemplateTab } from './types'; + +const { fileNameRenderer, fileRenderer, highlightRenderer } = getRenderers(); + +const InvalidRender = 'not valid'; + +export type TemplateEditorModalStore = { + activeTab: Writable ; + demoBooks: Readable ; + selectedBook: Writable ; + isDirty: Readable ; + fileNameTemplateField: Writable ; + fileNameTemplateFieldHasError: Writable ; + fileTemplateField: Writable ; + fileTemplateFieldHasError: Writable ; + highlightTemplateField: Writable ; + highlightTemplateFieldHasError: Writable ; + renderedFileName: Readable ; + renderedFile: Readable ; + hasErrors: Readable ; +}; + +export default (): TemplateEditorModalStore => { + const selectedBook = writable(data[0]); + + const fileNameTemplateField = writable(get(settingsStore).fileNameTemplate); + const fileNameTemplateFieldHasError = writable(false); + + const fileTemplateField = writable(get(settingsStore).fileTemplate); + const fileTemplateFieldHasError = writable(false); + + const highlightTemplateField = writable(get(settingsStore).highlightTemplate); + const highlightTemplateFieldHasError = writable(false); + + const renderedFileName = derived( + [selectedBook, fileNameTemplateField], + ([$selectedBook, $fileNameTemplateField]) => { + const fileNameTemplate = $fileNameTemplateField || DefaultFileNameTemplate; + try { + const renderer = new FileNameRenderer(fileNameTemplate); + return renderer.render($selectedBook.book); + } catch (error) { + return InvalidRender; + } + } + ); + + const renderedFile = derived( + [selectedBook, fileTemplateField, highlightTemplateField], + ([$selectedBook, $fileTemplateField, $highlightTemplateField]) => { + const fileTemplate = $fileTemplateField || DefaultFileTemplate; + const highlightTemplate = $highlightTemplateField || DefaultHighlightTemplate; + + try { + const renderer = new FileRenderer(fileTemplate, highlightTemplate); + return renderer.render($selectedBook); + } catch (error) { + return InvalidRender; + } + } + ); + + const isDirty = derived( + [fileNameTemplateField, fileTemplateField, highlightTemplateField, settingsStore.store], + ([ + $fileNameTemplateField, + $fileTemplateField, + $highlightTemplateField, + $settingsStore, + ]) => { + const { fileNameTemplate, fileTemplate, highlightTemplate } = $settingsStore; + return ( + fileNameTemplate !== $fileNameTemplateField || + fileTemplate !== $fileTemplateField || + highlightTemplate !== $highlightTemplateField + ); + } + ); + + fileNameTemplateField.subscribe((value) => { + const isValid = fileNameRenderer.validate(value); + fileNameTemplateFieldHasError.set(!isValid); + }); + + fileTemplateField.subscribe((value) => { + const isValid = fileRenderer.validate(value); + fileTemplateFieldHasError.set(!isValid); + }); + + highlightTemplateField.subscribe((value) => { + const isValid = highlightRenderer.validate(value); + highlightTemplateFieldHasError.set(!isValid); + }); + + const hasErrors = derived( + [fileNameTemplateFieldHasError, fileTemplateFieldHasError, highlightTemplateFieldHasError], + ([ + $fileNameTemplateFieldHasError, + $fileTemplateFieldHasError, + $highlightTemplateFieldHasError, + ]) => { + return ( + $fileNameTemplateFieldHasError || + $fileTemplateFieldHasError || + $highlightTemplateFieldHasError + ); + } + ); + + return { + activeTab: writable ('file-name'), + demoBooks: readable(data), + selectedBook, + isDirty, + fileNameTemplateField, + fileNameTemplateFieldHasError, + fileTemplateField, + fileTemplateFieldHasError, + highlightTemplateField, + highlightTemplateFieldHasError, + renderedFileName, + renderedFile, + hasErrors, + }; +}; diff --git a/src/settings/templateEditorModal/types.ts b/src/settings/templateEditorModal/types.ts index 8f8516d..6276ad2 100644 --- a/src/settings/templateEditorModal/types.ts +++ b/src/settings/templateEditorModal/types.ts @@ -1 +1 @@ -export type TemplateTab = 'file' | 'file-name' | 'highlight'; +export type TemplateTab = 'file' | 'file-name' | 'highlight'; diff --git a/src/store/fileStore.ts b/src/store/fileStore.ts index 4b8c627..38bb51a 100644 --- a/src/store/fileStore.ts +++ b/src/store/fileStore.ts @@ -1,50 +1,50 @@ -import _ from 'lodash'; -import { readable } from 'svelte/store'; - -import { ee } from '~/eventEmitter'; -import type FileManager from '~/fileManager'; - -type FileStoreState = { - fileCount: number; - highlightCount: number; -}; - -const INITIAL_STATE: FileStoreState = { - fileCount: 0, - highlightCount: 0, -}; - -const createFileStore = () => { - let _fileManager: FileManager; - - const initialize = (fileManager: FileManager): void => { - _fileManager = fileManager; - }; - - const store = readable(INITIAL_STATE, (set) => { - const updateFileCount = () => { - const files = _fileManager.getKindleFiles(); - set({ - fileCount: files.length, - highlightCount: _.sumBy(files, (file) => file.frontmatter?.highlightsCount), - }); - }; - - // Initial seed when Obsidian is loaded - updateFileCount(); - - ee.on('obsidianReady', updateFileCount); - - // Delay fetching of latest count to give Obsidian time to cache newly created file - ee.on('syncBookSuccess', () => { - window.setTimeout(updateFileCount, 500); - }); - }); - - return { - subscribe: store.subscribe, - initialize, - }; -}; - -export const fileStore = createFileStore(); +import _ from 'lodash'; +import { readable } from 'svelte/store'; + +import { ee } from '~/eventEmitter'; +import type FileManager from '~/fileManager'; + +type FileStoreState = { + fileCount: number; + highlightCount: number; +}; + +const INITIAL_STATE: FileStoreState = { + fileCount: 0, + highlightCount: 0, +}; + +const createFileStore = () => { + let _fileManager: FileManager; + + const initialize = (fileManager: FileManager): void => { + _fileManager = fileManager; + }; + + const store = readable(INITIAL_STATE, (set) => { + const updateFileCount = () => { + const files = _fileManager.getKindleFiles(); + set({ + fileCount: files.length, + highlightCount: _.sumBy(files, (file) => file.frontmatter?.highlightsCount), + }); + }; + + // Initial seed when Obsidian is loaded + updateFileCount(); + + ee.on('obsidianReady', updateFileCount); + + // Delay fetching of latest count to give Obsidian time to cache newly created file + ee.on('syncBookSuccess', () => { + window.setTimeout(updateFileCount, 500); + }); + }); + + return { + subscribe: store.subscribe, + initialize, + }; +}; + +export const fileStore = createFileStore(); diff --git a/src/store/index.ts b/src/store/index.ts index 36e295b..180557e 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,15 +1,15 @@ -import type KindlePlugin from '~/.'; -import type FileManager from '~/fileManager'; - -import { fileStore } from './fileStore'; -import { settingsStore } from './settingsStore'; - -const initializeStores = async ( - plugin: KindlePlugin, - fileManager: FileManager -): Promise => { - await settingsStore.initialize(plugin); - fileStore.initialize(fileManager); -}; - -export { initializeStores, fileStore, settingsStore }; +import type KindlePlugin from '~/.'; +import type FileManager from '~/fileManager'; + +import { fileStore } from './fileStore'; +import { settingsStore } from './settingsStore'; + +const initializeStores = async ( + plugin: KindlePlugin, + fileManager: FileManager +): Promise => { + await settingsStore.initialize(plugin); + fileStore.initialize(fileManager); +}; + +export { initializeStores, fileStore, settingsStore }; diff --git a/src/store/settingsStore.ts b/src/store/settingsStore.ts index 96ec416..0bdfc4a 100644 --- a/src/store/settingsStore.ts +++ b/src/store/settingsStore.ts @@ -1,180 +1,180 @@ -import { writable } from 'svelte/store'; - -import type KindlePlugin from '~/.'; -import { ee } from '~/eventEmitter'; -import type { AmazonAccountRegion, SyncMode } from '~/models'; - -type Settings = { - amazonRegion: AmazonAccountRegion; - highlightsFolder: string; - lastSyncDate?: Date; - lastSyncMode: SyncMode; - isLoggedIn: boolean; - fileTemplate?: string; - highlightTemplate?: string; - fileNameTemplate?: string; - syncOnBoot: boolean; - downloadBookMetadata: boolean; - - // Deprecated - delete eventually - noteTemplate?: string; - history?: string; -}; - -const DEFAULT_SETTINGS: Settings = { - amazonRegion: 'global', - highlightsFolder: '/', - lastSyncMode: 'amazon', - isLoggedIn: false, - syncOnBoot: false, - downloadBookMetadata: true, -}; - -const createSettingsStore = () => { - const store = writable(DEFAULT_SETTINGS); - - let _plugin!: KindlePlugin; - - // Load settings data from disk into store - const initialize = async (plugin: KindlePlugin): Promise => { - const data = Object.assign({}, DEFAULT_SETTINGS, await plugin.loadData()) as Settings; - - const settings: Settings = { - ...data, - lastSyncDate: data.lastSyncDate ? new Date(data.lastSyncDate) : undefined, - }; - - store.set(settings); - - _plugin = plugin; - }; - - ee.on('resyncComplete', () => { - store.update((state) => { - state.lastSyncDate = new Date(); - return state; - }); - }); - - ee.on('syncSessionStart', (mode) => { - store.update((state) => { - state.lastSyncMode = mode; - return state; - }); - }); - - ee.on('syncSessionSuccess', () => { - store.update((state) => { - state.lastSyncDate = new Date(); - return state; - }); - }); - - // Listen to any change to store, and write to disk - store.subscribe((settings) => { - if (_plugin) { - // Transform settings fields for serialization - const data = { - ...settings, - lastSyncDate: settings.lastSyncDate ? settings.lastSyncDate.toJSON() : undefined, - }; - - _plugin - .saveData(data) - .catch((err) => console.error(`Error saving settings: ${String(err)}`)); - } - }); - - const isLegacy = async () => { - const data = Object.assign({}, DEFAULT_SETTINGS, await _plugin.loadData()) as Settings; - return data.history != null; - }; - - const upgradeStoreState = async () => { - const data = Object.assign({}, DEFAULT_SETTINGS, await _plugin.loadData()) as Settings; - - // Remove deprecated settings field - delete data.noteTemplate; - delete data.history; - - await _plugin.saveData(data); - }; - - const setHighlightsFolder = (value: string) => { - store.update((state) => { - state.highlightsFolder = value; - return state; - }); - }; - - const login = () => { - store.update((state) => { - state.isLoggedIn = true; - return state; - }); - }; - - const logout = () => { - store.update((state) => { - state.isLoggedIn = false; - return state; - }); - }; - - const setHighlightTemplate = (value: string) => { - store.update((state) => { - state.highlightTemplate = value; - return state; - }); - }; - - const setFileTemplate = (value: string) => { - store.update((state) => ({ ...state, fileTemplate: value })); - }; - - const setFileNameTemplate = (value: string) => { - store.update((state) => ({ ...state, fileNameTemplate: value })); - }; - - const setSyncOnBoot = (value: boolean) => { - store.update((state) => { - state.syncOnBoot = value; - return state; - }); - }; - - const setDownloadBookMetadata = (value: boolean) => { - store.update((state) => { - state.downloadBookMetadata = value; - return state; - }); - }; - - const setAmazonRegion = (value: AmazonAccountRegion) => { - store.update((state) => { - state.amazonRegion = value; - return state; - }); - }; - - return { - store, - subscribe: store.subscribe, - initialize, - isLegacy, - actions: { - setHighlightsFolder, - login, - logout, - setFileTemplate, - setFileNameTemplate, - setHighlightTemplate, - setSyncOnBoot, - setDownloadBookMetadata, - setAmazonRegion, - upgradeStoreState, - }, - }; -}; - -export const settingsStore = createSettingsStore(); +import { writable } from 'svelte/store'; + +import type KindlePlugin from '~/.'; +import { ee } from '~/eventEmitter'; +import type { AmazonAccountRegion, SyncMode } from '~/models'; + +type Settings = { + amazonRegion: AmazonAccountRegion; + highlightsFolder: string; + lastSyncDate?: Date; + lastSyncMode: SyncMode; + isLoggedIn: boolean; + fileTemplate?: string; + highlightTemplate?: string; + fileNameTemplate?: string; + syncOnBoot: boolean; + downloadBookMetadata: boolean; + + // Deprecated - delete eventually + noteTemplate?: string; + history?: string; +}; + +const DEFAULT_SETTINGS: Settings = { + amazonRegion: 'global', + highlightsFolder: '/', + lastSyncMode: 'amazon', + isLoggedIn: false, + syncOnBoot: false, + downloadBookMetadata: true, +}; + +const createSettingsStore = () => { + const store = writable(DEFAULT_SETTINGS); + + let _plugin!: KindlePlugin; + + // Load settings data from disk into store + const initialize = async (plugin: KindlePlugin): Promise => { + const data = Object.assign({}, DEFAULT_SETTINGS, await plugin.loadData()) as Settings; + + const settings: Settings = { + ...data, + lastSyncDate: data.lastSyncDate ? new Date(data.lastSyncDate) : undefined, + }; + + store.set(settings); + + _plugin = plugin; + }; + + ee.on('resyncComplete', () => { + store.update((state) => { + state.lastSyncDate = new Date(); + return state; + }); + }); + + ee.on('syncSessionStart', (mode) => { + store.update((state) => { + state.lastSyncMode = mode; + return state; + }); + }); + + ee.on('syncSessionSuccess', () => { + store.update((state) => { + state.lastSyncDate = new Date(); + return state; + }); + }); + + // Listen to any change to store, and write to disk + store.subscribe((settings) => { + if (_plugin) { + // Transform settings fields for serialization + const data = { + ...settings, + lastSyncDate: settings.lastSyncDate ? settings.lastSyncDate.toJSON() : undefined, + }; + + _plugin + .saveData(data) + .catch((err) => console.error(`Error saving settings: ${String(err)}`)); + } + }); + + const isLegacy = async () => { + const data = Object.assign({}, DEFAULT_SETTINGS, await _plugin.loadData()) as Settings; + return data.history != null; + }; + + const upgradeStoreState = async () => { + const data = Object.assign({}, DEFAULT_SETTINGS, await _plugin.loadData()) as Settings; + + // Remove deprecated settings field + delete data.noteTemplate; + delete data.history; + + await _plugin.saveData(data); + }; + + const setHighlightsFolder = (value: string) => { + store.update((state) => { + state.highlightsFolder = value; + return state; + }); + }; + + const login = () => { + store.update((state) => { + state.isLoggedIn = true; + return state; + }); + }; + + const logout = () => { + store.update((state) => { + state.isLoggedIn = false; + return state; + }); + }; + + const setHighlightTemplate = (value: string) => { + store.update((state) => { + state.highlightTemplate = value; + return state; + }); + }; + + const setFileTemplate = (value: string) => { + store.update((state) => ({ ...state, fileTemplate: value })); + }; + + const setFileNameTemplate = (value: string) => { + store.update((state) => ({ ...state, fileNameTemplate: value })); + }; + + const setSyncOnBoot = (value: boolean) => { + store.update((state) => { + state.syncOnBoot = value; + return state; + }); + }; + + const setDownloadBookMetadata = (value: boolean) => { + store.update((state) => { + state.downloadBookMetadata = value; + return state; + }); + }; + + const setAmazonRegion = (value: AmazonAccountRegion) => { + store.update((state) => { + state.amazonRegion = value; + return state; + }); + }; + + return { + store, + subscribe: store.subscribe, + initialize, + isLegacy, + actions: { + setHighlightsFolder, + login, + logout, + setFileTemplate, + setFileNameTemplate, + setHighlightTemplate, + setSyncOnBoot, + setDownloadBookMetadata, + setAmazonRegion, + upgradeStoreState, + }, + }; +}; + +export const settingsStore = createSettingsStore(); diff --git a/src/sync/diffManager/helpers.ts b/src/sync/diffManager/helpers.ts index 0b69052..4f0eea8 100644 --- a/src/sync/diffManager/helpers.ts +++ b/src/sync/diffManager/helpers.ts @@ -1,54 +1,54 @@ -import _ from 'lodash'; - -import type { Highlight } from '~/models'; - -import type { DiffResult, RenderedHighlight } from './'; - -type DiffIndex = { - highlight: Highlight; - exists: boolean; -}; - -const getNextNeighbour = (state: Map , needle: string): Highlight => { - const keys = Array.from(state.keys()); - const needleIndex = keys.indexOf(needle); - - let next: Highlight = null; - - for (let i = needleIndex + 1; i < keys.length; i++) { - const diffIndex = state.get(keys[i]); - if (diffIndex.exists) { - next = diffIndex.highlight; - break; - } - } - - return next; -}; - -export const diffLists = ( - remotes: Highlight[], - renders: RenderedHighlight[] -): DiffResult[] => { - /** - * Array of remote highlights that have not been rendered - */ - const diff = _.differenceWith(remotes, renders, (a, b) => a.id === b.highlightId); - - /** - * Map every remote highlight id to where it exists (in render) - * Use an ES6 Map to ensure key orders are preserved - */ - const syncState = new Map (); - remotes.forEach((r) => syncState.set(r.id, { highlight: r, exists: !diff.contains(r) })); - - return diff.map((remote): DiffResult => { - const next = getNextNeighbour(syncState, remote.id); - const nextRendered = renders.find((r) => r.highlightId === next?.id); - - return { - remoteHighlight: remote, - nextRenderedHighlight: nextRendered, - }; - }); -}; +import _ from 'lodash'; + +import type { Highlight } from '~/models'; + +import type { DiffResult, RenderedHighlight } from './'; + +type DiffIndex = { + highlight: Highlight; + exists: boolean; +}; + +const getNextNeighbour = (state: Map , needle: string): Highlight => { + const keys = Array.from(state.keys()); + const needleIndex = keys.indexOf(needle); + + let next: Highlight = null; + + for (let i = needleIndex + 1; i < keys.length; i++) { + const diffIndex = state.get(keys[i]); + if (diffIndex.exists) { + next = diffIndex.highlight; + break; + } + } + + return next; +}; + +export const diffLists = ( + remotes: Highlight[], + renders: RenderedHighlight[] +): DiffResult[] => { + /** + * Array of remote highlights that have not been rendered + */ + const diff = _.differenceWith(remotes, renders, (a, b) => a.id === b.highlightId); + + /** + * Map every remote highlight id to where it exists (in render) + * Use an ES6 Map to ensure key orders are preserved + */ + const syncState = new Map (); + remotes.forEach((r) => syncState.set(r.id, { highlight: r, exists: !diff.contains(r) })); + + return diff.map((remote): DiffResult => { + const next = getNextNeighbour(syncState, remote.id); + const nextRendered = renders.find((r) => r.highlightId === next?.id); + + return { + remoteHighlight: remote, + nextRenderedHighlight: nextRendered, + }; + }); +}; diff --git a/src/sync/diffManager/index.ts b/src/sync/diffManager/index.ts index 9a6add4..ae03b1e 100644 --- a/src/sync/diffManager/index.ts +++ b/src/sync/diffManager/index.ts @@ -1,91 +1,91 @@ -import _ from 'lodash'; - -import type FileManager from '~/fileManager'; -import type { Highlight } from '~/models'; -import type { Book, KindleFile } from '~/models'; -import { getRenderers } from '~/rendering'; -import { HighlightIdBlockRefPrefix } from '~/rendering/renderer'; -import { sb, StringBuffer } from '~/utils'; - -import { diffLists } from './helpers'; - -export type RenderedHighlight = { - line: number; - highlightId: string; -}; - -export type DiffResult = { - remoteHighlight: Highlight; - nextRenderedHighlight?: RenderedHighlight; -}; - -export class DiffManager { - private fileBuffer: StringBuffer; - - public static async create( - fileManager: FileManager, - kindleFile: KindleFile - ): Promise { - const manager = new DiffManager(fileManager, kindleFile); - await manager.load(); - return manager; - } - - private constructor(private fileManager: FileManager, private kindleFile: KindleFile) {} - - private async load(): Promise { - const fileContents = await this.fileManager.readFile(this.kindleFile); - this.fileBuffer = sb(fileContents); - } - - public diff(remoteHighlights: Highlight[]): DiffResult[] { - const renderedHighlights = this.parseRenderedHighlights(); - return diffLists(remoteHighlights, renderedHighlights); - } - - private parseRenderedHighlights(): RenderedHighlight[] { - const needle = _.escapeRegExp(HighlightIdBlockRefPrefix); - const endsWithRegex = new RegExp(`.*(${needle}.*)$`); - - return this.fileBuffer - .match(endsWithRegex) - .filter((lem) => lem.match != null) - .map((lem) => { - return { - line: lem.line, - highlightId: lem.match[1].replace(HighlightIdBlockRefPrefix, ''), - }; - }); - } - - public async applyDiffs( - remoteBook: Book, - remoteHighlights: Highlight[], - diffs: DiffResult[] - ): Promise { - const highlightRenderer = getRenderers().highlightRenderer; - - const insertList = diffs - .filter((d) => d.nextRenderedHighlight) - .map((d) => ({ - line: d.nextRenderedHighlight?.line, - content: highlightRenderer.render(d.remoteHighlight, this.kindleFile.book), - })); - - const appendList = diffs - .filter((d) => d.nextRenderedHighlight == null) - .map((d) => highlightRenderer.render(d.remoteHighlight, this.kindleFile.book)); - - const modifiedFileContents = this.fileBuffer - .insertLinesAt(insertList) - .append(appendList) - .toString(); - - await this.fileManager.updateFile( - this.kindleFile, - remoteBook, - modifiedFileContents, - remoteHighlights.length - ); - } -} +import _ from 'lodash'; + +import type FileManager from '~/fileManager'; +import type { Highlight } from '~/models'; +import type { Book, KindleFile } from '~/models'; +import { getRenderers } from '~/rendering'; +import { HighlightIdBlockRefPrefix } from '~/rendering/renderer'; +import { sb, StringBuffer } from '~/utils'; + +import { diffLists } from './helpers'; + +export type RenderedHighlight = { + line: number; + highlightId: string; +}; + +export type DiffResult = { + remoteHighlight: Highlight; + nextRenderedHighlight?: RenderedHighlight; +}; + +export class DiffManager { + private fileBuffer: StringBuffer; + + public static async create( + fileManager: FileManager, + kindleFile: KindleFile + ): Promise { + const manager = new DiffManager(fileManager, kindleFile); + await manager.load(); + return manager; + } + + private constructor(private fileManager: FileManager, private kindleFile: KindleFile) {} + + private async load(): Promise { + const fileContents = await this.fileManager.readFile(this.kindleFile); + this.fileBuffer = sb(fileContents); + } + + public diff(remoteHighlights: Highlight[]): DiffResult[] { + const renderedHighlights = this.parseRenderedHighlights(); + return diffLists(remoteHighlights, renderedHighlights); + } + + private parseRenderedHighlights(): RenderedHighlight[] { + const needle = _.escapeRegExp(HighlightIdBlockRefPrefix); + const endsWithRegex = new RegExp(`.*(${needle}.*)$`); + + return this.fileBuffer + .match(endsWithRegex) + .filter((lem) => lem.match != null) + .map((lem) => { + return { + line: lem.line, + highlightId: lem.match[1].replace(HighlightIdBlockRefPrefix, ''), + }; + }); + } + + public async applyDiffs( + remoteBook: Book, + remoteHighlights: Highlight[], + diffs: DiffResult[] + ): Promise { + const highlightRenderer = getRenderers().highlightRenderer; + + const insertList = diffs + .filter((d) => d.nextRenderedHighlight) + .map((d) => ({ + line: d.nextRenderedHighlight?.line, + content: highlightRenderer.render(d.remoteHighlight, this.kindleFile.book), + })); + + const appendList = diffs + .filter((d) => d.nextRenderedHighlight == null) + .map((d) => highlightRenderer.render(d.remoteHighlight, this.kindleFile.book)); + + const modifiedFileContents = this.fileBuffer + .insertLinesAt(insertList) + .append(appendList) + .toString(); + + await this.fileManager.updateFile( + this.kindleFile, + remoteBook, + modifiedFileContents, + remoteHighlights.length + ); + } +} diff --git a/src/sync/index.ts b/src/sync/index.ts index 3816ee3..5241973 100644 --- a/src/sync/index.ts +++ b/src/sync/index.ts @@ -1,5 +1,5 @@ -import SyncAmazon from './syncAmazon'; -import SyncClippings from './syncClippings'; -import SyncManager from './syncManager'; - -export { SyncAmazon, SyncClippings, SyncManager }; +import SyncAmazon from './syncAmazon'; +import SyncClippings from './syncClippings'; +import SyncManager from './syncManager'; + +export { SyncAmazon, SyncClippings, SyncManager }; diff --git a/src/sync/syncAmazon/index.ts b/src/sync/syncAmazon/index.ts index 4e4f3ce..53439dd 100644 --- a/src/sync/syncAmazon/index.ts +++ b/src/sync/syncAmazon/index.ts @@ -1,88 +1,88 @@ -import AmazonLoginModal from '~/components/amazonLoginModal'; -import { ee } from '~/eventEmitter'; -import type { Book, KindleFile } from '~/models'; -import { scrapeBooks, scrapeHighlightsForBook } from '~/scraper'; -import type { SyncManager } from '~/sync'; - -export default class SyncAmazon { - constructor(private syncManager: SyncManager) {} - - public async startSync(): Promise { - ee.emit('syncSessionStart', 'amazon'); - - const success = await this.login(); - - if (!success) { - return; // Do nothing... - } - - try { - ee.emit('fetchingBooks'); - - const remoteBooks = await scrapeBooks(); - const booksToSync = this.syncManager.filterBooksToSync(remoteBooks); - - ee.emit('fetchingBooksSuccess', booksToSync, remoteBooks); - - if (booksToSync.length > 0) { - await this.syncBooks(booksToSync); - } - - ee.emit('syncSessionSuccess'); - } catch (error) { - console.error('Error while trying fetch books and to sync', error); - ee.emit('syncSessionFailure', String(error)); - } - } - - public async resync(file: KindleFile): Promise { - ee.emit('resyncBook', file); - - const success = await this.login(); - - if (!success) { - return; // Do nothing... - } - - try { - const remoteBooks = await scrapeBooks(); - const remoteBook = remoteBooks.find((r) => r.id === file.book.id); - - const highlights = await scrapeHighlightsForBook(file.book); - - const diffs = await this.syncManager.resyncBook(file, remoteBook, highlights); - - ee.emit('resyncComplete', file, diffs.length); - } catch (error) { - console.error('Error resyncing higlights for file', file, error); - ee.emit('resyncFailure', file, String(error)); - } - } - - private async login(): Promise { - ee.emit('startLogin'); - - const modal = new AmazonLoginModal(); - const success = await modal.doLogin(); - - ee.emit('loginComplete', success); - - return success; - } - - private async syncBooks(books: Book[]): Promise { - for (const [index, book] of books.entries()) { - try { - ee.emit('syncBook', book, index); - - const highlights = await scrapeHighlightsForBook(book); - await this.syncManager.syncBook(book, highlights); - - ee.emit('syncBookSuccess', book, highlights); - } catch (error) { - console.error('Error syncing book', book, error); - ee.emit('syncBookFailure', book, String(error)); - } - } - } -} +import AmazonLoginModal from '~/components/amazonLoginModal'; +import { ee } from '~/eventEmitter'; +import type { Book, KindleFile } from '~/models'; +import { scrapeBooks, scrapeHighlightsForBook } from '~/scraper'; +import type { SyncManager } from '~/sync'; + +export default class SyncAmazon { + constructor(private syncManager: SyncManager) {} + + public async startSync(): Promise { + ee.emit('syncSessionStart', 'amazon'); + + const success = await this.login(); + + if (!success) { + return; // Do nothing... + } + + try { + ee.emit('fetchingBooks'); + + const remoteBooks = await scrapeBooks(); + const booksToSync = this.syncManager.filterBooksToSync(remoteBooks); + + ee.emit('fetchingBooksSuccess', booksToSync, remoteBooks); + + if (booksToSync.length > 0) { + await this.syncBooks(booksToSync); + } + + ee.emit('syncSessionSuccess'); + } catch (error) { + console.error('Error while trying fetch books and to sync', error); + ee.emit('syncSessionFailure', String(error)); + } + } + + public async resync(file: KindleFile): Promise { + ee.emit('resyncBook', file); + + const success = await this.login(); + + if (!success) { + return; // Do nothing... + } + + try { + const remoteBooks = await scrapeBooks(); + const remoteBook = remoteBooks.find((r) => r.id === file.book.id); + + const highlights = await scrapeHighlightsForBook(file.book); + + const diffs = await this.syncManager.resyncBook(file, remoteBook, highlights); + + ee.emit('resyncComplete', file, diffs.length); + } catch (error) { + console.error('Error resyncing higlights for file', file, error); + ee.emit('resyncFailure', file, String(error)); + } + } + + private async login(): Promise { + ee.emit('startLogin'); + + const modal = new AmazonLoginModal(); + const success = await modal.doLogin(); + + ee.emit('loginComplete', success); + + return success; + } + + private async syncBooks(books: Book[]): Promise { + for (const [index, book] of books.entries()) { + try { + ee.emit('syncBook', book, index); + + const highlights = await scrapeHighlightsForBook(book); + await this.syncManager.syncBook(book, highlights); + + ee.emit('syncBookSuccess', book, highlights); + } catch (error) { + console.error('Error syncing book', book, error); + ee.emit('syncBookFailure', book, String(error)); + } + } + } +} diff --git a/src/sync/syncClippings/index.ts b/src/sync/syncClippings/index.ts index 3743c4c..d562edc 100644 --- a/src/sync/syncClippings/index.ts +++ b/src/sync/syncClippings/index.ts @@ -1,33 +1,33 @@ -import { ee } from '~/eventEmitter'; -import type { SyncManager } from '~/sync'; - -import { openDialog } from './openDialog'; -import { parseBooks } from './parseBooks'; - -export default class SyncKindleClippings { - constructor(private syncManager: SyncManager) {} - - public async startSync(): Promise { - const [clippingsFile, canceled] = await openDialog(); - - if (canceled) { - return; // Do nothing... - } - - try { - ee.emit('syncSessionStart', 'my-clippings'); - - const bookHighlights = parseBooks(clippingsFile); - - for (const { book, highlights } of bookHighlights) { - await this.syncManager.syncBook(book, highlights); - } - - ee.emit('syncSessionSuccess'); - } catch (error) { - const message = `Error parsing ${clippingsFile}.\n\n${String(error)}`; - ee.emit('syncSessionFailure', message); - console.error(message); - } - } -} +import { ee } from '~/eventEmitter'; +import type { SyncManager } from '~/sync'; + +import { openDialog } from './openDialog'; +import { parseBooks } from './parseBooks'; + +export default class SyncKindleClippings { + constructor(private syncManager: SyncManager) {} + + public async startSync(): Promise { + const [clippingsFile, canceled] = await openDialog(); + + if (canceled) { + return; // Do nothing... + } + + try { + ee.emit('syncSessionStart', 'my-clippings'); + + const bookHighlights = parseBooks(clippingsFile); + + for (const { book, highlights } of bookHighlights) { + await this.syncManager.syncBook(book, highlights); + } + + ee.emit('syncSessionSuccess'); + } catch (error) { + const message = `Error parsing ${clippingsFile}.\n\n${String(error)}`; + ee.emit('syncSessionFailure', message); + console.error(message); + } + } +} diff --git a/src/sync/syncClippings/openDialog.ts b/src/sync/syncClippings/openDialog.ts index 2096e78..cf4c393 100644 --- a/src/sync/syncClippings/openDialog.ts +++ b/src/sync/syncClippings/openDialog.ts @@ -1,18 +1,18 @@ -import { remote } from 'electron'; - -const { dialog } = remote; - -type DialogResponse = [file: string, canceled: boolean]; - -export const openDialog = async (): Promise => { - const result = await dialog.showOpenDialog(remote.getCurrentWindow(), { - filters: [{ name: 'Text file', extensions: ['txt'] }], - properties: ['openFile'], - }); - - if (result.canceled === true) { - return ['', true]; - } - - return [result.filePaths[0], false]; -}; +import { remote } from 'electron'; + +const { dialog } = remote; + +type DialogResponse = [file: string, canceled: boolean]; + +export const openDialog = async (): Promise => { + const result = await dialog.showOpenDialog(remote.getCurrentWindow(), { + filters: [{ name: 'Text file', extensions: ['txt'] }], + properties: ['openFile'], + }); + + if (result.canceled === true) { + return ['', true]; + } + + return [result.filePaths[0], false]; +}; diff --git a/src/sync/syncClippings/parseBooks.ts b/src/sync/syncClippings/parseBooks.ts index 3c2c2f7..9eaa174 100644 --- a/src/sync/syncClippings/parseBooks.ts +++ b/src/sync/syncClippings/parseBooks.ts @@ -1,36 +1,36 @@ -import { Book, groupToBooks, readMyClippingsFile } from '@hadynz/kindle-clippings'; -import fs from 'fs'; - -import type { BookHighlight, Highlight } from '~/models'; -import { hash } from '~/utils'; - -const toBookHighlight = (book: Book): BookHighlight => { - return { - book: { - id: hash(book.title), - title: book.title, - author: book.author, - }, - highlights: book.annotations - .filter((entry) => entry.type === 'HIGHLIGHT' || entry.type === 'UNKNOWN') - .map( - (entry): Highlight => ({ - id: hash(entry.content), - text: entry.content, - note: entry.note, - location: entry.location?.display, - page: entry.page?.display, - createdDate: entry.createdDate, - }) - ), - }; -}; - -export const parseBooks = (file: string): BookHighlight[] => { - const clippingsFileContent = fs.readFileSync(file, 'utf8'); - - const parsedRows = readMyClippingsFile(clippingsFileContent); - const books = groupToBooks(parsedRows); - - return books.map(toBookHighlight); -}; +import { Book, groupToBooks, readMyClippingsFile } from '@hadynz/kindle-clippings'; +import fs from 'fs'; + +import type { BookHighlight, Highlight } from '~/models'; +import { hash } from '~/utils'; + +const toBookHighlight = (book: Book): BookHighlight => { + return { + book: { + id: hash(book.title), + title: book.title, + author: book.author, + }, + highlights: book.annotations + .filter((entry) => entry.type === 'HIGHLIGHT' || entry.type === 'UNKNOWN') + .map( + (entry): Highlight => ({ + id: hash(entry.content), + text: entry.content, + note: entry.note, + location: entry.location?.display, + page: entry.page?.display, + createdDate: entry.createdDate, + }) + ), + }; +}; + +export const parseBooks = (file: string): BookHighlight[] => { + const clippingsFileContent = fs.readFileSync(file, 'utf8'); + + const parsedRows = readMyClippingsFile(clippingsFileContent); + const books = groupToBooks(parsedRows); + + return books.map(toBookHighlight); +}; diff --git a/src/sync/syncManager/diffBooks.spec.ts b/src/sync/syncManager/diffBooks.spec.ts index 1c514e7..91e4aae 100644 --- a/src/sync/syncManager/diffBooks.spec.ts +++ b/src/sync/syncManager/diffBooks.spec.ts @@ -1,67 +1,67 @@ -import faker from 'faker'; - -import type { Book } from '~/models'; - -import { diffBooks } from './diffBooks'; - -const book = (id: string, lastAnnotatedDate?: Date): Book => { - return { - id, - title: faker.lorem.words(3), - author: faker.name.findName(), - lastAnnotatedDate, - }; -}; - -describe('diffBooks', () => { - it('New remote books are always filtered for sync', () => { - const remoteBooks = [book('1'), book('2'), book('3')]; - const vaultBooks = [book('1')]; - - const actualBooks = diffBooks(remoteBooks, vaultBooks, new Date()); - expect(actualBooks.map((a) => a.id)).toEqual(['2', '3']); - }); - - it('No books to sync if remote and vault are identical', () => { - const remoteBooks = [book('1'), book('2'), book('3')]; - const vaultBooks = [book('1'), book('2'), book('3')]; - - const actualBooks = diffBooks(remoteBooks, vaultBooks, new Date()); - expect(actualBooks).toHaveLength(0); - }); - - it('Books with same last annotated date on same day as last sync will always be filtered for sync', () => { - const remoteBooks = [book('1', new Date('October 25, 2021'))]; - const vaultBooks = [book('1', new Date('October 25, 2021'))]; - const lastSyncDate = new Date('Tue Oct 25 2021 18:58:18 GMT+1300'); - - const actualBooks = diffBooks(remoteBooks, vaultBooks, lastSyncDate); - expect(actualBooks.map((a) => a.id)).toEqual(['1']); - }); - - it('Books with same last annotated date a day before last sync will always be filtered for sync', () => { - const remoteBooks = [book('1', new Date('October 25, 2021'))]; - const vaultBooks = [book('1', new Date('October 25, 2021'))]; - const lastSyncDate = new Date('Tue Oct 26 2021 18:58:18 GMT+1300'); - - const actualBooks = diffBooks(remoteBooks, vaultBooks, lastSyncDate); - expect(actualBooks.map((a) => a.id)).toEqual(['1']); - }); - - it('Books with same last annotated date two days before last sync will not be filtered for sync', () => { - const remoteBooks = [book('1', new Date('October 25, 2021'))]; - const vaultBooks = [book('1', new Date('October 25, 2021'))]; - const lastSyncDate = new Date('Tue Oct 27 2021 18:58:18 GMT+1300'); - - const actualBooks = diffBooks(remoteBooks, vaultBooks, lastSyncDate); - expect(actualBooks.map((a) => a.id)).toHaveLength(0); - }); - - it('Books with different last annotated dates are filtered for sync', () => { - const remoteBooks = [book('1', new Date('October 19, 2018'))]; - const vaultBooks = [book('1', new Date('August 6, 2018'))]; - - const actualBooks = diffBooks(remoteBooks, vaultBooks, new Date()); - expect(actualBooks.map((a) => a.id)).toEqual(['1']); - }); -}); +import faker from 'faker'; + +import type { Book } from '~/models'; + +import { diffBooks } from './diffBooks'; + +const book = (id: string, lastAnnotatedDate?: Date): Book => { + return { + id, + title: faker.lorem.words(3), + author: faker.name.findName(), + lastAnnotatedDate, + }; +}; + +describe('diffBooks', () => { + it('New remote books are always filtered for sync', () => { + const remoteBooks = [book('1'), book('2'), book('3')]; + const vaultBooks = [book('1')]; + + const actualBooks = diffBooks(remoteBooks, vaultBooks, new Date()); + expect(actualBooks.map((a) => a.id)).toEqual(['2', '3']); + }); + + it('No books to sync if remote and vault are identical', () => { + const remoteBooks = [book('1'), book('2'), book('3')]; + const vaultBooks = [book('1'), book('2'), book('3')]; + + const actualBooks = diffBooks(remoteBooks, vaultBooks, new Date()); + expect(actualBooks).toHaveLength(0); + }); + + it('Books with same last annotated date on same day as last sync will always be filtered for sync', () => { + const remoteBooks = [book('1', new Date('October 25, 2021'))]; + const vaultBooks = [book('1', new Date('October 25, 2021'))]; + const lastSyncDate = new Date('Tue Oct 25 2021 18:58:18 GMT+1300'); + + const actualBooks = diffBooks(remoteBooks, vaultBooks, lastSyncDate); + expect(actualBooks.map((a) => a.id)).toEqual(['1']); + }); + + it('Books with same last annotated date a day before last sync will always be filtered for sync', () => { + const remoteBooks = [book('1', new Date('October 25, 2021'))]; + const vaultBooks = [book('1', new Date('October 25, 2021'))]; + const lastSyncDate = new Date('Tue Oct 26 2021 18:58:18 GMT+1300'); + + const actualBooks = diffBooks(remoteBooks, vaultBooks, lastSyncDate); + expect(actualBooks.map((a) => a.id)).toEqual(['1']); + }); + + it('Books with same last annotated date two days before last sync will not be filtered for sync', () => { + const remoteBooks = [book('1', new Date('October 25, 2021'))]; + const vaultBooks = [book('1', new Date('October 25, 2021'))]; + const lastSyncDate = new Date('Tue Oct 27 2021 18:58:18 GMT+1300'); + + const actualBooks = diffBooks(remoteBooks, vaultBooks, lastSyncDate); + expect(actualBooks.map((a) => a.id)).toHaveLength(0); + }); + + it('Books with different last annotated dates are filtered for sync', () => { + const remoteBooks = [book('1', new Date('October 19, 2018'))]; + const vaultBooks = [book('1', new Date('August 6, 2018'))]; + + const actualBooks = diffBooks(remoteBooks, vaultBooks, new Date()); + expect(actualBooks.map((a) => a.id)).toEqual(['1']); + }); +}); diff --git a/src/sync/syncManager/diffBooks.ts b/src/sync/syncManager/diffBooks.ts index 1a053be..23aaa24 100644 --- a/src/sync/syncManager/diffBooks.ts +++ b/src/sync/syncManager/diffBooks.ts @@ -1,42 +1,42 @@ -import _ from 'lodash'; -import moment from 'moment'; - -import type { Book } from '~/models'; - -const isEqual = (book1: Book, book2: Book): boolean => { - return book1.id === book2.id; -}; - -const isSameDate = (date1: Date | undefined, date2: Date | undefined): boolean => { - return date1?.getTime() === date2?.getTime(); -}; - -const updatedSince = (book: Book, lastSyncDate: Date): boolean => { - if (book.lastAnnotatedDate != null) { - return moment(lastSyncDate) - .startOf('day') - .subtract(1, 'd') - .isSameOrBefore(book.lastAnnotatedDate); - } - return false; -}; - -export const diffBooks = ( - remoteBooks: Book[], - vaultBooks: Book[], - lastSyncDate: Date -): Book[] => { - const newBooks = remoteBooks.filter((remote) => !vaultBooks.some((v) => isEqual(v, remote))); - - const diffAnnotatedDates = remoteBooks.filter((remote) => - vaultBooks.some( - (v) => isEqual(v, remote) && !isSameDate(remote.lastAnnotatedDate, v.lastAnnotatedDate) - ) - ); - - const updatedBooks = remoteBooks.filter((remote) => - vaultBooks.some((v) => isEqual(v, remote) && updatedSince(remote, lastSyncDate)) - ); - - return _.uniqBy([...newBooks, ...diffAnnotatedDates, ...updatedBooks], (book) => book.id); -}; +import _ from 'lodash'; +import moment from 'moment'; + +import type { Book } from '~/models'; + +const isEqual = (book1: Book, book2: Book): boolean => { + return book1.id === book2.id; +}; + +const isSameDate = (date1: Date | undefined, date2: Date | undefined): boolean => { + return date1?.getTime() === date2?.getTime(); +}; + +const updatedSince = (book: Book, lastSyncDate: Date): boolean => { + if (book.lastAnnotatedDate != null) { + return moment(lastSyncDate) + .startOf('day') + .subtract(1, 'd') + .isSameOrBefore(book.lastAnnotatedDate); + } + return false; +}; + +export const diffBooks = ( + remoteBooks: Book[], + vaultBooks: Book[], + lastSyncDate: Date +): Book[] => { + const newBooks = remoteBooks.filter((remote) => !vaultBooks.some((v) => isEqual(v, remote))); + + const diffAnnotatedDates = remoteBooks.filter((remote) => + vaultBooks.some( + (v) => isEqual(v, remote) && !isSameDate(remote.lastAnnotatedDate, v.lastAnnotatedDate) + ) + ); + + const updatedBooks = remoteBooks.filter((remote) => + vaultBooks.some((v) => isEqual(v, remote) && updatedSince(remote, lastSyncDate)) + ); + + return _.uniqBy([...newBooks, ...diffAnnotatedDates, ...updatedBooks], (book) => book.id); +}; diff --git a/src/sync/syncManager/index.ts b/src/sync/syncManager/index.ts index 066019a..dfdf633 100644 --- a/src/sync/syncManager/index.ts +++ b/src/sync/syncManager/index.ts @@ -1,81 +1,81 @@ -import { get } from 'svelte/store'; - -import type FileManager from '~/fileManager'; -import type { Book, BookMetadata, Highlight, KindleFile } from '~/models'; -import { getRenderers } from '~/rendering'; -import { scrapeBookMetadata } from '~/scraper'; -import { settingsStore } from '~/store'; - -import type { DiffResult } from '../diffManager'; -import { DiffManager } from '../diffManager'; - -import { diffBooks } from './diffBooks'; - -export default class SyncManager { - constructor(private fileManager: FileManager) { - this.fileManager = fileManager; - } - - public filterBooksToSync(remoteBooks: Book[]): Book[] { - const lastSyncDate = get(settingsStore).lastSyncDate; - const vaultBooks = this.fileManager.getKindleFiles(); - - return diffBooks( - remoteBooks, - vaultBooks.map((v) => v.book), - lastSyncDate - ); - } - - public async syncBook(book: Book, highlights: Highlight[]): Promise { - if (highlights.length === 0) { - return; // No highlights for book. Skip sync - } - - const file = this.fileManager.getKindleFile(book); - - if (file == null) { - await this.createBook(book, highlights); - } else { - await this.resyncBook(file, book, highlights); - } - } - - public async resyncBook( - file: KindleFile, - remoteBook: Book, - remoteHighlights: Highlight[] - ): Promise { - const diffManager = await DiffManager.create(this.fileManager, file); - - const diffs = diffManager.diff(remoteHighlights); - - if (diffs.length > 0) { - await diffManager.applyDiffs(remoteBook, remoteHighlights, diffs); - } - - return diffs; - } - - private async createBook(book: Book, highlights: Highlight[]): Promise { - const metadata = await this.syncMetadata(book); - - const content = getRenderers().fileRenderer.render({ book, highlights, metadata }); - - await this.fileManager.createFile(book, content, highlights.length); - } - - private async syncMetadata(book: Book): Promise { - let metadata: BookMetadata; - - try { - if (get(settingsStore).downloadBookMetadata && book.asin) { - metadata = await scrapeBookMetadata(book); - } - } catch (error) { - console.error(`Couldn't download metadata for ${book.title}`, error); - } - - return metadata; - } -} +import { get } from 'svelte/store'; + +import type FileManager from '~/fileManager'; +import type { Book, BookMetadata, Highlight, KindleFile } from '~/models'; +import { getRenderers } from '~/rendering'; +import { scrapeBookMetadata } from '~/scraper'; +import { settingsStore } from '~/store'; + +import type { DiffResult } from '../diffManager'; +import { DiffManager } from '../diffManager'; + +import { diffBooks } from './diffBooks'; + +export default class SyncManager { + constructor(private fileManager: FileManager) { + this.fileManager = fileManager; + } + + public filterBooksToSync(remoteBooks: Book[]): Book[] { + const lastSyncDate = get(settingsStore).lastSyncDate; + const vaultBooks = this.fileManager.getKindleFiles(); + + return diffBooks( + remoteBooks, + vaultBooks.map((v) => v.book), + lastSyncDate + ); + } + + public async syncBook(book: Book, highlights: Highlight[]): Promise { + if (highlights.length === 0) { + return; // No highlights for book. Skip sync + } + + const file = this.fileManager.getKindleFile(book); + + if (file == null) { + await this.createBook(book, highlights); + } else { + await this.resyncBook(file, book, highlights); + } + } + + public async resyncBook( + file: KindleFile, + remoteBook: Book, + remoteHighlights: Highlight[] + ): Promise { + const diffManager = await DiffManager.create(this.fileManager, file); + + const diffs = diffManager.diff(remoteHighlights); + + if (diffs.length > 0) { + await diffManager.applyDiffs(remoteBook, remoteHighlights, diffs); + } + + return diffs; + } + + private async createBook(book: Book, highlights: Highlight[]): Promise { + const metadata = await this.syncMetadata(book); + + const content = getRenderers().fileRenderer.render({ book, highlights, metadata }); + + await this.fileManager.createFile(book, content, highlights.length); + } + + private async syncMetadata(book: Book): Promise { + let metadata: BookMetadata; + + try { + if (get(settingsStore).downloadBookMetadata && book.asin) { + metadata = await scrapeBookMetadata(book); + } + } catch (error) { + console.error(`Couldn't download metadata for ${book.title}`, error); + } + + return metadata; + } +} diff --git a/src/sync/syncState.ts b/src/sync/syncState.ts index 34a00ca..5397fe0 100644 --- a/src/sync/syncState.ts +++ b/src/sync/syncState.ts @@ -1,4 +1,4 @@ -export type SyncState = { - newBooksSynced: number; - newHighlightsSynced: number; -}; +export type SyncState = { + newBooksSynced: number; + newHighlightsSynced: number; +}; diff --git a/src/utils/br2ln.spec.ts b/src/utils/br2ln.spec.ts index 5531c8e..2e49417 100644 --- a/src/utils/br2ln.spec.ts +++ b/src/utils/br2ln.spec.ts @@ -1,28 +1,28 @@ -import { br2ln } from '~/utils'; - -describe('HTML breakline to new line', () => { - it('replaces breakline elements with no spaces', () => { - const actual = br2ln('hello
there'); - expect(actual).toEqual('hello\nthere'); - }); - - it('replaces breakline elements with spaces', () => { - const actual = br2ln('hello
there'); - expect(actual).toEqual('hello\nthere'); - }); - - it('returns string with no breaklines', () => { - const actual = br2ln('hello there'); - expect(actual).toEqual('hello there'); - }); - - it('handles null', () => { - const actual = br2ln(null); - expect(actual).toEqual(null); - }); - - it('handles undefined', () => { - const actual = br2ln(undefined); - expect(actual).toEqual(undefined); - }); -}); +import { br2ln } from '~/utils'; + +describe('HTML breakline to new line', () => { + it('replaces breakline elements with no spaces', () => { + const actual = br2ln('hello
there'); + expect(actual).toEqual('hello\nthere'); + }); + + it('replaces breakline elements with spaces', () => { + const actual = br2ln('hello
there'); + expect(actual).toEqual('hello\nthere'); + }); + + it('returns string with no breaklines', () => { + const actual = br2ln('hello there'); + expect(actual).toEqual('hello there'); + }); + + it('handles null', () => { + const actual = br2ln(null); + expect(actual).toEqual(null); + }); + + it('handles undefined', () => { + const actual = br2ln(undefined); + expect(actual).toEqual(undefined); + }); +}); diff --git a/src/utils/br2ln.ts b/src/utils/br2ln.ts index 3ab5755..34019c2 100644 --- a/src/utils/br2ln.ts +++ b/src/utils/br2ln.ts @@ -1,3 +1,3 @@ -export const br2ln = (html: string): string => { - return html ? html.replace(/
/gi, '\n') : html; -}; +export const br2ln = (html: string): string => { + return html ? html.replace(/
/gi, '\n') : html; +}; diff --git a/src/utils/frontmatter.spec.ts b/src/utils/frontmatter.spec.ts index 1864100..f6f14c4 100644 --- a/src/utils/frontmatter.spec.ts +++ b/src/utils/frontmatter.spec.ts @@ -1,107 +1,122 @@ -import { mergeFrontmatter } from '~/utils'; - -describe('Setting frontmatter', () => { - it('Merge a single, existing frontmatter value', () => { - const yamlContent = (value: string | number) => { - return `--- -tag: source/book -bookId: ${value} ---- - -# Content -## Heading 1 -## Heading 2 -`; - }; - - const newBookId = 'ABC456'; - const fileContent = yamlContent('ABC123'); - const actual = mergeFrontmatter(fileContent, { bookId: newBookId }); - - const expected = yamlContent(newBookId); - expect(actual).toEqual(expected); - }); - - it('Merge multiple existing frontmatter values', () => { - const yamlContent = (value1: string | number, value2: string | number) => { - return `--- -bookName: ${value1} -tag: source/book -bookId: ${value2} ---- - -# Content -## Heading 1 -## Heading 2 -`; - }; - - const fileContent = yamlContent('My Book', 'Book1234'); - const actual = mergeFrontmatter(fileContent, { - bookName: 'New Book', - bookId: 'NewBook1234', - }); - - const expected = yamlContent('New Book', 'NewBook1234'); - expect(actual).toEqual(expected); - }); - - it('Add new frontmatter values to an existing empty frontmatter block', () => { - const originalYamlContent = `--- ---- - -# Content -## Heading 1 -## Heading 2 -`; - - const yamlContent = (key: string, value: string) => { - return `--- -${key}: ${value} ---- - -# Content -## Heading 1 -## Heading 2 -`; - }; - - const actual = mergeFrontmatter(originalYamlContent, { - bookName: 'New Book', - }); - - const expected = yamlContent('bookName', 'New Book'); - expect(actual).toEqual(expected); - }); - - it('Insert new frontmatter to string without any frontmatter', () => { - const originalYamlContent = `# Content -## Heading 1 -## Heading 2 -`; - - const expectedYamlContent = `--- -bookName: New Book ---- -# Content -## Heading 1 -## Heading 2 -`; - - const actual = mergeFrontmatter(originalYamlContent, { - bookName: 'New Book', - }); - - expect(actual).toEqual(expectedYamlContent); - }); - - it('Frontmatter with undefined values does not throw exception', () => { - expect(() => { - mergeFrontmatter('', { - 'kindle-sync': { - lastAnnotatedDate: undefined, - }, - }); - }).not.toThrow(); - }); -}); +import { mergeFrontmatter } from '~/utils'; + +describe('Setting frontmatter', () => { + it('Merge a single, existing frontmatter value', () => { + const yamlContent = (value: string | number) => { + return `--- +tag: source/book +bookId: ${value} +--- + +# Content +## Heading 1 +## Heading 2 +`; + }; + + const newBookId = 'ABC456'; + const fileContent = yamlContent('ABC123'); + const actual = mergeFrontmatter(fileContent, { bookId: newBookId }); + + const expected = yamlContent(newBookId); + expect(actual).toEqual(expected); + }); + + it('Merge multiple existing frontmatter values', () => { + const yamlContent = (value1: string | number, value2: string | number) => { + return `--- +bookName: ${value1} +tag: source/book +bookId: ${value2} +--- + +# Content +## Heading 1 +## Heading 2 +`; + }; + + const fileContent = yamlContent('My Book', 'Book1234'); + const actual = mergeFrontmatter(fileContent, { + bookName: 'New Book', + bookId: 'NewBook1234', + }); + + const expected = yamlContent('New Book', 'NewBook1234'); + expect(actual).toEqual(expected); + }); + + it('Add new frontmatter values to an existing empty frontmatter block', () => { + const originalYamlContent = `--- +--- + +# Content +## Heading 1 +## Heading 2 +`; + + const yamlContent = (key: string, value: string) => { + return `--- +${key}: ${value} +--- + +# Content +## Heading 1 +## Heading 2 +`; + }; + + const actual = mergeFrontmatter(originalYamlContent, { + bookName: 'New Book', + }); + + const expected = yamlContent('bookName', 'New Book'); + expect(actual).toEqual(expected); + }); + + it('Insert new frontmatter to string without any frontmatter', () => { + const originalYamlContent = `# Content +## Heading 1 +## Heading 2 +`; + + const expectedYamlContent = `--- +bookName: New Book +--- + +# Content +## Heading 1 +## Heading 2 +`; + + const actual = mergeFrontmatter(originalYamlContent, { + bookName: 'New Book', + }); + + expect(actual).toEqual(expectedYamlContent); + }); + + it('Frontmatter with undefined values does not throw exception', () => { + expect(() => { + mergeFrontmatter('', { + 'kindle-sync': { + lastAnnotatedDate: undefined, + }, + }); + }).not.toThrow(); + }); + + it('Formats nested frontmatter objects on separate lines', () => { + const actual = mergeFrontmatter('', { + 'kindle-sync': { + bookId: 'ABC123', + title: 'My Book', + author: 'An Author', + }, + }); + + expect(actual).toContain( + 'kindle-sync:\n bookId: ABC123\n title: My Book\n author: An Author\n---' + ); + }); +}); diff --git a/src/utils/frontmatter.ts b/src/utils/frontmatter.ts index f2ad310..ad51e05 100644 --- a/src/utils/frontmatter.ts +++ b/src/utils/frontmatter.ts @@ -1,27 +1,30 @@ -import matter from 'gray-matter'; - -/** - * Remove any falsy or undefined values from nested object - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const sanitize = (obj: any): any => { - return JSON.parse( - JSON.stringify(obj, (_key, value) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return value === null ? undefined : value; - }) - ); -}; - -export const mergeFrontmatter = ( - textWithFrontMatter: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - newFrontMatter: Record-): string => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const cleanFrontmatter = sanitize(newFrontMatter); - const { data, content } = matter(textWithFrontMatter); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const mergedFrontMatter = Object.assign({}, data, cleanFrontmatter); - return matter.stringify(content, mergedFrontMatter); -}; +import matter from 'gray-matter'; +import yaml from 'js-yaml'; + +/** + * Remove any falsy or undefined values from nested object + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const sanitize = (obj: any): any => { + return JSON.parse( + JSON.stringify(obj, (_key, value) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return value === null ? undefined : value; + }) + ); +}; + +export const mergeFrontmatter = ( + textWithFrontMatter: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + newFrontMatter: Record +): string => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const cleanFrontmatter = sanitize(newFrontMatter); + const { data, content } = matter(textWithFrontMatter); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const mergedFrontMatter = Object.assign({}, data, cleanFrontmatter); + const yamlContent = yaml.dump(mergedFrontMatter, { flowLevel: -1, lineWidth: -1 }); + const trimmedContent = content.startsWith('\n') ? content.slice(1) : content; + return `---\n${yamlContent}---\n\n${trimmedContent}`; +}; diff --git a/src/utils/hash.ts b/src/utils/hash.ts index e56536a..a176f02 100644 --- a/src/utils/hash.ts +++ b/src/utils/hash.ts @@ -1,4 +1,4 @@ -import fletcher16 from 'fletcher'; +import fletcher16 = require('fletcher'); export const hash = (value: string): string => { return fletcher16(Buffer.from(value.toLowerCase())).toString(); diff --git a/src/utils/index.ts b/src/utils/index.ts index bd99823..86090b0 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,6 +1,6 @@ -export * from './shortenTitle'; -export * from './frontmatter'; -export * from './br2ln'; -export * from './hash'; -export * from './stringBuffer'; -export * from './parseAuthor'; +export * from './shortenTitle'; +export * from './frontmatter'; +export * from './br2ln'; +export * from './hash'; +export * from './stringBuffer'; +export * from './parseAuthor'; diff --git a/src/utils/parseAuthor.spec.ts b/src/utils/parseAuthor.spec.ts index 03107ef..9d0cce1 100644 --- a/src/utils/parseAuthor.spec.ts +++ b/src/utils/parseAuthor.spec.ts @@ -1,32 +1,32 @@ -import { parseAuthors } from './parseAuthor'; - -describe('parseAuthor', () => { - it.each([ - ['Michael Port', 'Michael', 'Port'], - ['Strunk Jr., William', 'William', 'Strunk Jr'], - ['Yuval Noah Harari', 'Yuval', 'Harari'], - ['P2K', undefined, 'P2K'], - ['Toole, John Kennedy', 'John', 'Toole'], - [null, undefined, undefined], - ['Schwab, V. E.', 'V', 'Schwab'], - ['Brandon Sanderson', 'Brandon', 'Sanderson'], - ['Sanderson, Brandon', 'Brandon', 'Sanderson'], - ])( - 'Parse "%s" evaluated as firstName: "%s" and lastName: "%s', - (author, firstName, lastName) => { - const authors = parseAuthors(author); - expect(authors).toHaveLength(1); - expect(authors[0]).toEqual({ firstName, lastName }); - } - ); - - it.each([ - ['Michael Port', 1], - ['Vicki Robin, Joe Dominguez, And Mr. Money Mustache', 3], - ['Robert Kegan aNd Lisa Laskow Lahey', 2], - ['Chan, Francis;Sprinkle, Preston', 2], - ])('"%s" is parsed as %s author(s)', (author, expectedAuthorCount) => { - const authors = parseAuthors(author); - expect(authors).toHaveLength(expectedAuthorCount); - }); -}); +import { parseAuthors } from './parseAuthor'; + +describe('parseAuthor', () => { + it.each([ + ['Michael Port', 'Michael', 'Port'], + ['Strunk Jr., William', 'William', 'Strunk Jr'], + ['Yuval Noah Harari', 'Yuval', 'Harari'], + ['P2K', undefined, 'P2K'], + ['Toole, John Kennedy', 'John', 'Toole'], + [null, undefined, undefined], + ['Schwab, V. E.', 'V', 'Schwab'], + ['Brandon Sanderson', 'Brandon', 'Sanderson'], + ['Sanderson, Brandon', 'Brandon', 'Sanderson'], + ])( + 'Parse "%s" evaluated as firstName: "%s" and lastName: "%s', + (author, firstName, lastName) => { + const authors = parseAuthors(author); + expect(authors).toHaveLength(1); + expect(authors[0]).toEqual({ firstName, lastName }); + } + ); + + it.each([ + ['Michael Port', 1], + ['Vicki Robin, Joe Dominguez, And Mr. Money Mustache', 3], + ['Robert Kegan aNd Lisa Laskow Lahey', 2], + ['Chan, Francis;Sprinkle, Preston', 2], + ])('"%s" is parsed as %s author(s)', (author, expectedAuthorCount) => { + const authors = parseAuthors(author); + expect(authors).toHaveLength(expectedAuthorCount); + }); +}); diff --git a/src/utils/parseAuthor.ts b/src/utils/parseAuthor.ts index 6acb5bd..8bb1e17 100644 --- a/src/utils/parseAuthor.ts +++ b/src/utils/parseAuthor.ts @@ -1,52 +1,52 @@ -type Author = { - firstName: string; - lastName: string; -}; - -export const parseAuthors = (author: string | undefined): Author[] => { - if (author == null) { - return [{ firstName: undefined, lastName: undefined }]; - } - - if (new RegExp(/\b(and)+/, 'i').exec(author)) { - return author - .split(new RegExp(/\b(and|,)+/, 'i')) - .map((a) => a.trim()) - .filter((a) => ['and', ',', ''].indexOf(a.toLowerCase()) === -1) - .map(parseSingleAuthor); - } - - if (author.includes(';')) { - return author - .split(';') - .map((a) => a.trim()) - .map(parseSingleAuthor); - } - - return [parseSingleAuthor(author)]; -}; - -const parseSingleAuthor = (author: string): Author => { - const hasComma = author.includes(','); - - if (hasComma) { - const names = splitAndTrim(',', author); - return { - firstName: names.length == 1 ? undefined : splitAndTrim(' ', names[names.length - 1])[0], - lastName: names[0], - }; - } - - const names = splitAndTrim(' ', author); - return { - firstName: names.length == 1 ? undefined : names[0], - lastName: names[names.length - 1], - }; -}; - -const splitAndTrim = (needle: string, author: string): string[] => { - return author - .split(needle) - .map((a) => a.trim()) - .map((a) => a.replace(/\.$/, '')); -}; +type Author = { + firstName: string; + lastName: string; +}; + +export const parseAuthors = (author: string | undefined): Author[] => { + if (author == null) { + return [{ firstName: undefined, lastName: undefined }]; + } + + if (new RegExp(/\b(and)+/, 'i').exec(author)) { + return author + .split(new RegExp(/\b(and|,)+/, 'i')) + .map((a) => a.trim()) + .filter((a) => ['and', ',', ''].indexOf(a.toLowerCase()) === -1) + .map(parseSingleAuthor); + } + + if (author.includes(';')) { + return author + .split(';') + .map((a) => a.trim()) + .map(parseSingleAuthor); + } + + return [parseSingleAuthor(author)]; +}; + +const parseSingleAuthor = (author: string): Author => { + const hasComma = author.includes(','); + + if (hasComma) { + const names = splitAndTrim(',', author); + return { + firstName: names.length == 1 ? undefined : splitAndTrim(' ', names[names.length - 1])[0], + lastName: names[0], + }; + } + + const names = splitAndTrim(' ', author); + return { + firstName: names.length == 1 ? undefined : names[0], + lastName: names[names.length - 1], + }; +}; + +const splitAndTrim = (needle: string, author: string): string[] => { + return author + .split(needle) + .map((a) => a.trim()) + .map((a) => a.replace(/\.$/, '')); +}; diff --git a/src/utils/shortenTitle.spec.ts b/src/utils/shortenTitle.spec.ts index 9e9852d..8d4a6be 100644 --- a/src/utils/shortenTitle.spec.ts +++ b/src/utils/shortenTitle.spec.ts @@ -1,46 +1,46 @@ -import { shortenTitle } from '~/utils'; - -describe('Santize title for Obsidian environment', () => { - it('strip book description in title after colon', () => { - const santizedTitle = shortenTitle( - 'Book Yourself Solid: The Fastest, Easiest, and Most Reliable System for Getting More Clients Than You Can Handle Even if You Hate Marketing and Selling' - ); - expect(santizedTitle).toEqual('Book Yourself Solid'); - }); - - it('strips text after the last colon when multiple exist', () => { - const santizedTitle = shortenTitle('Summary: Sapiens: A Brief History of Humankind'); - expect(santizedTitle).toEqual('Summary: Sapiens'); - }); - - it('remove reserved characters — single quote', () => { - const santizedTitle = shortenTitle( - "The Manager's Path: A Guide for Tech Leaders Navigating Growth and Change" - ); - expect(santizedTitle).toEqual('The Managers Path'); - }); - - it('remove reserved characters — single quote with other special characters', () => { - const santizedTitle = shortenTitle( - 'Rich Dad Poor Dad: What the Rich Teach Their Kids About Money That the Poor and Middle Class Do Not!' - ); - expect(santizedTitle).toEqual('Rich Dad Poor Dad'); - }); - - it('remove any title content inside brackets', () => { - const santizedTitle = shortenTitle( - 'The Discipline of Teams (Harvard Business Review Classics)' - ); - expect(santizedTitle).toEqual('The Discipline of Teams'); - }); - - it('trims any leading or trailing spaces', () => { - const santizedTitle = shortenTitle(' The Warm-Hearted Snowman '); - expect(santizedTitle).toEqual('The Warm-Hearted Snowman'); - }); - - it('replace [] with ()', () => { - const santizedTitle = shortenTitle('Ricochet Joe [Kindle in Motion]'); - expect(santizedTitle).toEqual('Ricochet Joe (Kindle in Motion)'); - }); -}); +import { shortenTitle } from '~/utils'; + +describe('Santize title for Obsidian environment', () => { + it('strip book description in title after colon', () => { + const santizedTitle = shortenTitle( + 'Book Yourself Solid: The Fastest, Easiest, and Most Reliable System for Getting More Clients Than You Can Handle Even if You Hate Marketing and Selling' + ); + expect(santizedTitle).toEqual('Book Yourself Solid'); + }); + + it('strips text after the last colon when multiple exist', () => { + const santizedTitle = shortenTitle('Summary: Sapiens: A Brief History of Humankind'); + expect(santizedTitle).toEqual('Summary: Sapiens'); + }); + + it('remove reserved characters — single quote', () => { + const santizedTitle = shortenTitle( + "The Manager's Path: A Guide for Tech Leaders Navigating Growth and Change" + ); + expect(santizedTitle).toEqual('The Managers Path'); + }); + + it('remove reserved characters — single quote with other special characters', () => { + const santizedTitle = shortenTitle( + 'Rich Dad Poor Dad: What the Rich Teach Their Kids About Money That the Poor and Middle Class Do Not!' + ); + expect(santizedTitle).toEqual('Rich Dad Poor Dad'); + }); + + it('remove any title content inside brackets', () => { + const santizedTitle = shortenTitle( + 'The Discipline of Teams (Harvard Business Review Classics)' + ); + expect(santizedTitle).toEqual('The Discipline of Teams'); + }); + + it('trims any leading or trailing spaces', () => { + const santizedTitle = shortenTitle(' The Warm-Hearted Snowman '); + expect(santizedTitle).toEqual('The Warm-Hearted Snowman'); + }); + + it('replace [] with ()', () => { + const santizedTitle = shortenTitle('Ricochet Joe [Kindle in Motion]'); + expect(santizedTitle).toEqual('Ricochet Joe (Kindle in Motion)'); + }); +}); diff --git a/src/utils/shortenTitle.ts b/src/utils/shortenTitle.ts index e070a63..07ad750 100644 --- a/src/utils/shortenTitle.ts +++ b/src/utils/shortenTitle.ts @@ -1,9 +1,9 @@ -export const shortenTitle = (title: string): string => { - return title - .replace(/ *\([^)]*\) */g, '') // remove parenthesis and contents from title - .replace(/:([^:]*)$/g, '') // remove text after last colon - .replace(/[']/g, '') // remove single quotes from title - .replace('[', '(') // replace [ with ( - .replace(']', ')') // replace ] with ) - .trim(); -}; +export const shortenTitle = (title: string): string => { + return title + .replace(/ *\([^)]*\) */g, '') // remove parenthesis and contents from title + .replace(/:([^:]*)$/g, '') // remove text after last colon + .replace(/[']/g, '') // remove single quotes from title + .replace('[', '(') // replace [ with ( + .replace(']', ')') // replace ] with ) + .trim(); +}; diff --git a/src/utils/stringBuffer.spec.ts b/src/utils/stringBuffer.spec.ts index 9db3842..2922e29 100644 --- a/src/utils/stringBuffer.spec.ts +++ b/src/utils/stringBuffer.spec.ts @@ -1,130 +1,130 @@ -import faker from 'faker'; - -import { sb } from '~/utils'; - -describe('StringBuffer', () => { - describe('insertLinesAt', () => { - it('Add a single line mid string', () => { - const content = `Line 1 -Line 2 -Line 3`; - - const expected = `Line 1 -Line 1a -Line 2 -Line 3`; - - const actual = sb(content) - .insertLinesAt([{ line: 2, content: 'Line 1a' }]) - .toString(); - - expect(actual).toEqual(expected); - }); - - it('Add a single line at the start of string', () => { - const content = `Line 1 -Line 2 -Line 3`; - - const expected = `Line 1a -Line 1 -Line 2 -Line 3`; - - const actual = sb(content) - .insertLinesAt([{ line: 1, content: 'Line 1a' }]) - .toString(); - - expect(actual).toEqual(expected); - }); - - it('Line numbers must start at 1', () => { - expect(() => { - sb(faker.datatype.string()).insertLinesAt([ - { line: 2, content: faker.datatype.string() }, - { line: 0, content: faker.datatype.string() }, - ]); - }).toThrow('Line numbers must start from 1'); - }); - - it('Inserting multiple lines in document', () => { - const content = `Line 1 -Line 2 -Line 3`; - - const expected = `Before Line 1 -Line 1 -After Line 1 -Line 2 -After Line 2 -Line 3`; - - const actual = sb(content) - .insertLinesAt([ - { line: 1, content: 'Before Line 1' }, - { line: 2, content: 'After Line 1' }, - { line: 3, content: 'After Line 2' }, - ]) - .toString(); - - expect(actual).toEqual(expected); - }); - - it('Inserting multiple subsequent lines at the same location', () => { - const content = `Line 1 -Line 2 -Line 3`; - - const expected = `Line 1 -Line 2 -Line 2a -Line 2b -Line 3`; - - const actual = sb(content) - .insertLinesAt([ - { line: 3, content: 'Line 2a' }, - { line: 3, content: 'Line 2b' }, - ]) - .toString(); - - expect(actual).toEqual(expected); - }); - }); - - describe('append', () => { - it('Append multiple lines to a string', () => { - const content = `Line 1 -Line 2 -Line 3`; - - const expected = `Line 1 -Line 2 -Line 3 -hello -there`; - - const actual = sb(content).append(['hello', 'there']).toString(); - - expect(actual).toEqual(expected); - }); - }); - - describe('getLine', () => { - it('Append multiple lines to a string', () => { - const content = `Line 1 -Line 2 -Line 3`; - - expect(sb(content).getLine(1)).toEqual('Line 1'); - expect(sb(content).getLine(2)).toEqual('Line 2'); - expect(sb(content).getLine(3)).toEqual('Line 3'); - }); - - it('Append multiple lines to a string', () => { - expect(() => { - sb(faker.datatype.string()).getLine(0); - }).toThrow('Line numbers must start from 1'); - }); - }); -}); +import faker from 'faker'; + +import { sb } from '~/utils'; + +describe('StringBuffer', () => { + describe('insertLinesAt', () => { + it('Add a single line mid string', () => { + const content = `Line 1 +Line 2 +Line 3`; + + const expected = `Line 1 +Line 1a +Line 2 +Line 3`; + + const actual = sb(content) + .insertLinesAt([{ line: 2, content: 'Line 1a' }]) + .toString(); + + expect(actual).toEqual(expected); + }); + + it('Add a single line at the start of string', () => { + const content = `Line 1 +Line 2 +Line 3`; + + const expected = `Line 1a +Line 1 +Line 2 +Line 3`; + + const actual = sb(content) + .insertLinesAt([{ line: 1, content: 'Line 1a' }]) + .toString(); + + expect(actual).toEqual(expected); + }); + + it('Line numbers must start at 1', () => { + expect(() => { + sb(faker.datatype.string()).insertLinesAt([ + { line: 2, content: faker.datatype.string() }, + { line: 0, content: faker.datatype.string() }, + ]); + }).toThrow('Line numbers must start from 1'); + }); + + it('Inserting multiple lines in document', () => { + const content = `Line 1 +Line 2 +Line 3`; + + const expected = `Before Line 1 +Line 1 +After Line 1 +Line 2 +After Line 2 +Line 3`; + + const actual = sb(content) + .insertLinesAt([ + { line: 1, content: 'Before Line 1' }, + { line: 2, content: 'After Line 1' }, + { line: 3, content: 'After Line 2' }, + ]) + .toString(); + + expect(actual).toEqual(expected); + }); + + it('Inserting multiple subsequent lines at the same location', () => { + const content = `Line 1 +Line 2 +Line 3`; + + const expected = `Line 1 +Line 2 +Line 2a +Line 2b +Line 3`; + + const actual = sb(content) + .insertLinesAt([ + { line: 3, content: 'Line 2a' }, + { line: 3, content: 'Line 2b' }, + ]) + .toString(); + + expect(actual).toEqual(expected); + }); + }); + + describe('append', () => { + it('Append multiple lines to a string', () => { + const content = `Line 1 +Line 2 +Line 3`; + + const expected = `Line 1 +Line 2 +Line 3 +hello +there`; + + const actual = sb(content).append(['hello', 'there']).toString(); + + expect(actual).toEqual(expected); + }); + }); + + describe('getLine', () => { + it('Append multiple lines to a string', () => { + const content = `Line 1 +Line 2 +Line 3`; + + expect(sb(content).getLine(1)).toEqual('Line 1'); + expect(sb(content).getLine(2)).toEqual('Line 2'); + expect(sb(content).getLine(3)).toEqual('Line 3'); + }); + + it('Append multiple lines to a string', () => { + expect(() => { + sb(faker.datatype.string()).getLine(0); + }).toThrow('Line numbers must start from 1'); + }); + }); +}); diff --git a/src/utils/stringBuffer.ts b/src/utils/stringBuffer.ts index 711726b..780e307 100644 --- a/src/utils/stringBuffer.ts +++ b/src/utils/stringBuffer.ts @@ -1,66 +1,66 @@ -type LineEntry = { - line: number; - content: string; -}; - -type LineEntryMatch = LineEntry & { - match: RegExpMatchArray; -}; - -export class StringBuffer { - private lines: string[]; - - constructor(content: string) { - this.lines = content.split('\n'); - } - - public getLine(line: number): string { - if (line <= 0) { - throw new Error('Line numbers must start from 1'); - } - - return this.lines[line - 1]; - } - - public find(predicate: (entry: LineEntry) => boolean): LineEntry[] { - return this.lines - .map((content, index): LineEntry => ({ line: index + 1, content })) - .filter(predicate); - } - - public match(regex: RegExp): LineEntryMatch[] { - return this.lines.map((content, index) => { - const match = content.match(regex); - return { line: index + 1, content, match }; - }); - } - - public insertLinesAt(newLines: LineEntry[]): StringBuffer { - if (newLines.some((l) => l.line <= 0)) { - throw new Error('Line numbers must start from 1'); - } - - for (let i = newLines.length - 1; i >= 0; i--) { - const newLine = newLines[i]; - this.lines.splice(newLine.line - 1, 0, newLine.content); - } - - return this; - } - - public replace(line: LineEntry): StringBuffer { - this.lines[line.line] = line.content; - return this; - } - - public append(newLines: string[]): StringBuffer { - this.lines.push(...newLines); - return this; - } - - public toString(): string { - return this.lines.join('\n'); - } -} - -export const sb = (content: string): StringBuffer => new StringBuffer(content); +type LineEntry = { + line: number; + content: string; +}; + +type LineEntryMatch = LineEntry & { + match: RegExpMatchArray; +}; + +export class StringBuffer { + private lines: string[]; + + constructor(content: string) { + this.lines = content.split('\n'); + } + + public getLine(line: number): string { + if (line <= 0) { + throw new Error('Line numbers must start from 1'); + } + + return this.lines[line - 1]; + } + + public find(predicate: (entry: LineEntry) => boolean): LineEntry[] { + return this.lines + .map((content, index): LineEntry => ({ line: index + 1, content })) + .filter(predicate); + } + + public match(regex: RegExp): LineEntryMatch[] { + return this.lines.map((content, index) => { + const match = content.match(regex); + return { line: index + 1, content, match }; + }); + } + + public insertLinesAt(newLines: LineEntry[]): StringBuffer { + if (newLines.some((l) => l.line <= 0)) { + throw new Error('Line numbers must start from 1'); + } + + for (let i = newLines.length - 1; i >= 0; i--) { + const newLine = newLines[i]; + this.lines.splice(newLine.line - 1, 0, newLine.content); + } + + return this; + } + + public replace(line: LineEntry): StringBuffer { + this.lines[line.line] = line.content; + return this; + } + + public append(newLines: string[]): StringBuffer { + this.lines.push(...newLines); + return this; + } + + public toString(): string { + return this.lines.join('\n'); + } +} + +export const sb = (content: string): StringBuffer => new StringBuffer(content); diff --git a/tsconfig.json b/tsconfig.json index fe910c0..765b67e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,22 +1,22 @@ -{ - "extends": "@tsconfig/svelte/tsconfig.json", - - "include": ["src/**/*", "tests/**/*", "webpack.config.ts"], - "exclude": ["node_modules/*"], - "compilerOptions": { - "types": ["node", "svelte", "jest"], - "baseUrl": ".", - "paths": { - "src": ["src/*", "tests/*"], - "~/*": ["src/*"] - }, - "resolveJsonModule": true - }, - // Fixes errors when changing `module` to ES in the above compiler options - // See: https://github.com/webpack/webpack-cli/issues/2458#issuecomment-846635277 - "ts-node": { - "compilerOptions": { - "module": "commonjs" - } - } -} +{ + "extends": "@tsconfig/svelte/tsconfig.json", + + "include": ["src/**/*", "tests/**/*", "webpack.config.ts"], + "exclude": ["node_modules/*"], + "compilerOptions": { + "types": ["node", "svelte", "jest"], + "baseUrl": ".", + "paths": { + "src": ["src/*", "tests/*"], + "~/*": ["src/*"] + }, + "resolveJsonModule": true + }, + // Fixes errors when changing `module` to ES in the above compiler options + // See: https://github.com/webpack/webpack-cli/issues/2458#issuecomment-846635277 + "ts-node": { + "compilerOptions": { + "module": "commonjs" + } + } +} diff --git a/versions.json b/versions.json index 686cb4c..b082400 100644 --- a/versions.json +++ b/versions.json @@ -1,3 +1,3 @@ -{ - "0.0.1": "0.10.2" -} +{ + "0.0.1": "0.10.2" +} diff --git a/webpack.config.ts b/webpack.config.ts index 5a8c2d0..3743a4a 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -1,18 +1,19 @@ -import CopyPlugin from 'copy-webpack-plugin'; -import dotenv from 'dotenv'; -import path from 'path'; -import sveltePreprocess from 'svelte-preprocess'; -import TerserPlugin from 'terser-webpack-plugin'; -import { Configuration, DefinePlugin } from 'webpack'; +export {}; +const CopyPlugin = require('copy-webpack-plugin'); +const dotenv = require('dotenv'); +const path = require('path'); +const sveltePreprocess = require('svelte-preprocess'); +const TerserPlugin = require('terser-webpack-plugin'); +const { Configuration, DefinePlugin } = require('webpack'); -import pack from './package.json'; +const pack = require('./package.json'); dotenv.config(); const isProduction = process.env.NODE_ENV === 'production'; const releaseVersion = pack.version; -const config: Configuration = { +const config: typeof Configuration = { entry: './src/index.ts', output: { path: path.resolve(__dirname, 'dist'), @@ -88,4 +89,4 @@ const config: Configuration = { }, }; -export default config; +module.exports = config; \ No newline at end of file