]> git.wh0rd.org - chrome-ext/template.git/commitdiff
initial template main
authorMike Frysinger <vapier@gmail.com>
Sat, 26 Apr 2025 23:26:08 +0000 (19:26 -0400)
committerMike Frysinger <vapier@gmail.com>
Thu, 17 Jul 2025 20:08:26 +0000 (16:08 -0400)
19 files changed:
.eslintrc.js [new file with mode: 0644]
.gitignore [new file with mode: 0644]
.html-minifier.conf [new file with mode: 0644]
.prettierrc.js [new file with mode: 0644]
.terser.json [new file with mode: 0644]
README.md [new file with mode: 0644]
UNLICENSE [new file with mode: 0644]
css/options.css [new file with mode: 0644]
html/options.html [new file with mode: 0644]
images/icon-128.png [new file with mode: 0644]
images/icon-16.png [new file with mode: 0644]
images/icon-48.png [new file with mode: 0644]
js/background.js [new file with mode: 0644]
js/options.js [new file with mode: 0644]
manifest-files.py [new file with mode: 0755]
manifest.files [new file with mode: 0644]
manifest.json [new file with mode: 0644]
package.json [new file with mode: 0644]
postcss.config.js [new file with mode: 0644]

diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644 (file)
index 0000000..d12a929
--- /dev/null
@@ -0,0 +1,221 @@
+// Copyright 2021 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+  root: true,
+  env: {
+    browser: true,
+    // This allows the runtime environment (i.e. objects).
+    es6: true,
+  },
+  parserOptions: {
+    // This sets the syntax parsing level.
+    ecmaVersion: 2020,
+    sourceType: 'module',
+  },
+
+  plugins: ['jsdoc'],
+
+  // See https://eslint.org/docs/rules/ for details.
+  // These rules were picked based on the existing codebase.  If you find one
+  // to be too onerous and not required by the styleguide, feel free to discuss.
+  rules: {
+    'array-bracket-spacing': 'error',
+    'arrow-parens': ['error', 'always'],
+    'arrow-spacing': ['error', {before: true, after: true}],
+    'block-spacing': ['error', 'always'],
+    'comma-dangle': ['error', 'always-multiline'],
+    'comma-spacing': 'error',
+    'comma-style': 'error',
+    'curly': 'error',
+    'default-param-last': 'error',
+    'eol-last': 'error',
+    'func-call-spacing': 'error',
+    'generator-star-spacing': ['error', 'after'],
+    // l/I: Depending on the font, these are hard to distinguish.
+    'id-blacklist': ['error', 'l', 'I', 'self'],
+    'keyword-spacing': 'error',
+    'lines-between-class-members': 'error',
+    'max-len': ['error', {code: 80, ignoreUrls: true}],
+    'new-parens': 'error',
+    'no-alert': 'error',
+    'no-case-declarations': 'error',
+    'no-cond-assign': 'error',
+    'no-const-assign': 'error',
+    'no-control-regex': 'error',
+    'no-debugger': 'error',
+    'no-dupe-args': 'error',
+    'no-dupe-class-members': 'error',
+    'no-dupe-keys': 'error',
+    'no-duplicate-case': 'error',
+    'no-empty': 'error',
+    'no-empty-character-class': 'error',
+    'no-eval': 'error',
+    'no-ex-assign': 'error',
+    // We want 'all' (nestedBinaryExpressions=false), but this breaks
+    // closure-compiler casts.
+    'no-extra-parens': ['error', 'functions'],
+    'no-extra-semi': 'error',
+    'no-implied-eval': 'error',
+    'no-invalid-regexp': 'error',
+    'no-irregular-whitespace': 'error',
+    'no-label-var': 'error',
+    'no-mixed-spaces-and-tabs': 'error',
+    'no-multi-spaces': ['error', {ignoreEOLComments: true}],
+    'no-multiple-empty-lines': 'error',
+    'no-new': 'error',
+    'no-new-func': 'error',
+    'no-new-object': 'error',
+    'no-new-wrappers': 'error',
+    'no-obj-calls': 'error',
+    'no-octal': 'error',
+    'no-octal-escape': 'error',
+    'no-return-await': 'error',
+    'no-script-url': 'error',
+    'no-self-assign': 'error',
+    'no-self-compare': 'error',
+    'no-sequences': 'error',
+    'no-shadow-restricted-names': 'error',
+    'no-tabs': 'error',
+    'no-template-curly-in-string': 'error',
+    'no-throw-literal': 'error',
+    'no-trailing-spaces': 'error',
+    'no-unmodified-loop-condition': 'error',
+    'no-unneeded-ternary': 'error',
+    'no-unreachable': 'error',
+    'no-useless-call': 'error',
+    'no-useless-concat': 'error',
+    'no-useless-escape': 'error',
+    'no-useless-return': 'error',
+    'no-var': 'error',
+    'no-void': 'error',
+    // We allow TODO comments.
+    'no-warning-comments': [
+      'error',
+      {
+        terms: ['fix', 'fixme', 'xxx'],
+      },
+    ],
+    'no-whitespace-before-property': 'error',
+    'no-with': 'error',
+    'object-curly-newline': ['error', {consistent: true}],
+    'object-curly-spacing': 'error',
+    'one-var-declaration-per-line': 'error',
+    'prefer-const': 'error',
+    'prefer-numeric-literals': 'error',
+    'prefer-rest-params': 'error',
+    'quote-props': ['error', 'consistent'],
+    'quotes': [
+      'error',
+      'single',
+      {avoidEscape: true, allowTemplateLiterals: true},
+    ],
+    'radix': 'error',
+    'rest-spread-spacing': 'error',
+    'semi': ['error', 'always'],
+    'semi-spacing': 'error',
+    'semi-style': ['error', 'last'],
+    'space-before-blocks': ['error', 'always'],
+    'space-before-function-paren': [
+      'error',
+      {
+        anonymous: 'never',
+        named: 'never',
+        asyncArrow: 'always',
+      },
+    ],
+    'space-in-parens': ['error', 'never'],
+    'space-infix-ops': 'error',
+    'space-unary-ops': 'error',
+    'spaced-comment': ['error', 'always'],
+    'switch-colon-spacing': ['error', {after: true, before: false}],
+    'symbol-description': 'error',
+    'template-curly-spacing': ['error', 'never'],
+    'unicode-bom': ['error', 'never'],
+    'use-isnan': 'error',
+    'valid-typeof': 'error',
+    'yield-star-spacing': ['error', 'after'],
+    'yoda': 'error',
+
+    'jsdoc/check-access': 'error',
+    'jsdoc/check-alignment': 'error',
+    'jsdoc/check-examples': 'error',
+    // We want hanging indentation, but this check requires none everywhere.
+    'jsdoc/check-indentation': 'off',
+    'jsdoc/check-param-names': 'error',
+    'jsdoc/check-property-names': 'error',
+    // Make sure this is disabled as this rejects closure syntax.
+    'jsdoc/check-syntax': 'off',
+    'jsdoc/check-tag-names': 'error',
+    // This is disabled until this crash is resolved:
+    // https://github.com/gajus/eslint-plugin-jsdoc/issues/389
+    'jsdoc/check-types': 'off',
+    // We don't use these tags in the project.
+    'jsdoc/check-values': 'off',
+    'jsdoc/empty-tags': 'error',
+    'jsdoc/implements-on-classes': 'error',
+    // Can't turn on until require-description is enabled.
+    'jsdoc/match-description': 'off',
+    'jsdoc/newline-after-description': 'error',
+    // This is only for TypeScript which we don't care about.
+    'jsdoc/no-types': 'off',
+    // This would be nice to turn on, but requires a lot more research.
+    // See valid-types setting below too.
+    'jsdoc/no-undefined-types': 'off',
+    // TODO(vapier): Turn this on.
+    'jsdoc/require-description': 'off',
+    // TODO(vapier): Turn this on.
+    'jsdoc/require-description-complete-sentence': 'off',
+    // We don't want to require examples.
+    'jsdoc/require-example': 'off',
+    // TODO(vapier): Turn this on.
+    'jsdoc/require-file-overview': 'off',
+    'jsdoc/require-hyphen-before-param-description': ['error', 'never'],
+    // TODO(vapier): Turn this on.
+    'jsdoc/require-jsdoc': 'off',
+    'jsdoc/require-param': 'off',
+    // TODO(vapier): Turn this on.
+    'jsdoc/require-param-description': 'off',
+    'jsdoc/require-param-name': 'error',
+    'jsdoc/require-param-type': 'error',
+    'jsdoc/require-returns': 'off',
+    'jsdoc/require-returns-check': 'error',
+    // TODO(vapier): Turn this on.
+    'jsdoc/require-returns-description': 'off',
+    'jsdoc/require-returns-type': 'error',
+    // This would be nice to turn on, but requires a lot more research.
+    'jsdoc/valid-types': 'off',
+  },
+
+  settings: {
+    // https://github.com/BenoitZugmeyer/eslint-plugin-html#settings
+    html: {
+      // TODO(vapier): Would like to use .html.in, but doesn't work right.
+      // https://github.com/BenoitZugmeyer/eslint-plugin-html/issues/127
+      'html-extensions': ['.html', '.in'],
+    },
+
+    // https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc
+    jsdoc: {
+      mode: 'closure',
+      preferredTypes: {
+        object: 'Object',
+      },
+      tagNamePreference: {
+        // While not explicitly defined, Google/Chromium JS style guides only
+        // use these keyword forms, as does the closure compiler docs.
+        augments: 'extends',
+        constant: 'const',
+        class: 'constructor',
+        file: 'fileoverview',
+        returns: 'return',
+        yields: 'yield',
+
+        // Stub out closure-specific tags so they get ignored.
+        // TODO(vapier): Delete this after upgrade to newer jsdoc.
+        closurePrimitive: '',
+      },
+    },
+  },
+};
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..89df27f
--- /dev/null
@@ -0,0 +1,15 @@
+# Various temp files and editor configs.
+*~
+\#*
+.#*
+*.swp
+.eslintcache
+.vscode
+
+# Stuff we build for distribution.
+dist
+*.zip
+
+# npm related dirs.
+node_modules
+package-lock.json
diff --git a/.html-minifier.conf b/.html-minifier.conf
new file mode 100644 (file)
index 0000000..21a31cc
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "collapseBooleanAttributes": true,
+  "collapseWhitespace": true,
+  "customAttrCollapse": ".*",
+  "decodeEntities": true,
+  "html5": true,
+  "includeAutoGeneratedTags": false,
+  "keepClosingSlash": false,
+  "maxLineLength": 0,
+  "processConditionalComments": true,
+  "processScripts": [
+    "text/html"
+  ],
+  "removeAttributeQuotes": true,
+  "removeComments": true,
+  "removeEmptyAttributes": true,
+  "removeEmptyElements": true,
+  "removeOptionalTags": true,
+  "removeRedundantAttributes": true,
+  "removeScriptTypeAttributes": true,
+  "removeStyleLinkTypeAttributes": true,
+  "removeTagWhitespace": true,
+  "sortAttributes": true,
+  "sortClassName": true,
+  "trimCustomFragments": true,
+  "useShortDoctype": true
+}
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644 (file)
index 0000000..245d4f3
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2021 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+  bracketSpacing: false,
+  trailingComma: 'all',
+  quoteProps: 'consistent',
+  singleQuote: true,
+};
diff --git a/.terser.json b/.terser.json
new file mode 100644 (file)
index 0000000..f661b00
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "compress": {
+    "unused": false
+  },
+  "ecma": 2024,
+  "mangle": false,
+  "module": true
+}
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..8f6ba0b
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+Template for Chrome extensions.
diff --git a/UNLICENSE b/UNLICENSE
new file mode 100644 (file)
index 0000000..efb9808
--- /dev/null
+++ b/UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+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 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.
+
+For more information, please refer to <https://unlicense.org/>
diff --git a/css/options.css b/css/options.css
new file mode 100644 (file)
index 0000000..4f82c66
--- /dev/null
@@ -0,0 +1,8 @@
+/**
+ * Styles used by the options page.
+ *
+ * Written by Mike Frysinger <vapier@gmail.com>.  Released into the public domain.
+ */
+
+@media (prefers-color-scheme: dark) {
+}
diff --git a/html/options.html b/html/options.html
new file mode 100644 (file)
index 0000000..4c21677
--- /dev/null
@@ -0,0 +1,10 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <title>Options</title>
+    <link rel="stylesheet" href="../css/options.css" />
+    <script type="module" src="../js/options.js"></script>
+  </head>
+  <body></body>
+</html>
diff --git a/images/icon-128.png b/images/icon-128.png
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/images/icon-16.png b/images/icon-16.png
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/images/icon-48.png b/images/icon-48.png
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/js/background.js b/js/background.js
new file mode 100644 (file)
index 0000000..5cd428c
--- /dev/null
@@ -0,0 +1,5 @@
+// Written by Mike Frysinger <vapier@gmail.com>.  Released into the public domain.
+
+/**
+ * @fileoverview Code for the background page.
+ */
diff --git a/js/options.js b/js/options.js
new file mode 100644 (file)
index 0000000..31567c1
--- /dev/null
@@ -0,0 +1,5 @@
+// Written by Mike Frysinger <vapier@gmail.com>.  Released into the public domain.
+
+/**
+ * @fileoverview Code for the options page.
+ */
diff --git a/manifest-files.py b/manifest-files.py
new file mode 100755 (executable)
index 0000000..944bbec
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+# Written by Mike Frysinger <vapier@gmail.com>.  Released into the public domain.
+
+import argparse
+import fnmatch
+import json
+import sys
+
+
+def get_parser() -> argparse.ArgumentParser:
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument("--filter", default="*")
+    parser.add_argument("manifest", nargs="?", default="manifest.json")
+    parser.add_argument("filelist", nargs="?", default="manifest.files")
+    return parser
+
+
+def main(argv: list[str]) -> int | None:
+    parser = get_parser()
+    opts = parser.parse_args(argv)
+
+    with open(opts.manifest) as fp:
+        data = json.load(fp)
+
+    files = set(data["icons"].values())
+    for script in data.get("content_scripts", []):
+        files.update(script.get("css", ()))
+        files.update(script.get("js", ()))
+    files.add(data["background"]["service_worker"])
+    files.add(data["options_ui"]["page"])
+
+    with open(opts.filelist) as fp:
+        for line in fp:
+            line = line.split("#", 1)[0].strip()
+            if not line:
+                continue
+            if line in files:
+                print(
+                    "warning: redundant entry in %s: %s" % (opts.filelist, line),
+                    file=sys.stderr,
+                )
+            else:
+                files.add(line)
+
+    print("\n".join(sorted(x for x in files if fnmatch.fnmatch(x, opts.filter))))
+
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv[1:]))
diff --git a/manifest.files b/manifest.files
new file mode 100644 (file)
index 0000000..da0e4e9
--- /dev/null
@@ -0,0 +1,3 @@
+# List of files to include in the extension.  Files listed in the manifest.json
+# are automatically included and do not need listing here.
+css/options.css
diff --git a/manifest.json b/manifest.json
new file mode 100644 (file)
index 0000000..3966eeb
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "key": "",
+  "short_name": "",
+  "name": "",
+  "description": "",
+  "version": "0.0.0",
+  "manifest_version": 3,
+  "icons": {
+    "16": "images/icon-16.png",
+    "48": "images/icon-48.png",
+    "128": "images/icon-128.png"
+  },
+  "options_ui": {
+    "page": "html/options.html",
+    "open_in_tab": false
+  },
+  "permissions": [],
+  "action": {},
+  "background": {
+    "type": "module",
+    "service_worker": "js/background.js"
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644 (file)
index 0000000..46fa0b2
--- /dev/null
@@ -0,0 +1,45 @@
+{
+  "name": "",
+  "version": "0.0.0",
+  "author": "vapier@gmail.com",
+  "license": "Unlicense",
+  "scripts": {
+    "ci": "npm-run-all --parallel 'format:* -- --check' lint",
+    "dist": "rm -rf dist ext.zip && mkdir -p dist/css dist/fonts dist/html dist/images dist/js && npm-run-all --parallel dist:* && cd dist && zip -r ../ext.zip .",
+    "dist:css": "postcss `./manifest-files.py --filter 'css/*.css'` --dir dist/css/",
+    "dist:fonts": "[ -d fonts ] || exit 0; cp `./manifest-files.py --filter 'fonts/*'` dist/fonts/",
+    "dist:html": "set -e; for f in `./manifest-files.py --filter '*.html'`; do html-minifier -c .html-minifier.conf $f >dist/$f; done",
+    "dist:js": "set -e; for f in `./manifest-files.py --filter '*.js'`; do terser --config-file .terser.json $f --output dist/$f; done",
+    "dist:json": "sed '/\"key\":/d' manifest.json | json-minify >dist/manifest.json",
+    "dist:images": "cp `./manifest-files.py --filter 'images/*'` dist/images/",
+    "fix": "npm-run-all --parallel fix:*",
+    "fix:js": "eslint --cache --fix js/*.js",
+    "format": "npm-run-all --parallel 'format:* -- --write'",
+    "format:css": "prettier css/*.css",
+    "format:js": "prettier js/*.js .*.js *.js",
+    "format:json": "prettier *.json",
+    "format:html": "prettier html/*.html",
+    "format:md": "prettier *.md",
+    "format:py": "black *.py #",
+    "lint": "npm-run-all --parallel lint:*",
+    "lint:js": "eslint --cache js/*.js",
+    "lint:md": "markdownlint *.md",
+    "release": "npm-run-all --parallel ci dist",
+    "start": "http-server -a localhost -c-1 --cors ."
+  },
+  "devDependencies": {
+    "cssnano": "~7",
+    "eslint": "~9",
+    "eslint-plugin-jsdoc": "~50",
+    "html-minifier": "~4",
+    "http-server": "~14",
+    "json-minify": "^1.0.0",
+    "markdownlint-cli": "~0",
+    "npm-run-all": "~4",
+    "postcss": "~8",
+    "postcss-cli": "~8",
+    "prettier": "~3",
+    "terser": "~5"
+  },
+  "dependencies": {}
+}
diff --git a/postcss.config.js b/postcss.config.js
new file mode 100644 (file)
index 0000000..c4cf788
--- /dev/null
@@ -0,0 +1,7 @@
+module.exports = {
+  plugins: [
+    require('cssnano')({
+      preset: 'default',
+    }),
+  ],
+};