[
  {
    "path": ".eslintignore",
    "content": "node_modules\n*.d.ts\ngenerator-temp\n"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"root\": true,\n  \"env\": {\n    \"browser\": true,\n    \"es6\": true,\n    \"node\": true\n  },\n  \"extends\": [\n    \"eslint:recommended\",\n    \"plugin:@typescript-eslint/recommended\",\n    \"plugin:@typescript-eslint/eslint-recommended\",\n    \"plugin:@typescript-eslint/recommended-requiring-type-checking\"\n  ],\n  \"parser\": \"@typescript-eslint/parser\",\n  \"parserOptions\": {\n    \"project\": \"tsconfig.json\",\n    \"sourceType\": \"module\"\n  },\n  \"plugins\": [\n    \"eslint-plugin-import\",\n    \"eslint-plugin-prefer-arrow\",\n    \"@typescript-eslint\",\n    \"@typescript-eslint/eslint-plugin\"\n  ],\n  \"rules\": {\n    \"@typescript-eslint/adjacent-overload-signatures\": \"error\",\n    \"@typescript-eslint/array-type\": [\n      \"error\",\n      {\n        \"default\": \"array\"\n      }\n    ],\n    \"@typescript-eslint/await-thenable\": \"error\",\n    \"@typescript-eslint/ban-ts-comment\": \"warn\",\n    \"@typescript-eslint/ban-types\": [\n      \"warn\",\n      {\n        \"types\": {\n          \"Object\": {\n            \"message\": \"Avoid using the `Object` type. Did you mean `object`?\"\n          },\n          \"Function\": {\n            \"message\": \"Avoid using the `Function` type. Prefer a specific function type, like `() => void`.\"\n          },\n          \"Boolean\": {\n            \"message\": \"Avoid using the `Boolean` type. Did you mean `boolean`?\"\n          },\n          \"Number\": {\n            \"message\": \"Avoid using the `Number` type. Did you mean `number`?\"\n          },\n          \"String\": {\n            \"message\": \"Avoid using the `String` type. Did you mean `string`?\"\n          },\n          \"Symbol\": {\n            \"message\": \"Avoid using the `Symbol` type.  Did you mean `symbol`?\"\n          }\n        }\n      }\n    ],\n    \"@typescript-eslint/consistent-type-assertions\": \"error\",\n    \"@typescript-eslint/dot-notation\": \"error\",\n    \"@typescript-eslint/explicit-module-boundary-types\": \"warn\",\n    \"@typescript-eslint/indent\": [\n      \"error\",\n      2\n    ],\n    \"@typescript-eslint/member-delimiter-style\": [\n      \"error\",\n      {\n        \"multiline\": {\n          \"delimiter\": \"none\",\n          \"requireLast\": false\n        },\n        \"singleline\": {\n          \"delimiter\": \"comma\",\n          \"requireLast\": false\n        }\n      }\n    ],\n    \"@typescript-eslint/member-ordering\": \"off\",\n    \"@typescript-eslint/naming-convention\": \"off\",\n    \"@typescript-eslint/no-array-constructor\": \"error\",\n    \"@typescript-eslint/no-empty-function\": \"error\",\n    \"@typescript-eslint/no-empty-interface\": \"error\",\n    \"@typescript-eslint/no-explicit-any\": \"off\",\n    \"@typescript-eslint/no-extra-non-null-assertion\": \"error\",\n    \"@typescript-eslint/no-extra-semi\": \"error\",\n    \"@typescript-eslint/no-floating-promises\": \"error\",\n    \"@typescript-eslint/no-for-in-array\": \"error\",\n    \"@typescript-eslint/no-implied-eval\": \"off\",\n    \"@typescript-eslint/no-inferrable-types\": \"error\",\n    \"@typescript-eslint/no-misused-new\": \"error\",\n    \"@typescript-eslint/no-misused-promises\": \"error\",\n    \"@typescript-eslint/no-namespace\": \"error\",\n    \"@typescript-eslint/no-non-null-asserted-optional-chain\": \"error\",\n    \"@typescript-eslint/no-non-null-assertion\": \"warn\",\n    \"@typescript-eslint/no-parameter-properties\": \"off\",\n    \"@typescript-eslint/no-shadow\": [\n      \"error\",\n      {\n        \"hoist\": \"all\"\n      }\n    ],\n    \"@typescript-eslint/no-this-alias\": \"error\",\n    \"@typescript-eslint/no-unnecessary-type-assertion\": \"error\",\n    \"@typescript-eslint/no-unsafe-assignment\": \"off\",\n    \"@typescript-eslint/no-unsafe-call\": \"off\",\n    \"@typescript-eslint/no-unsafe-member-access\": \"off\",\n    \"@typescript-eslint/no-unsafe-return\": \"error\",\n    \"@typescript-eslint/no-unused-expressions\": \"error\",\n    \"@typescript-eslint/no-unused-vars\": [\n      \"error\",\n      {\n        \"argsIgnorePattern\": \"^_\"\n      }\n    ],\n    \"@typescript-eslint/no-use-before-define\": \"off\",\n    \"@typescript-eslint/no-var-requires\": \"off\",\n    \"@typescript-eslint/prefer-as-const\": \"error\",\n    \"@typescript-eslint/prefer-for-of\": \"error\",\n    \"@typescript-eslint/prefer-function-type\": \"error\",\n    \"@typescript-eslint/prefer-namespace-keyword\": \"error\",\n    \"@typescript-eslint/prefer-regexp-exec\": \"off\",\n    \"@typescript-eslint/quotes\": [\n      \"error\",\n      \"single\",\n      {\n        \"avoidEscape\": true\n      }\n    ],\n    \"@typescript-eslint/require-await\": \"error\",\n    \"@typescript-eslint/restrict-plus-operands\": \"error\",\n    \"@typescript-eslint/restrict-template-expressions\": \"off\",\n    \"@typescript-eslint/semi\": [\n      \"error\",\n      \"never\"\n    ],\n    \"@typescript-eslint/triple-slash-reference\": [\n      \"error\",\n      {\n        \"path\": \"always\",\n        \"types\": \"prefer-import\",\n        \"lib\": \"always\"\n      }\n    ],\n    \"@typescript-eslint/unbound-method\": \"error\",\n    \"@typescript-eslint/unified-signatures\": \"error\",\n    \"arrow-body-style\": \"error\",\n    \"arrow-parens\": [\n      \"error\",\n      \"as-needed\"\n    ],\n    \"brace-style\": [\n      \"error\",\n      \"stroustrup\",\n      {\n        \"allowSingleLine\": true\n      }\n    ],\n    \"comma-dangle\": [\n      \"error\",\n      {\n        \"objects\": \"always-multiline\",\n        \"arrays\": \"always-multiline\",\n        \"functions\": \"never\"\n      }\n    ],\n    \"complexity\": \"off\",\n    \"constructor-super\": \"error\",\n    \"curly\": [\n      \"error\",\n      \"multi-line\"\n    ],\n    \"eol-last\": \"error\",\n    \"eqeqeq\": [\n      \"error\",\n      \"smart\"\n    ],\n    \"guard-for-in\": \"error\",\n    \"id-blacklist\": [\n      \"error\",\n      \"any\",\n      \"Number\",\n      \"number\",\n      \"String\",\n      \"string\",\n      \"Boolean\",\n      \"boolean\",\n      \"Undefined\",\n      \"undefined\"\n    ],\n    \"id-match\": \"error\",\n    \"import/order\": \"off\",\n    \"linebreak-style\": [\n      \"error\",\n      \"unix\"\n    ],\n    \"max-classes-per-file\": \"off\",\n    \"max-len\": [\n      \"warn\",\n      {\n        \"code\": 240\n      }\n    ],\n    \"new-parens\": \"off\",\n    \"no-array-constructor\": \"off\",\n    \"no-bitwise\": \"error\",\n    \"no-caller\": \"error\",\n    \"no-cond-assign\": \"off\",\n    \"no-console\": \"error\",\n    \"no-debugger\": \"error\",\n    \"no-empty\": [\n      \"error\",\n      {\n        \"allowEmptyCatch\": true\n      }\n    ],\n    \"no-empty-function\": \"off\",\n    \"no-eval\": \"error\",\n    \"no-extra-semi\": \"off\",\n    \"no-fallthrough\": \"off\",\n    \"no-implied-eval\": \"off\",\n    \"no-invalid-this\": \"off\",\n    \"no-irregular-whitespace\": \"error\",\n    \"no-magic-numbers\": \"off\",\n    \"@typescript-eslint/no-magic-numbers\": [ \"error\", {\n      \"ignore\": [ -1, 0, 1, 2 ],\n      \"ignoreEnums\": true\n    }],\n    \"no-new-wrappers\": \"error\",\n    \"no-redeclare\": \"error\",\n    \"no-throw-literal\": \"error\",\n    \"no-trailing-spaces\": \"error\",\n    \"no-undef-init\": \"error\",\n    \"no-underscore-dangle\": [\n      \"error\",\n      {\n        \"allowAfterThis\": true\n      }\n    ],\n    \"no-unsafe-finally\": \"error\",\n    \"no-unused-labels\": \"error\",\n    \"no-unused-vars\": \"off\",\n    \"no-var\": \"error\",\n    \"object-shorthand\": \"error\",\n    \"one-var\": [\n      \"off\",\n      \"never\"\n    ],\n    \"prefer-arrow/prefer-arrow-functions\": [\n      \"error\",\n      {\n        \"allowStandaloneDeclarations\": true\n      }\n    ],\n    \"prefer-const\": [\n      \"error\",\n      {\n        \"destructuring\": \"all\"\n      }\n    ],\n    \"prefer-object-spread\": \"error\",\n    \"prefer-template\": \"error\",\n    \"quote-props\": [\n      \"error\",\n      \"as-needed\"\n    ],\n    \"radix\": \"off\",\n    \"require-await\": \"off\",\n    \"space-before-function-paren\": [\n      \"error\",\n      {\n        \"anonymous\": \"never\",\n        \"named\": \"never\",\n        \"asyncArrow\": \"always\"\n      }\n    ],\n    \"spaced-comment\": [\n      \"error\",\n      \"always\",\n      {\n        \"markers\": [\n          \"/\"\n        ]\n      }\n    ],\n    \"use-isnan\": \"error\",\n    \"valid-typeof\": \"off\",\n    \"yoda\": \"error\",\n    \"@typescript-eslint/consistent-type-definitions\": \"off\",\n    \"no-new-func\": \"off\"\n  },\n  \"ignorePatterns\": [\n    \"webpack.config.ts\",\n    \"util/*.ts\",\n    \"minitests/*.ts\",\n    \"content/minitests/*.ts\"\n  ]\n}\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: release\n\non:\n  push:\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v2\n    - name: install node\n      uses: actions/setup-node@v1\n      with:\n        node-version: 14.x\n    - name: Cache node dependencies\n      uses: actions/cache@v2\n      env:\n        cache-name: cache-dependencies\n      with:\n        path: |\n          ~/.npm\n        key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }}\n        restore-keys: |\n          ${{ runner.os }}-build-${{ env.cache-name }}-\n          ${{ runner.os }}-build-\n          ${{ runner.os }}-\n    - name: install node dependencies\n      run: npm install\n    - name: build\n      run: npm run build\n    - name: release\n      run: npm run release\n      env:\n        GITHUB_TOKEN: ${{ github.token }}\n"
  },
  {
    "path": ".gitignore",
    "content": "wiki\ngen\nbuild\n*~\n*.swp\n*.debug\n*.cache\n*.status\n*.js.map\n*.tmp\n*.xpi\nnode_modules\n.env\n.eslintcache\n"
  },
  {
    "path": "README.md",
    "content": "# This plugin has been superceeded by Zotero Attachment Scanner\n\nwhich can be found at https://github.com/SciImage/zotero-attachment-scanner\n\n## Zotero Storage Scanner\n\nA Zotero plugin to remove the broken & duplicate attachment link of the bibliography\n\nInstall by downloading the [latest version](https://github.com/retorquere/zotero-storage-scanner/releases/latest).\n\nThis plugin scans your attachments of storage to remove the missing & duplicate attachment link. The combination of the duplicated bibliography in Zotero could create a lot of duplicate attachments. Also when you use a plugin/ third-party software to directly remove the PDF of the bibliography, the attachment link becomes broken in Zotero. This plugin is designed to solve the problem.\n\nInstall by downloading the latest version and installing it from the Zotero add-ons screen.\n\n## A little background on how the plugin works\n\nThere is no UI, this plugin scans your library after being launched from tools->storage scanner in the background.\n\nIf you run zotero-storage-scanner you will see a zotero process (name dependand on OS) kick off in your proccess manager (top, activity monitor, Task Manager), however as it works through your library it live updates two tags `#duplicates` and `#broken` as it goes. If those tags have no items attached to them after some time (variable depending on size of library) then you are golden, if there are entries tagged in either then your likely have duplicate articles or a file/DB has issues been identified with the most likely cause being a \"missing\" PDF sometimes caused by incomplete syncing.\n"
  },
  {
    "path": "chrome.manifest",
    "content": "content\tzotero-storage-scanner\t\t\t\tcontent/\nlocale\tzotero-storage-scanner\ten-US\t\tlocale/en-US/\nskin\tzotero-storage-scanner\tdefault\t\tskin/\n\noverlay\tchrome://zotero/content/zoteroPane.xul\tchrome://zotero-storage-scanner/content/zotero-storage-scanner.xul\n"
  },
  {
    "path": "content/zotero-storage-scanner.ts",
    "content": "declare const Zotero: any\n// declare const Components: any\n\nconst monkey_patch_marker = 'StorageScannerMonkeyPatched'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction patch(object, method, patcher) {\n  if (object[method][monkey_patch_marker]) return\n  object[method] = patcher(object[method])\n  object[method][monkey_patch_marker] = true\n}\n\nclass StorageScanner {\n  private duplicates: string\n  private noattachments: string\n  private globals: Record<string, any>\n\n  // eslint-disable-next-line @typescript-eslint/require-await\n  public async load(globals: Record<string, any>) {\n    this.globals = globals\n    if (!this.duplicates) {\n      // https://groups.google.com/d/msg/zotero-dev/QYNGxqTSpaQ/uvGObVNlCgAJ\n      await Zotero.Schema.schemaUpdatePromise\n\n      let attachmentTypeID\n      for (const type of await Zotero.DB.queryAsync(\"select itemTypeID from itemTypes where typeName = 'attachment'\")) {\n        attachmentTypeID = type.itemTypeID\n      }\n\n      this.duplicates = `\n        SELECT\n          item.itemID,\n          attachment.path,\n          CASE attachment.linkMode WHEN ${Zotero.Attachments.LINK_MODE_LINKED_URL} THEN 1 ELSE 0 END AS isLinkedURL,\n          COALESCE(duplicates.duplicates, 1) as duplicates\n        FROM items item\n        LEFT JOIN itemAttachments attachment ON attachment.itemID = item.itemID\n        LEFT JOIN (\n          SELECT parentItemID, contentType, COUNT(*) as duplicates\n          FROM itemAttachments\n          WHERE linkMode <> ${Zotero.Attachments.LINK_MODE_LINKED_URL} AND itemID NOT IN (select itemID from deletedItems)\n          GROUP BY parentItemID, contentType\n        ) duplicates ON attachment.parentItemID = duplicates.parentItemID AND attachment.contentType = duplicates.contentType\n        WHERE\n            item.itemTypeID = ${attachmentTypeID}\n          AND\n            item.itemID NOT IN (select itemID from deletedItems)\n          AND\n            (\n                attachment.path IS NULL\n              OR\n                (attachment.linkMode IS NOT NULL AND attachment.linkMode <> ${Zotero.Attachments.LINK_MODE_LINKED_URL})\n            )\n      `.replace(/\\n/g, ' ').trim()\n      Zotero.debug(`StorageScanner: duplicates = ${this.duplicates}`)\n\n      this.noattachments = `\n\t      SELECT item.itemID, COUNT(attachment.itemID) AS attachments\n        FROM items item\n        JOIN itemTypes ON item.itemTypeID = itemTypes.itemTypeID AND itemTypes.typeName NOT IN ('note', 'attachment')\n        LEFT JOIN itemAttachments attachment ON attachment.parentItemID = item.itemID AND attachment.itemID NOT IN (select itemID from deletedItems)\n        WHERE item.itemID NOT IN (select itemID from deletedItems)\n        GROUP BY item.itemID\n\n        UNION\n\n        SELECT itemID, CASE WHEN parentItemID IS NULL THEN 0 ELSE 1 END as attachments\n        FROM itemAttachments attachment\n        WHERE attachment.itemID NOT IN (select itemID from deletedItems)\n      `.replace(/\\n/g, ' ').trim()\n    }\n  }\n\n  public async scan() {\n    if (!this.duplicates) return\n\n    // Zotero.Attachments.LINK_MODE_LINKED_URL // ignore this\n    // Zotero.Attachments.LINK_MODE_IMPORTED_URL // snapshot\n    // Zotero.Attachments.LINK_MODE_IMPORTED_FILE\n    // LINK_MODE_LINKED_FILE\n\n    const attachments = (await Zotero.DB.queryAsync(this.duplicates)) || [] // apparently 'no results' gets me 'null', not an empty list. Sure, ok.\n\n    Zotero.debug(`StorageScanner.attachments: ${attachments.length}`)\n\n    for (const attachment of attachments) {\n      Zotero.debug(`StorageScanner.attachment: ${JSON.stringify({itemID: attachment.itemID, path: attachment.path, duplicates: attachment.duplicates})}`)\n      const item = await Zotero.Items.getAsync(attachment.itemID)\n      /*\n        because getAsync isn't \"same as get but asynchronously\" but \"sort\n        of same as get but asynchronously, however if the object was not\n        already loaded by some user interaction you're out of luck\". BTW,\n        if you could know at this point that getAsync would get you a loaded\n        object, you could just have called \"get\". Nice.\n        https://groups.google.com/d/msg/zotero-dev/QYNGxqTSpaQ/nGKJakGnBAAJ\n        https://groups.google.com/d/msg/zotero-dev/naAxXIbpDhU/iSLpXo-UBQAJ\n      */\n      await item.loadAllData()\n\n      let save = false\n\n      if (this.updateTag(item, '#broken_attachments', !attachment.isLinkedURL && !(await item.getFilePathAsync()))) save = true\n      if (this.updateTag(item, '#multiple_attachments_of_same_type', attachment.duplicates > 1)) save = true\n      Zotero.debug(`StorageScanner.save: ${save}`)\n\n      if (save) await item.saveTx()\n    }\n\n    const items = (await Zotero.DB.queryAsync(this.noattachments)) || []\n    Zotero.debug(`StorageScanner.items: ${items.length}`)\n    for (const status of items) {\n      const item = await Zotero.Items.getAsync(status.itemID)\n      await item.loadAllData()\n\n      let save = false\n      if (this.updateTag(item, '#nosource ', !status.attachments)) save = true\n      if (save) await item.saveTx()\n    }\n  }\n\n  private updateTag(item, tag, add) {\n    Zotero.debug(`StorageScanner.updateTag('${item.id}.${tag}', ist: ${item.hasTag(tag)}, soll: ${add})`)\n    if (add) {\n      if (item.hasTag(tag)) return false\n      item.addTag(tag)\n    }\n    else {\n      if (!item.hasTag(tag)) return false\n      item.removeTag(tag)\n    }\n\n    return true\n  }\n}\n\nZotero.StorageScanner = new StorageScanner\n"
  },
  {
    "path": "content/zotero-storage-scanner.xul",
    "content": "<?xml version=\"1.0\"?>\n<?xml-stylesheet href=\"chrome://zotero-storage-scanner/skin/overlay.css\" type=\"text/css\"?>\n<!DOCTYPE window SYSTEM \"chrome://zotero-storage-scanner/locale/zotero-storage-scanner.dtd\">\n\n<overlay id=\"zotero-storage-scanner-overlay\" xmlns=\"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul\">\n  <script>\n    var globals = Function('return this')();\n    var zotero_storage_scanner_zoteropane = null;\n  </script>\n  <stringbundleset>\n    <stringbundle id=\"zotero-storage-scanner-strings\" src=\"chrome://zotero-storage-scanner/locale/zotero-storage-scanner.properties\"/>\n  </stringbundleset>\n\n  <menupopup id=\"menu_ToolsPopup\">\n    <menuitem label=\"&zotero-storage-scanner.name;\" oncommand=\"Zotero.StorageScanner.scan()\"/>\n  </menupopup>\n\t\n\t<!-- Include the main extension logic -->\n  <script src=\"chrome://zotero-storage-scanner/content/zotero-storage-scanner.js\"/>\n  <script>\n    window.addEventListener('load', async function() {\n      try {\n        Zotero.debug('zotero-storage-scanner startup')\n        await Zotero.StorageScanner.load(globals)\n        Zotero.debug('zotero-storage-scanner started')\n      } catch (err) {\n        Zotero.debug(`zotero-storage-scanner ZoteroPane overlay error: ${err.message}\\n${err.stack ||''}`)\n      }\n    })\n  </script>\n</overlay>\n"
  },
  {
    "path": "esbuild.js",
    "content": "const path = require('path')\nconst fs = require('fs')\nconst esbuild = require('esbuild')\nconst rmrf = require('rimraf')\n\nrequire('zotero-plugin/copy-assets')\nrequire('zotero-plugin/rdf')\nrequire('zotero-plugin/version')\n\nasync function build() {\n  rmrf.sync('gen')\n  await esbuild.build({\n    bundle: true,\n    format: 'iife',\n    target: ['firefox60'],\n    entryPoints: [ 'content/zotero-storage-scanner.ts' ],\n    outdir: 'build/content',\n    banner: { js: 'if (!Zotero.StorageScanner) {\\n' },\n    footer: { js: '\\n}' },\n  })\n}\n\nbuild().catch(err => {\n  console.log(err)\n  process.exit(1)\n})\n"
  },
  {
    "path": "locale/en-US/zotero-storage-scanner.dtd",
    "content": "<!ENTITY zotero-storage-scanner.name \"Storage Scanner\">\n"
  },
  {
    "path": "locale/en-US/zotero-storage-scanner.properties",
    "content": ""
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"zotero-storage-scanner\",\n  \"version\": \"5.0.12\",\n  \"description\": \"Scan attachments for duplicates\",\n  \"scripts\": {\n    \"lint\": \"eslint . --ext .ts --cache --cache-location .eslintcache/\",\n    \"prebuild\": \"npm run lint\",\n    \"build\": \"tsc --noEmit && node esbuild.js\",\n    \"postbuild\": \"zotero-plugin-zipup build zotero-storage-scanner\",\n    \"release\": \"zotero-plugin-release\",\n    \"postversion\": \"git push --follow-tags\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/retorquere/zotero-storage-scanner.git\"\n  },\n  \"author\": {\n    \"name\": \"Emiliano Heyns\",\n    \"email\": \"emiliano.heyns@iris-advies.com\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/retorquere/zotero-storage-scanner/issues\"\n  },\n  \"homepage\": \"https://github.com/retorquere/zotero-storage-scanner\",\n  \"dependencies\": {\n    \"@types/mocha\": \"^9.1.1\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.25.0\",\n    \"@typescript-eslint/parser\": \"^5.25.0\",\n    \"esbuild\": \"^0.14.39\",\n    \"eslint\": \"^8.16.0\",\n    \"eslint-plugin-import\": \"^2.26.0\",\n    \"eslint-plugin-jsdoc\": \"^39.3.0\",\n    \"eslint-plugin-prefer-arrow\": \"^1.2.3\",\n    \"mkdirp\": \"^1.0.4\",\n    \"rimraf\": \"^3.0.2\",\n    \"ts-node\": \"^10.8.0\",\n    \"typescript\": \"^4.6.4\",\n    \"zotero-plugin\": \"^1.4.2\"\n  },\n  \"xpi\": {\n    \"name\": \"Storage Scanner for Zotero\",\n    \"updateLink\": \"https://github.com/retorquere/zotero-storage-scanner/releases/download/v{version}/zotero-storage-scanner-{version}.xpi\",\n    \"releaseURL\": \"https://github.com/retorquere/zotero-storage-scanner/releases/download/release/\"\n  }\n}\n"
  },
  {
    "path": "skin/default/overlay.css",
    "content": ""
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"importHelpers\": true,\n    \"target\": \"es2017\",\n    \"disableSizeLimit\": true,\n    \"module\": \"commonjs\",\n    \"noImplicitAny\": false,\n    \"esModuleInterop\": true,\n    \"removeComments\": false,\n    \"preserveConstEnums\": false,\n    \"sourceMap\": false,\n    \"downlevelIteration\": true,\n    \"lib\": [ \"es2017\", \"dom\" ],\n    \"typeRoots\": [\n      \"./typings\",\n      \"./node_modules/@types\"\n    ]\n  },\n  \"include\": [\n    \"content/**/*\",\n    \"resource/**/*\",\n    \"*.ts\"\n  ],\n  \"exclude\": [\n    \"node_modules\",\n    \"**/*.spec.ts\",\n    \"typings\"\n  ]\n}\n"
  }
]