diff --git a/README.md b/README.md index fd1285c..300816f 100644 --- a/README.md +++ b/README.md @@ -3,39 +3,32 @@ [![Build Status](https://travis-ci.org/announce/crx-mortal.svg?branch=master)](https://travis-ci.org/announce/crx-mortal) -## Getting Started +## Getting started -1. Install the Chrome Extension at [**Chrome Web Store**](https://chrome.google.com/webstore/detail/crx-mortal/plbhlfecmbmkphfgcpoijlidjapddidj?utm_source=github) +1. Install the extension at [**Chrome Web Store**](https://chrome.google.com/webstore/detail/crx-mortal/fgnhcpkfpdiaeikgdjbgfodclmnpbjno?utm_source=github) +2. Submit your game log at https://mjai.ekyu.moe/ + +## How crx-mortal works + +This extension annotates your less optimal moves based on the Mortal's score where `πτ​(a∣s)×100 < 5.0`. ## Development Prerequisites: -* Docker * Node v18 +* `jq` command -Run: +To run in the development mode: ```bash -./app start +npm run watch ``` -For the release: +To release the extension: ```bash -./app release +npm run build ``` -## Project Links - -* Upstream work: [trunk](https://github.com/announce/crx-mortal/compare/master...ymkjp:master) -* Demo app: [crx](https://chrome.google.com/webstore/detail/crx-mortal/plbhlfecmbmkphfgcpoijlidjapddidj?utm_source=github) -* Release: [Chrome Developer Dashboard](https://chrome.google.com/webstore/developer/dashboard) - -## Documents - -* CRX - * [Declare Permissions](https://developer.chrome.com/extensions/declare_permissions) - * [chrome\.i18n](https://developer.chrome.com/extensions/i18n) -* ImageMagick - * [Text Handling \- IM v6](http://www.imagemagick.org/Usage/text/#label_bestfit) +Then submit the bundled package at [**Chrome Developer Dashboard**](https://chrome.google.com/webstore/developer/dashboard). diff --git a/package.json b/package.json index c0d1df8..05648dd 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,18 @@ { "name": "crx-mortal", - "version": "1.0.0", - "description": "crx-mortal", - "main": "index.js", + "version": "1.0.1", + "description": "A Chrome extension to help Mahjong players spot their less optimal moves", "scripts": { "watch": "webpack --config webpack/webpack.dev.js --watch", "build": "npm-run-all style clean build:** bundle", + "build:manifest": "./app update-manifest-version", "build:js": "webpack --config webpack/webpack.prod.js", - "bundle": "zip -r dist-$(date +%s).zip ./dist/*", + "bundle": "./app bundle-dist", "clean": "rimraf dist", "test": "npx jest", "style": "prettier --write \"src/**/*.{ts,tsx}\" \"public/**/*.{json,html,css}\"" }, - "author": "", + "author": "Kenta Yamamoto ", "license": "MIT", "repository": { "type": "git", diff --git a/public/manifest.json b/public/manifest.json index b9ce70a..962a619 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,18 +1,20 @@ { "manifest_version": 3, - "name": "crx-mortal", - "description": "annotating bad-moves", - "version": "1.0", - + "description": "This extension helps Mahjong players spot their less optimal moves", + "version": "1.0.1", "action": { "default_icon": "icon.png" }, - "content_scripts": [ { - "matches": ["https://mjai.ekyu.moe/*"], - "js": ["js/vendor.js", "js/content_script.js"] + "matches": [ + "https://mjai.ekyu.moe/*" + ], + "js": [ + "js/vendor.js", + "js/content_script.js" + ] } ] } diff --git a/script/app.bash b/script/app.bash index 067a3b3..9ac1d6d 100755 --- a/script/app.bash +++ b/script/app.bash @@ -3,20 +3,16 @@ app () { set -u - start () { - export NODE_ENV=development - npm start + bundle-dist () { + [[ $(command -v zip) ]] || return + zip -r ./var/dist-$(date +%s).zip ./dist/* } - release () { - export NODE_ENV=production - npm run build - } - - die () { - MESSAGE="${1:-Something went wrong.}" - echo "[$(basename "$0")] ERROR: ${MESSAGE}" >&2 - exit 1 + update-manifest-version () { + [[ $(command -v jq) ]] || return + PACKAGE_VERSION="$(jq '.version' package.json)" + MANIFEST="$(jq ".version = ${PACKAGE_VERSION}" public/manifest.json)" + echo -e "${MANIFEST}" > public/manifest.json } usage () { diff --git a/src/content_script.tsx b/src/content_script.tsx index b202906..adbc944 100644 --- a/src/content_script.tsx +++ b/src/content_script.tsx @@ -1,48 +1,56 @@ /** * https://mjai.ekyu.moe/report/888288d74f7ed24c.html#kyoku-6-0 */ +class CrxMortal { + static DEFAULT_THRESHOLD = 5.0; + createSpan = (text: string) => { + const span = document.createElement("span"); + span.innerText = text; + span.style.background = `#ffd5d5`; + span.style.margin = `auto .5rem`; + span.style.fontWeight = `bold`; + return span; + }; -const THRESHOLD = 5.0; -const createSpan = (text: string) => { - const suggestion = document.createElement("span"); - suggestion.innerText = text; - suggestion.style.background = `#ffd5d5`; - suggestion.style.margin = `auto .5rem`; - suggestion.style.fontWeight = `bold`; - return suggestion; -}; + main = () => { + const scores = [...document.querySelectorAll(`body section details.entry`)] + .map((element) => { + const tile = element.querySelector(`span svg.tile use`) as SVGAElement; + if (tile === null) { + return null; + } + // '#pai-9s' + const score = element + .querySelector(`table [href*="${tile.href.baseVal}"]`) + ?.closest(`tr`) + ?.querySelector(`td:nth-child(3)`) as HTMLElement; + const scoreNum = parseFloat(score.textContent || ``); + if (scoreNum < CrxMortal.DEFAULT_THRESHOLD) { + const suggestion = this.createSpan(score.textContent || ``); + element.querySelector(`:scope > span`)?.appendChild(suggestion); + } else { + element.removeAttribute(`open`); + } + return scoreNum; + }) + .filter((score) => score !== null); -const scores = [...document.querySelectorAll(`body section details.entry`)] - .map((element) => { - const tile = element.querySelector(`span svg.tile use`) as SVGAElement; - if (tile === null) { - return null; - } - // '#pai-9s' - const score = element - .querySelector(`table [href*="${tile.href.baseVal}"]`) - ?.closest(`tr`) - ?.querySelector(`td:nth-child(3)`) as HTMLElement; - const scoreNum = parseFloat(score.textContent || ``); - if (scoreNum < THRESHOLD) { - const suggestion = createSpan(score.textContent || ``); - element.querySelector(`:scope > span`)?.appendChild(suggestion); - } else { - element.removeAttribute(`open`); - } - return scoreNum; - }) - .filter((score) => score !== null); - -const badMoves = scores.filter( - (score) => score !== null && score < THRESHOLD -).length; -const totalMoves = scores.length; - -const metrics = createSpan( - `${badMoves}/${totalMoves} = ${Math.round((badMoves / totalMoves) * 100)}%` -); -document - .querySelector("body > details.collapse:nth-child(6) > summary") - ?.appendChild(metrics); + const totalMoves = scores.length; + const badMoves = scores.filter( + (score) => score !== null && score < CrxMortal.DEFAULT_THRESHOLD + ).length; + const metrics = this.createSpan( + `${badMoves}/${totalMoves} = ${ + totalMoves > 0 ? Math.round((badMoves / totalMoves) * 100) : NaN + }%` + ); + document + .querySelector("body > details.collapse:nth-child(6) > summary") + ?.appendChild(metrics); + }; +} +if (require.main === module) { + const crx = new CrxMortal(); + crx.main(); +} diff --git a/src/popup.tsx b/src/popup.tsx index d4244f1..3444136 100644 --- a/src/popup.tsx +++ b/src/popup.tsx @@ -8,7 +8,7 @@ const Popup = () => { useEffect(() => { (async () => { await chrome.action.setBadgeText({ text: count.toString() }); - })() + })(); }, [count]); useEffect(() => {