├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ ├── addon-docs.yml │ ├── ci.yml │ ├── plan-release.yml │ ├── publish.yml │ └── push-dist.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc.cjs ├── .release-plan.json ├── .tool-versions ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── RELEASE.md ├── config └── ember-cli-update.json ├── ember-math-helpers ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc.cjs ├── .prettierrc.js ├── .template-lintrc.cjs ├── README.md ├── addon-main.cjs ├── babel.config.json ├── eslint.config.mjs ├── package.json ├── rollup.config.mjs ├── src │ ├── .gitkeep │ ├── helpers │ │ ├── abs.ts │ │ ├── acos.ts │ │ ├── acosh.ts │ │ ├── add.ts │ │ ├── asin.ts │ │ ├── asinh.ts │ │ ├── atan.ts │ │ ├── atan2.ts │ │ ├── atanh.ts │ │ ├── cbrt.ts │ │ ├── ceil.ts │ │ ├── clz32.ts │ │ ├── cos.ts │ │ ├── cosh.ts │ │ ├── div.ts │ │ ├── exp.ts │ │ ├── expm1.ts │ │ ├── floor.ts │ │ ├── fround.ts │ │ ├── gcd.ts │ │ ├── hypot.ts │ │ ├── imul.ts │ │ ├── lcm.ts │ │ ├── log-e.ts │ │ ├── log10.ts │ │ ├── log1p.ts │ │ ├── log2.ts │ │ ├── max.ts │ │ ├── min.ts │ │ ├── mod.ts │ │ ├── mult.ts │ │ ├── pow.ts │ │ ├── random.ts │ │ ├── round.ts │ │ ├── sign.ts │ │ ├── sin.ts │ │ ├── sqrt.ts │ │ ├── sub.ts │ │ ├── sum.ts │ │ ├── tan.ts │ │ ├── tanh.ts │ │ └── trunc.ts │ ├── index.ts │ └── template-registry.ts ├── tsconfig.json └── unpublished-development-types │ └── index.d.ts ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── test-app ├── .editorconfig ├── .ember-cli ├── .gitignore ├── .prettierignore ├── .prettierrc.js ├── .stylelintignore ├── .stylelintrc.js ├── .template-lintrc.js ├── .watchmanconfig ├── README.md ├── app ├── app.ts ├── components │ ├── .gitkeep │ ├── editable-templates.hbs │ ├── editable-templates.js │ ├── render-template.hbs │ └── render-template.js ├── config │ └── environment.d.ts ├── controllers │ └── .gitkeep ├── deprecation-workflow.ts ├── helpers │ └── .gitkeep ├── index.html ├── models │ └── .gitkeep ├── router.js ├── routes │ └── .gitkeep ├── styles │ └── app.css └── templates │ ├── application.hbs │ ├── docs.hbs │ ├── docs │ ├── index.md │ ├── playground.md │ └── usage.md │ ├── index.hbs │ └── not-found.hbs ├── config ├── addon-docs.js ├── deploy.js ├── ember-cli-update.json ├── ember-try.js ├── environment.js ├── optional-features.json └── targets.js ├── ember-cli-build.js ├── eslint.config.mjs ├── package.json ├── public ├── img │ └── ember-math-helpers.svg └── robots.txt ├── testem.js ├── tests ├── helpers │ ├── index.js │ ├── index.ts │ └── range.js ├── index.html ├── integration │ └── .gitkeep ├── test-helper.ts └── unit │ ├── .gitkeep │ └── helpers │ ├── abs-test.js │ ├── acos-test.js │ ├── acosh-test.js │ ├── add-test.js │ ├── asin-test.js │ ├── asinh-test.js │ ├── atan-test.js │ ├── atan2-test.js │ ├── atanh-test.js │ ├── cbrt-test.js │ ├── ceil-test.js │ ├── clz32-test.js │ ├── cos-test.js │ ├── cosh-test.js │ ├── div-test.js │ ├── exp-test.js │ ├── expm1-test.js │ ├── floor-test.js │ ├── fround-test.js │ ├── gcd-test.js │ ├── hypot-test.js │ ├── imul-test.js │ ├── lcm-test.js │ ├── log-e-test.js │ ├── log10-test.js │ ├── log1p-test.js │ ├── log2-test.js │ ├── max-test.js │ ├── min-test.js │ ├── mod-test.js │ ├── mult-test.js │ ├── pow-test.js │ ├── random-test.js │ ├── round-test.js │ ├── sign-test.js │ ├── sin-test.js │ ├── sqrt-test.js │ ├── sub-test.js │ ├── sum-test.js │ ├── tan-test.js │ ├── tanh-test.js │ └── trunc-test.js ├── tsconfig.json └── types └── global.d.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.hbs] 16 | insert_final_newline = false 17 | 18 | [*.{diff,md}] 19 | trim_trailing_whitespace = false 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "10:00" 8 | open-pull-requests-limit: 10 9 | labels: 10 | - dependencies 11 | ignore: 12 | - dependency-name: ember-cli 13 | versions: 14 | - ">= 0" 15 | -------------------------------------------------------------------------------- /.github/workflows/addon-docs.yml: -------------------------------------------------------------------------------- 1 | name: Publish Addon Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | tags: 9 | - "**" 10 | jobs: 11 | build: 12 | env: 13 | DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | token: ${{ secrets.GITHUB_TOKEN }} 20 | - name: Check for tags and set short-circuit condition 21 | id: check-tags 22 | run: | 23 | # Fetch tags pointing to the current commit 24 | TAGS=$(git tag --points-at $GITHUB_SHA) 25 | echo "Tags found: $TAGS" 26 | 27 | # Check if a tag exists and if the ref is 'refs/heads/main' or 'refs/heads/master' 28 | if [ -n "$TAGS" ] && ([[ "${GITHUB_REF}" == "refs/heads/main" ]] || [[ "${GITHUB_REF}" == "refs/heads/master" ]]); then 29 | echo "SHORT_CIRCUIT=true" >> $GITHUB_ENV 30 | else 31 | echo "SHORT_CIRCUIT=false" >> $GITHUB_ENV 32 | fi 33 | - uses: pnpm/action-setup@v4 34 | if: env.SHORT_CIRCUIT == 'false' 35 | - uses: actions/setup-node@v4 36 | if: env.SHORT_CIRCUIT == 'false' 37 | with: 38 | node-version: 20 39 | cache: pnpm 40 | - name: Install Dependencies 41 | if: env.SHORT_CIRCUIT == 'false' 42 | run: pnpm install --no-lockfile 43 | - name: Deploy Docs 44 | if: env.SHORT_CIRCUIT == 'false' 45 | run: | 46 | cd test-app 47 | pnpm ember deploy production 48 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | pull_request: {} 9 | 10 | concurrency: 11 | group: ci-${{ github.head_ref || github.ref }} 12 | cancel-in-progress: true 13 | 14 | jobs: 15 | test: 16 | name: 'Tests' 17 | runs-on: ubuntu-latest 18 | timeout-minutes: 10 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: pnpm/action-setup@v4 23 | - uses: actions/setup-node@v4 24 | with: 25 | node-version: 20 26 | cache: pnpm 27 | - name: Install Dependencies 28 | run: pnpm install --frozen-lockfile 29 | - name: Lint 30 | run: pnpm lint 31 | - name: Run Tests 32 | run: pnpm test 33 | 34 | floating: 35 | name: 'Floating Dependencies' 36 | runs-on: ubuntu-latest 37 | timeout-minutes: 10 38 | 39 | steps: 40 | - uses: actions/checkout@v4 41 | - uses: pnpm/action-setup@v4 42 | - uses: actions/setup-node@v4 43 | with: 44 | node-version: 20 45 | cache: pnpm 46 | - name: Install Dependencies 47 | run: pnpm install --no-lockfile 48 | - name: Run Tests 49 | run: pnpm test 50 | 51 | try-scenarios: 52 | name: ${{ matrix.try-scenario }} 53 | runs-on: ubuntu-latest 54 | needs: 'test' 55 | timeout-minutes: 10 56 | 57 | strategy: 58 | fail-fast: false 59 | matrix: 60 | try-scenario: 61 | - ember-lts-4.12 62 | - ember-lts-5.4 63 | - ember-release 64 | - ember-beta 65 | - ember-canary 66 | - embroider-safe 67 | - embroider-optimized 68 | 69 | steps: 70 | - uses: actions/checkout@v4 71 | - uses: pnpm/action-setup@v4 72 | - uses: actions/setup-node@v4 73 | with: 74 | node-version: 20 75 | cache: pnpm 76 | - name: Install Dependencies 77 | run: pnpm install --frozen-lockfile 78 | - name: Run Tests 79 | run: ./node_modules/.bin/ember try:one ${{ matrix.try-scenario }} --skip-cleanup 80 | working-directory: test-app 81 | automerge: 82 | needs: [test, try-scenarios] 83 | runs-on: ubuntu-latest 84 | permissions: 85 | pull-requests: write 86 | contents: write 87 | steps: 88 | - uses: fastify/github-action-merge-dependabot@v3.11.0 89 | with: 90 | github-token: ${{secrets.GITHUB_TOKEN}} 91 | -------------------------------------------------------------------------------- /.github/workflows/plan-release.yml: -------------------------------------------------------------------------------- 1 | name: Release Plan Review 2 | on: 3 | push: 4 | branches: 5 | - main 6 | - master 7 | pull_request_target: # This workflow has permissions on the repo, do NOT run code from PRs in this workflow. See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ 8 | types: 9 | - labeled 10 | - unlabeled 11 | 12 | concurrency: 13 | group: plan-release # only the latest one of these should ever be running 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | check-plan: 18 | name: "Check Release Plan" 19 | runs-on: ubuntu-latest 20 | outputs: 21 | command: ${{ steps.check-release.outputs.command }} 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | with: 26 | fetch-depth: 0 27 | ref: 'main' 28 | # This will only cause the `check-plan` job to have a "command" of `release` 29 | # when the .release-plan.json file was changed on the last commit. 30 | - id: check-release 31 | run: if git diff --name-only HEAD HEAD~1 | grep -w -q ".release-plan.json"; then echo "command=release"; fi >> $GITHUB_OUTPUT 32 | 33 | prepare-release-notes: 34 | name: Prepare Release Notes 35 | runs-on: ubuntu-latest 36 | timeout-minutes: 5 37 | needs: check-plan 38 | permissions: 39 | contents: write 40 | issues: read 41 | pull-requests: write 42 | outputs: 43 | explanation: ${{ steps.explanation.outputs.text }} 44 | # only run on push event if plan wasn't updated (don't create a release plan when we're releasing) 45 | # only run on labeled event if the PR has already been merged 46 | if: (github.event_name == 'push' && needs.check-plan.outputs.command != 'release') || (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true) 47 | 48 | steps: 49 | - uses: actions/checkout@v4 50 | # We need to download lots of history so that 51 | # github-changelog can discover what's changed since the last release 52 | with: 53 | fetch-depth: 0 54 | ref: 'main' 55 | - uses: pnpm/action-setup@v4 56 | - uses: actions/setup-node@v4 57 | with: 58 | node-version: 20 59 | cache: pnpm 60 | - run: pnpm install --frozen-lockfile 61 | - name: "Generate Explanation and Prep Changelogs" 62 | id: explanation 63 | run: | 64 | set +e 65 | pnpm release-plan prepare 2> >(tee -a release-plan-stderr.txt >&2) 66 | 67 | if [ $? -ne 0 ]; then 68 | echo 'text<> $GITHUB_OUTPUT 69 | cat release-plan-stderr.txt >> $GITHUB_OUTPUT 70 | echo 'EOF' >> $GITHUB_OUTPUT 71 | else 72 | echo 'text<> $GITHUB_OUTPUT 73 | jq .description .release-plan.json -r >> $GITHUB_OUTPUT 74 | echo 'EOF' >> $GITHUB_OUTPUT 75 | rm release-plan-stderr.txt 76 | fi 77 | env: 78 | GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }} 79 | 80 | - uses: peter-evans/create-pull-request@v7 81 | with: 82 | commit-message: "Prepare Release using 'release-plan'" 83 | labels: "internal" 84 | branch: release-preview 85 | title: Prepare Release 86 | body: | 87 | This PR is a preview of the release that [release-plan](https://github.com/embroider-build/release-plan) has prepared. To release you should just merge this PR 👍 88 | 89 | ----------------------------------------- 90 | 91 | ${{ steps.explanation.outputs.text }} 92 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # For every push to the master branch, this checks if the release-plan was 2 | # updated and if it was it will publish stable npm packages based on the 3 | # release plan 4 | 5 | name: Publish Stable 6 | 7 | on: 8 | workflow_dispatch: 9 | push: 10 | branches: 11 | - main 12 | - master 13 | 14 | concurrency: 15 | group: publish-${{ github.head_ref || github.ref }} 16 | cancel-in-progress: true 17 | 18 | jobs: 19 | check-plan: 20 | name: "Check Release Plan" 21 | runs-on: ubuntu-latest 22 | outputs: 23 | command: ${{ steps.check-release.outputs.command }} 24 | 25 | steps: 26 | - uses: actions/checkout@v4 27 | with: 28 | fetch-depth: 0 29 | ref: 'main' 30 | # This will only cause the `check-plan` job to have a result of `success` 31 | # when the .release-plan.json file was changed on the last commit. This 32 | # plus the fact that this action only runs on main will be enough of a guard 33 | - id: check-release 34 | run: if git diff --name-only HEAD HEAD~1 | grep -w -q ".release-plan.json"; then echo "command=release"; fi >> $GITHUB_OUTPUT 35 | 36 | publish: 37 | name: "NPM Publish" 38 | runs-on: ubuntu-latest 39 | needs: check-plan 40 | if: needs.check-plan.outputs.command == 'release' 41 | permissions: 42 | contents: write 43 | pull-requests: write 44 | id-token: write 45 | attestations: write 46 | 47 | steps: 48 | - uses: actions/checkout@v4 49 | - uses: pnpm/action-setup@v4 50 | - uses: actions/setup-node@v4 51 | with: 52 | node-version: 20 53 | # This creates an .npmrc that reads the NODE_AUTH_TOKEN environment variable 54 | registry-url: 'https://registry.npmjs.org' 55 | cache: pnpm 56 | - run: pnpm install --frozen-lockfile 57 | - name: npm publish 58 | run: NPM_CONFIG_PROVENANCE=true pnpm release-plan publish 59 | env: 60 | GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }} 61 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 62 | -------------------------------------------------------------------------------- /.github/workflows/push-dist.yml: -------------------------------------------------------------------------------- 1 | # Because this library needs to be built, 2 | # we can't easily point package.json files at the git repo for easy cross-repo testing. 3 | # 4 | # This workflow brings back that capability by placing the compiled assets on a "dist" branch 5 | # (configurable via the "branch" option below) 6 | name: Push dist 7 | 8 | on: 9 | push: 10 | branches: 11 | - main 12 | - master 13 | 14 | jobs: 15 | push-dist: 16 | name: Push dist 17 | runs-on: ubuntu-latest 18 | timeout-minutes: 10 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: pnpm/action-setup@v4 23 | - uses: actions/setup-node@v4 24 | with: 25 | node-version: 20 26 | cache: pnpm 27 | - name: Install Dependencies 28 | run: pnpm install --frozen-lockfile 29 | - uses: kategengler/put-built-npm-package-contents-on-branch@v2.0.0 30 | with: 31 | branch: dist 32 | token: ${{ secrets.GITHUB_TOKEN }} 33 | working-directory: 'ember-math-helpers' 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules/ 5 | 6 | # misc 7 | .env* 8 | .pnp* 9 | .pnpm-debug.log 10 | .sass-cache 11 | .eslintcache 12 | coverage/ 13 | npm-debug.log* 14 | yarn-error.log 15 | 16 | # ember-try 17 | /.node_modules.ember-try/ 18 | /package.json.ember-try 19 | /package-lock.json.ember-try 20 | /yarn.lock.ember-try 21 | /pnpm-lock.ember-try.yaml 22 | 23 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | #################### 2 | # super strict mode 3 | #################### 4 | auto-install-peers=false 5 | strict-peer-dependents=true 6 | resolve-peers-from-workspace-root=false 7 | 8 | ################ 9 | # Optimizations 10 | ################ 11 | # Less strict, but required for tooling to not barf on duplicate peer trees. 12 | # (many libraries declare the same peers, which resolve to the same 13 | # versions) 14 | peers-suffix-max-length=40 15 | dedupe-injected-deps=true 16 | dedupe-peer-dependents=true 17 | public-hoist-pattern[]=ember-source 18 | sync-injected-deps-after-scripts[]=build 19 | sync-injected-deps-after-scripts[]=sync 20 | inject-workspace-packages=true 21 | 22 | ################ 23 | # Compatibility 24 | ################ 25 | # highest is what everyone is used to, but 26 | # not ensuring folks are actually compatible with declared ranges. 27 | resolution-mode=highest 28 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Prettier is also run from each package, so the ignores here 2 | # protect against files that may not be within a package 3 | 4 | # misc 5 | !.* 6 | .lint-todo/ 7 | 8 | # ember-try 9 | /.node_modules.ember-try/ 10 | /pnpm-lock.ember-try.yaml 11 | -------------------------------------------------------------------------------- /.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | plugins: ['prettier-plugin-ember-template-tag'], 5 | singleQuote: true, 6 | }; 7 | -------------------------------------------------------------------------------- /.release-plan.json: -------------------------------------------------------------------------------- 1 | { 2 | "solution": { 3 | "ember-math-helpers": { 4 | "impact": "major", 5 | "oldVersion": "4.2.1", 6 | "newVersion": "5.0.0", 7 | "tagName": "latest", 8 | "constraints": [ 9 | { 10 | "impact": "major", 11 | "reason": "Appears in changelog section :boom: Breaking Change" 12 | } 13 | ], 14 | "pkgJSONPath": "./ember-math-helpers/package.json" 15 | } 16 | }, 17 | "description": "## Release (2025-04-07)\n\n* ember-math-helpers 5.0.0 (major)\n\n#### :boom: Breaking Change\n* `ember-math-helpers`\n * [#2053](https://github.com/RobbieTheWagner/ember-math-helpers/pull/2053) Drop support for Ember < 4.12 ([@RobbieTheWagner](https://github.com/RobbieTheWagner))\n\n#### Committers: 1\n- Robbie Wagner ([@RobbieTheWagner](https://github.com/RobbieTheWagner))\n" 18 | } 19 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | nodejs 20.19.0 2 | pnpm 10.7.1 -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Release (2025-04-07) 4 | 5 | * ember-math-helpers 5.0.0 (major) 6 | 7 | #### :boom: Breaking Change 8 | * `ember-math-helpers` 9 | * [#2053](https://github.com/RobbieTheWagner/ember-math-helpers/pull/2053) Drop support for Ember < 4.12 ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 10 | 11 | #### Committers: 1 12 | - Robbie Wagner ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 13 | 14 | ## Release (2024-12-10) 15 | 16 | ember-math-helpers 4.2.1 (patch) 17 | 18 | #### :bug: Bug Fix 19 | * `ember-math-helpers` 20 | * [#1872](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1872) Remove app reexport of index ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 21 | 22 | #### Committers: 1 23 | - Robbie Wagner ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 24 | 25 | ## Release (2024-12-06) 26 | 27 | ember-math-helpers 4.2.0 (minor) 28 | 29 | #### :rocket: Enhancement 30 | * `ember-math-helpers`, `test-app` 31 | * [#1863](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1863) More pnpm updates ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 32 | * Other 33 | * [#1861](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1861) pnpm update ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 34 | 35 | #### :house: Internal 36 | * Other 37 | * [#1862](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1862) Prepare Release ([@github-actions[bot]](https://github.com/apps/github-actions)) 38 | * [#1859](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1859) Prepare Release ([@github-actions[bot]](https://github.com/apps/github-actions)) 39 | * `test-app` 40 | * [#1858](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1858) Switch to release-plan ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 41 | 42 | #### Committers: 2 43 | - Robbie Wagner ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 44 | - [@github-actions[bot]](https://github.com/apps/github-actions) 45 | 46 | ## Release (2024-12-06) 47 | 48 | 49 | 50 | #### :rocket: Enhancement 51 | * [#1861](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1861) pnpm update ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 52 | 53 | #### :house: Internal 54 | * Other 55 | * [#1859](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1859) Prepare Release ([@github-actions[bot]](https://github.com/apps/github-actions)) 56 | * `test-app` 57 | * [#1858](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1858) Switch to release-plan ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 58 | 59 | #### Committers: 2 60 | - Robbie Wagner ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 61 | - [@github-actions[bot]](https://github.com/apps/github-actions) 62 | 63 | ## Release (2024-12-06) 64 | 65 | 66 | 67 | #### :house: Internal 68 | * `test-app` 69 | * [#1858](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1858) Switch to release-plan ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 70 | 71 | #### Committers: 1 72 | - Robbie Wagner ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 73 | 74 | ## v4.1.1 (2024-12-04) 75 | 76 | ## v4.1.0 (2024-12-04) 77 | 78 | #### :rocket: Enhancement 79 | * [#1798](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1798) Add Ember v6 Peer Support ([@jrjohnson](https://github.com/jrjohnson)) 80 | * [#1539](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1539) Re-export helpers from index ([@charlesfries](https://github.com/charlesfries)) 81 | * [#1423](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1423) use types shipped by ember-source ([@jelhan](https://github.com/jelhan)) 82 | 83 | #### :bug: Bug Fix 84 | * [#1694](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1694) fix: Make sure that global imports/exports do work ([@MichalBryxi](https://github.com/MichalBryxi)) 85 | 86 | #### :memo: Documentation 87 | * [#1857](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1857) Fix helper docs generation ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 88 | * [#1851](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1851) Add back addon-docs ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 89 | 90 | #### :house: Internal 91 | * [#1852](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1852) Switch to ember-repl ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 92 | * [#1844](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1844) Use workspace versions of ember-math-helpers, remove docfy ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 93 | 94 | #### Committers: 5 95 | - Charles Fries ([@charlesfries](https://github.com/charlesfries)) 96 | - Jeldrik Hanschke ([@jelhan](https://github.com/jelhan)) 97 | - Jon Johnson ([@jrjohnson](https://github.com/jrjohnson)) 98 | - Michal Bryxí ([@MichalBryxi](https://github.com/MichalBryxi)) 99 | - Robbie Wagner ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 100 | 101 | ## v4.0.0 (2023-11-02) 102 | 103 | #### :boom: Breaking Change 104 | * [#965](https://github.com/RobbieTheWagner/ember-math-helpers/pull/965) Support Ember 5, drop Ember 3.x support ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 105 | 106 | #### :rocket: Enhancement 107 | * [#1163](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1163) Add full TS/glint support ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 108 | * [#1162](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1162) Type declarations and template registry for Glint ([@BoussonKarel](https://github.com/BoussonKarel)) 109 | 110 | #### :memo: Documentation 111 | * [#951](https://github.com/RobbieTheWagner/ember-math-helpers/pull/951) Fix broken URLs ([@ursm](https://github.com/ursm)) 112 | 113 | #### :house: Internal 114 | * [#1100](https://github.com/RobbieTheWagner/ember-math-helpers/pull/1100) Fix build ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 115 | 116 | #### Committers: 3 117 | - Keita Urashima ([@ursm](https://github.com/ursm)) 118 | - Robbie Wagner ([@RobbieTheWagner](https://github.com/RobbieTheWagner)) 119 | - [@BoussonKarel](https://github.com/BoussonKarel) 120 | 121 | ## v3.0.0 (2022-10-25) 122 | 123 | #### :boom: Breaking Change 124 | * [#833](https://github.com/rwwagner90/ember-math-helpers/pull/833) Require node >= 14 ([@rwwagner90](https://github.com/rwwagner90)) 125 | 126 | #### Committers: 1 127 | - Robert Wagner ([@rwwagner90](https://github.com/rwwagner90)) 128 | 129 | ## v2.18.2 (2022-05-25) 130 | 131 | #### :house: Internal 132 | * [#796](https://github.com/rwwagner90/ember-math-helpers/pull/796) ember-cli 4.3 ([@rwwagner90](https://github.com/rwwagner90)) 133 | 134 | #### Committers: 1 135 | - Robert Wagner ([@rwwagner90](https://github.com/rwwagner90)) 136 | 137 | ## v2.18.1 (2022-01-25) 138 | 139 | #### :house: Internal 140 | * [#702](https://github.com/rwwagner90/ember-math-helpers/pull/702) ember-cli 4.1 ([@rwwagner90](https://github.com/rwwagner90)) 141 | 142 | #### Committers: 1 143 | - Robert Wagner ([@rwwagner90](https://github.com/rwwagner90)) 144 | 145 | ## v2.18.0 (2021-11-09) 146 | 147 | #### :rocket: Enhancement 148 | * [#614](https://github.com/rwwagner90/ember-math-helpers/pull/614) implement sum helper as strict alias for add helper ([@Mifrill](https://github.com/Mifrill)) 149 | 150 | #### :house: Internal 151 | * [#658](https://github.com/rwwagner90/ember-math-helpers/pull/658) exclude deploy-docs from publish ([@jakesjews](https://github.com/jakesjews)) 152 | 153 | #### Committers: 2 154 | - Aleksei Strizhak ([@Mifrill](https://github.com/Mifrill)) 155 | - Jacob Jewell ([@jakesjews](https://github.com/jakesjews)) 156 | 157 | ## v2.17.3 (2021-09-20) 158 | 159 | ## v2.17.2 (2021-09-20) 160 | 161 | ## v2.17.1 (2021-09-20) 162 | 163 | ## v2.17.0 (2021-09-17) 164 | 165 | #### :house: Internal 166 | * [#587](https://github.com/rwwagner90/ember-math-helpers/pull/587) Move documentation to /docs ([@rwwagner90](https://github.com/rwwagner90)) 167 | * [#495](https://github.com/rwwagner90/ember-math-helpers/pull/495) Add dependabot automerge ([@rwwagner90](https://github.com/rwwagner90)) 168 | 169 | #### Committers: 1 170 | - Robert Wagner ([@rwwagner90](https://github.com/rwwagner90)) 171 | 172 | ## v2.16.0 (2021-05-08) 173 | 174 | #### :rocket: Enhancement 175 | * [#324](https://github.com/rwwagner90/ember-math-helpers/pull/324) Ember 3.20 ([@rwwagner90](https://github.com/rwwagner90)) 176 | 177 | #### :house: Internal 178 | * [#401](https://github.com/rwwagner90/ember-math-helpers/pull/401) Update eslint-plugin-ember, fix lint ([@rwwagner90](https://github.com/rwwagner90)) 179 | 180 | #### Committers: 2 181 | - Robert Wagner ([@rwwagner90](https://github.com/rwwagner90)) 182 | - [@dependabot-preview[bot]](https://github.com/apps/dependabot-preview) 183 | 184 | ## v2.15.0 (2020-07-13) 185 | 186 | #### :house: Internal 187 | * [#299](https://github.com/rwwagner90/ember-math-helpers/pull/299) ember / ember-cli 3.19 ([@rwwagner90](https://github.com/rwwagner90)) 188 | 189 | #### Committers: 2 190 | - Robert Wagner ([@rwwagner90](https://github.com/rwwagner90)) 191 | - [@dependabot-preview[bot]](https://github.com/apps/dependabot-preview) 192 | 193 | # 2.7.0 (2018-09-04) 194 | * Implement `gcd` helper [#136](https://github.com/rwwagner90/ember-math-helpers/pull/136) 195 | 196 | # 2.6.0 (2018-07-30) 197 | * Bump to Ember 3.3.0 198 | * Bump to Ember CLI 3.3.0 199 | 200 | # 2.5.0 (2018-05-11) 201 | * Bump to Ember 3.2.0 beta 202 | * Bump to Ember CLI 3.1.1 203 | 204 | # 2.4.1 (2018-04-09) 205 | * Bump to Ember 3.1 beta and upgrade dependencies 206 | * Remove unused test helpers 207 | 208 | # 2.4.0 (2018-01-02) 209 | * Bump to Ember 3.0 beta 210 | 211 | # 2.2.4 212 | * Add `decimals` and `exp` options to `round` helper. 213 | 214 | # 2.2.3 215 | * Make whitelist/blacklist options work with engines 216 | 217 | # 2.2.2 218 | * Allow whitelist/blacklist functionality 219 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How To Contribute 2 | 3 | ## Installation 4 | 5 | - `git clone ` 6 | - `cd ember-math-helpers` 7 | - `pnpm install` 8 | 9 | ## Linting 10 | 11 | - `pnpm lint` 12 | - `pnpm lint:fix` 13 | 14 | ## Building the addon 15 | 16 | - `cd ember-math-helpers` 17 | - `pnpm build` 18 | 19 | ## Running tests 20 | 21 | - `cd test-app` 22 | - `pnpm test` – Runs the test suite on the current Ember version 23 | - `pnpm test:watch` – Runs the test suite in "watch mode" 24 | 25 | ## Running the test application 26 | 27 | - `cd test-app` 28 | - `pnpm start` 29 | - Visit the test application at [http://localhost:4200](http://localhost:4200). 30 | 31 | For more information on using ember-cli, visit [https://cli.emberjs.com/release/](https://cli.emberjs.com/release/). 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2025 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ember-math-helpers 2 | 3 | Ship Shape 4 | 5 | **[ember-math-helpers is built and maintained by Ship Shape. Contact us for Ember.js consulting, development, and training for your project](https://shipshape.io/ember-consulting/)**. 6 | 7 | [![npm version](https://badge.fury.io/js/ember-math-helpers.svg)](http://badge.fury.io/js/ember-math-helpers) 8 | ![Download count all time](https://img.shields.io/npm/dt/ember-math-helpers.svg) 9 | [![npm](https://img.shields.io/npm/dm/ember-math-helpers.svg)]() 10 | [![Ember Observer Score](http://emberobserver.com/badges/ember-math-helpers.svg)](http://emberobserver.com/addons/ember-math-helpers) 11 | [![CI](https://github.com/RobbieTheWagner/ember-math-helpers/actions/workflows/ci.yml/badge.svg)](https://github.com/RobbieTheWagner/ember-math-helpers/actions/workflows/ci.yml) 12 | 13 | HTMLBars template helpers for doing basic arithmetic operations 14 | 15 | ## Compatibility 16 | 17 | - Ember.js v4.12 or above 18 | - Embroider or ember-auto-import v2 19 | 20 | 21 | ## Installation 22 | 23 | ``` 24 | ember install ember-math-helpers 25 | ``` 26 | 27 | ## Documentation 28 | 29 | [View Docs](https://robbiethewagner.github.io/ember-math-helpers/) 30 | 31 | ## Contributing 32 | 33 | See the [Contributing](CONTRIBUTING.md) guide for details. 34 | 35 | 36 | ## License 37 | 38 | This project is licensed under the [MIT License](LICENSE.md). 39 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Release Process 2 | 3 | Releases in this repo are mostly automated using [release-plan](https://github.com/embroider-build/release-plan/). Once you label all your PRs correctly (see below) you will have an automatically generated PR that updates your CHANGELOG.md file and a `.release-plan.json` that is used to prepare the release once the PR is merged. 4 | 5 | ## Preparation 6 | 7 | Since the majority of the actual release process is automated, the remaining tasks before releasing are: 8 | 9 | - correctly labeling **all** pull requests that have been merged since the last release 10 | - updating pull request titles so they make sense to our users 11 | 12 | Some great information on why this is important can be found at [keepachangelog.com](https://keepachangelog.com/en/1.1.0/), but the overall 13 | guiding principle here is that changelogs are for humans, not machines. 14 | 15 | When reviewing merged PR's the labels to be used are: 16 | 17 | - breaking - Used when the PR is considered a breaking change. 18 | - enhancement - Used when the PR adds a new feature or enhancement. 19 | - bug - Used when the PR fixes a bug included in a previous release. 20 | - documentation - Used when the PR adds or updates documentation. 21 | - internal - Internal changes or things that don't fit in any other category. 22 | 23 | **Note:** `release-plan` requires that **all** PRs are labeled. If a PR doesn't fit in a category it's fine to label it as `internal` 24 | 25 | ## Release 26 | 27 | Once the prep work is completed, the actual release is straight forward: you just need to merge the open [Plan Release](https://github.com/RobbieTheWagner/ember-math-helpers/pulls?q=is%3Apr+is%3Aopen+%22Prepare+Release%22+in%3Atitle) PR 28 | -------------------------------------------------------------------------------- /config/ember-cli-update.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": "1.0.0", 3 | "projectName": "ember-math-helpers", 4 | "packages": [ 5 | { 6 | "name": "@embroider/addon-blueprint", 7 | "version": "4.1.1", 8 | "blueprints": [ 9 | { 10 | "name": "@embroider/addon-blueprint", 11 | "isBaseBlueprint": true, 12 | "options": [ 13 | "--ci-provider=github", 14 | "--pnpm", 15 | "--typescript" 16 | ] 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /ember-math-helpers/.gitignore: -------------------------------------------------------------------------------- 1 | # The authoritative copies of these live in the monorepo root (because they're 2 | # more useful on github that way), but the build copies them into here so they 3 | # will also appear in published NPM packages. 4 | /README.md 5 | /LICENSE.md 6 | 7 | # compiled output 8 | dist/ 9 | declarations/ 10 | 11 | # npm/pnpm/yarn pack output 12 | *.tgz 13 | 14 | # deps & caches 15 | node_modules/ 16 | .eslintcache 17 | .prettiercache 18 | -------------------------------------------------------------------------------- /ember-math-helpers/.npmignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | .eslintcache 4 | 5 | # README is copied from monorepo root each build 6 | README.md 7 | -------------------------------------------------------------------------------- /ember-math-helpers/.prettierignore: -------------------------------------------------------------------------------- 1 | # unconventional js 2 | /blueprints/*/files/ 3 | 4 | # compiled output 5 | /dist/ 6 | /declarations/ 7 | 8 | # misc 9 | /coverage/ 10 | -------------------------------------------------------------------------------- /ember-math-helpers/.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | plugins: ['prettier-plugin-ember-template-tag'], 5 | overrides: [ 6 | { 7 | files: '*.{js,gjs,ts,gts,mjs,mts,cjs,cts}', 8 | options: { 9 | singleQuote: true, 10 | templateSingleQuote: false, 11 | }, 12 | }, 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /ember-math-helpers/.prettierrc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | overrides: [ 5 | { 6 | files: '*.{cjs,js,mjs,ts}', 7 | options: { 8 | singleQuote: true, 9 | }, 10 | }, 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /ember-math-helpers/.template-lintrc.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | extends: 'recommended', 5 | }; 6 | -------------------------------------------------------------------------------- /ember-math-helpers/README.md: -------------------------------------------------------------------------------- 1 | # ember-math-helpers 2 | 3 | Ship Shape 4 | 5 | **[ember-math-helpers is built and maintained by Ship Shape. Contact us for Ember.js consulting, development, and training for your project](https://shipshape.io/ember-consulting/)**. 6 | 7 | [![npm version](https://badge.fury.io/js/ember-math-helpers.svg)](http://badge.fury.io/js/ember-math-helpers) 8 | ![Download count all time](https://img.shields.io/npm/dt/ember-math-helpers.svg) 9 | [![npm](https://img.shields.io/npm/dm/ember-math-helpers.svg)]() 10 | [![Ember Observer Score](http://emberobserver.com/badges/ember-math-helpers.svg)](http://emberobserver.com/addons/ember-math-helpers) 11 | [![CI](https://github.com/RobbieTheWagner/ember-math-helpers/actions/workflows/ci.yml/badge.svg)](https://github.com/RobbieTheWagner/ember-math-helpers/actions/workflows/ci.yml) 12 | 13 | HTMLBars template helpers for doing basic arithmetic operations 14 | 15 | ## Compatibility 16 | 17 | - Ember.js v4.12 or above 18 | - Embroider or ember-auto-import v2 19 | 20 | 21 | ## Installation 22 | 23 | ``` 24 | ember install ember-math-helpers 25 | ``` 26 | 27 | ## Documentation 28 | 29 | [View Docs](https://robbiethewagner.github.io/ember-math-helpers/) 30 | 31 | ## Contributing 32 | 33 | See the [Contributing](CONTRIBUTING.md) guide for details. 34 | 35 | 36 | ## License 37 | 38 | This project is licensed under the [MIT License](LICENSE.md). 39 | -------------------------------------------------------------------------------- /ember-math-helpers/addon-main.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { addonV1Shim } = require('@embroider/addon-shim'); 4 | module.exports = addonV1Shim(__dirname); 5 | -------------------------------------------------------------------------------- /ember-math-helpers/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | [ 4 | "@babel/plugin-transform-typescript", 5 | { 6 | "allExtensions": true, 7 | "onlyRemoveTypeImports": true, 8 | "allowDeclareFields": true 9 | } 10 | ], 11 | "@embroider/addon-dev/template-colocation-plugin", 12 | [ 13 | "babel-plugin-ember-template-compilation", 14 | { 15 | "targetFormat": "hbs", 16 | "transforms": [] 17 | } 18 | ], 19 | [ 20 | "module:decorator-transforms", 21 | { "runtime": { "import": "decorator-transforms/runtime" } } 22 | ] 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /ember-math-helpers/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Debugging: 3 | * https://eslint.org/docs/latest/use/configure/debug 4 | * ---------------------------------------------------- 5 | * 6 | * Print a file's calculated configuration 7 | * 8 | * npx eslint --print-config path/to/file.js 9 | * 10 | * Inspecting the config 11 | * 12 | * npx eslint --inspect-config 13 | * 14 | */ 15 | import babelParser from '@babel/eslint-parser'; 16 | import js from '@eslint/js'; 17 | import prettier from 'eslint-config-prettier'; 18 | import ember from 'eslint-plugin-ember/recommended'; 19 | import importPlugin from 'eslint-plugin-import'; 20 | import n from 'eslint-plugin-n'; 21 | import globals from 'globals'; 22 | import ts from 'typescript-eslint'; 23 | 24 | const parserOptions = { 25 | esm: { 26 | js: { 27 | ecmaFeatures: { modules: true }, 28 | ecmaVersion: 'latest', 29 | }, 30 | ts: { 31 | projectService: true, 32 | project: true, 33 | tsconfigRootDir: import.meta.dirname, 34 | }, 35 | }, 36 | }; 37 | 38 | export default ts.config( 39 | js.configs.recommended, 40 | ember.configs.base, 41 | ember.configs.gjs, 42 | ember.configs.gts, 43 | prettier, 44 | /** 45 | * Ignores must be in their own object 46 | * https://eslint.org/docs/latest/use/configure/ignore 47 | */ 48 | { 49 | ignores: ['dist/', 'declarations/', 'node_modules/', 'coverage/', '!**/.*'], 50 | }, 51 | /** 52 | * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options 53 | */ 54 | { 55 | linterOptions: { 56 | reportUnusedDisableDirectives: 'error', 57 | }, 58 | }, 59 | { 60 | files: ['**/*.js'], 61 | languageOptions: { 62 | parser: babelParser, 63 | }, 64 | }, 65 | { 66 | files: ['**/*.{js,gjs}'], 67 | languageOptions: { 68 | parserOptions: parserOptions.esm.js, 69 | globals: { 70 | ...globals.browser, 71 | }, 72 | }, 73 | }, 74 | { 75 | files: ['**/*.{ts,gts}'], 76 | languageOptions: { 77 | parser: ember.parser, 78 | parserOptions: parserOptions.esm.ts, 79 | }, 80 | extends: [...ts.configs.recommendedTypeChecked, ember.configs.gts], 81 | }, 82 | { 83 | files: ['src/**/*'], 84 | plugins: { 85 | import: importPlugin, 86 | }, 87 | rules: { 88 | // require relative imports use full extensions 89 | 'import/extensions': ['error', 'always', { ignorePackages: true }], 90 | }, 91 | }, 92 | /** 93 | * CJS node files 94 | */ 95 | { 96 | files: [ 97 | '**/*.cjs', 98 | '.prettierrc.js', 99 | '.stylelintrc.js', 100 | '.template-lintrc.js', 101 | 'addon-main.cjs', 102 | ], 103 | plugins: { 104 | n, 105 | }, 106 | 107 | languageOptions: { 108 | sourceType: 'script', 109 | ecmaVersion: 'latest', 110 | globals: { 111 | ...globals.node, 112 | }, 113 | }, 114 | }, 115 | /** 116 | * ESM node files 117 | */ 118 | { 119 | files: ['**/*.mjs'], 120 | plugins: { 121 | n, 122 | }, 123 | 124 | languageOptions: { 125 | sourceType: 'module', 126 | ecmaVersion: 'latest', 127 | parserOptions: parserOptions.esm.js, 128 | globals: { 129 | ...globals.node, 130 | }, 131 | }, 132 | }, 133 | ); 134 | -------------------------------------------------------------------------------- /ember-math-helpers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-math-helpers", 3 | "version": "5.0.0", 4 | "description": "HTMLBars helpers for basic arithmetic", 5 | "keywords": [ 6 | "ember-addon" 7 | ], 8 | "repository": "https://github.com/RobbieTheWagner/ember-math-helpers", 9 | "license": "MIT", 10 | "author": { 11 | "name": "Robbie Wagner", 12 | "email": "rwwagner90@gmail.com", 13 | "url": "https://github.com/RobbieTheWagner" 14 | }, 15 | "exports": { 16 | ".": { 17 | "types": "./declarations/index.d.ts", 18 | "default": "./dist/index.js" 19 | }, 20 | "./*": { 21 | "types": "./declarations/*.d.ts", 22 | "default": "./dist/*.js" 23 | }, 24 | "./addon-main.js": "./addon-main.cjs" 25 | }, 26 | "typesVersions": { 27 | "*": { 28 | "*": [ 29 | "declarations/*" 30 | ] 31 | } 32 | }, 33 | "files": [ 34 | "addon-main.cjs", 35 | "declarations", 36 | "dist" 37 | ], 38 | "scripts": { 39 | "build": "rollup --config", 40 | "format": "prettier . --cache --write", 41 | "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\" --prefixColors auto", 42 | "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\" --prefixColors auto && pnpm run format", 43 | "lint:format": "prettier . --cache --check", 44 | "lint:hbs": "ember-template-lint . --no-error-on-unmatched-pattern", 45 | "lint:hbs:fix": "ember-template-lint . --fix --no-error-on-unmatched-pattern", 46 | "lint:js": "eslint . --cache", 47 | "lint:js:fix": "eslint . --fix", 48 | "lint:types": "glint", 49 | "prepack": "rollup --config", 50 | "start": "rollup --config --watch", 51 | "test": "echo 'A v2 addon does not have tests, run tests in test-app'" 52 | }, 53 | "dependencies": { 54 | "@embroider/addon-shim": "^1.8.9", 55 | "decorator-transforms": "^2.2.2" 56 | }, 57 | "devDependencies": { 58 | "@babel/core": "^7.28.0", 59 | "@babel/eslint-parser": "^7.28.0", 60 | "@babel/plugin-transform-typescript": "^7.28.0", 61 | "@babel/runtime": "^7.27.6", 62 | "@embroider/addon-dev": "^8.1.0", 63 | "@eslint/js": "^9.30.1", 64 | "@glint/core": "^1.5.2", 65 | "@glint/environment-ember-loose": "^1.5.2", 66 | "@glint/environment-ember-template-imports": "^1.5.2", 67 | "@glint/template": "^1.5.2", 68 | "@rollup/plugin-babel": "6.0.4", 69 | "@tsconfig/ember": "^3.0.10", 70 | "@types/rsvp": "^4.0.9", 71 | "babel-plugin-ember-template-compilation": "^2.2.5", 72 | "concurrently": "^9.2.0", 73 | "ember-source": "^6.5.0", 74 | "ember-template-lint": "^7.9.1", 75 | "eslint": "^9.30.1", 76 | "eslint-config-prettier": "^10.1.5", 77 | "eslint-plugin-ember": "^12.3.3", 78 | "eslint-plugin-import": "^2.32.0", 79 | "eslint-plugin-n": "^17.21.0", 80 | "globals": "^16.3.0", 81 | "prettier": "^3.6.2", 82 | "prettier-plugin-ember-template-tag": "^2.0.6", 83 | "rollup": "^4.44.2", 84 | "rollup-plugin-copy": "^3.5.0", 85 | "typescript": "~5.8.3", 86 | "typescript-eslint": "^8.36.0", 87 | "webpack": "^5.100.0" 88 | }, 89 | "peerDependencies": { 90 | "ember-source": ">= 4.12.0" 91 | }, 92 | "engines": { 93 | "node": ">= 18" 94 | }, 95 | "publishConfig": { 96 | "registry": "https://registry.npmjs.org" 97 | }, 98 | "ember": { 99 | "edition": "octane" 100 | }, 101 | "ember-addon": { 102 | "version": 2, 103 | "type": "addon", 104 | "main": "addon-main.cjs", 105 | "app-js": { 106 | "./helpers/abs.js": "./dist/_app_/helpers/abs.js", 107 | "./helpers/acos.js": "./dist/_app_/helpers/acos.js", 108 | "./helpers/acosh.js": "./dist/_app_/helpers/acosh.js", 109 | "./helpers/add.js": "./dist/_app_/helpers/add.js", 110 | "./helpers/asin.js": "./dist/_app_/helpers/asin.js", 111 | "./helpers/asinh.js": "./dist/_app_/helpers/asinh.js", 112 | "./helpers/atan.js": "./dist/_app_/helpers/atan.js", 113 | "./helpers/atan2.js": "./dist/_app_/helpers/atan2.js", 114 | "./helpers/atanh.js": "./dist/_app_/helpers/atanh.js", 115 | "./helpers/cbrt.js": "./dist/_app_/helpers/cbrt.js", 116 | "./helpers/ceil.js": "./dist/_app_/helpers/ceil.js", 117 | "./helpers/clz32.js": "./dist/_app_/helpers/clz32.js", 118 | "./helpers/cos.js": "./dist/_app_/helpers/cos.js", 119 | "./helpers/cosh.js": "./dist/_app_/helpers/cosh.js", 120 | "./helpers/div.js": "./dist/_app_/helpers/div.js", 121 | "./helpers/exp.js": "./dist/_app_/helpers/exp.js", 122 | "./helpers/expm1.js": "./dist/_app_/helpers/expm1.js", 123 | "./helpers/floor.js": "./dist/_app_/helpers/floor.js", 124 | "./helpers/fround.js": "./dist/_app_/helpers/fround.js", 125 | "./helpers/gcd.js": "./dist/_app_/helpers/gcd.js", 126 | "./helpers/hypot.js": "./dist/_app_/helpers/hypot.js", 127 | "./helpers/imul.js": "./dist/_app_/helpers/imul.js", 128 | "./helpers/lcm.js": "./dist/_app_/helpers/lcm.js", 129 | "./helpers/log-e.js": "./dist/_app_/helpers/log-e.js", 130 | "./helpers/log10.js": "./dist/_app_/helpers/log10.js", 131 | "./helpers/log1p.js": "./dist/_app_/helpers/log1p.js", 132 | "./helpers/log2.js": "./dist/_app_/helpers/log2.js", 133 | "./helpers/max.js": "./dist/_app_/helpers/max.js", 134 | "./helpers/min.js": "./dist/_app_/helpers/min.js", 135 | "./helpers/mod.js": "./dist/_app_/helpers/mod.js", 136 | "./helpers/mult.js": "./dist/_app_/helpers/mult.js", 137 | "./helpers/pow.js": "./dist/_app_/helpers/pow.js", 138 | "./helpers/random.js": "./dist/_app_/helpers/random.js", 139 | "./helpers/round.js": "./dist/_app_/helpers/round.js", 140 | "./helpers/sign.js": "./dist/_app_/helpers/sign.js", 141 | "./helpers/sin.js": "./dist/_app_/helpers/sin.js", 142 | "./helpers/sqrt.js": "./dist/_app_/helpers/sqrt.js", 143 | "./helpers/sub.js": "./dist/_app_/helpers/sub.js", 144 | "./helpers/sum.js": "./dist/_app_/helpers/sum.js", 145 | "./helpers/tan.js": "./dist/_app_/helpers/tan.js", 146 | "./helpers/tanh.js": "./dist/_app_/helpers/tanh.js", 147 | "./helpers/trunc.js": "./dist/_app_/helpers/trunc.js" 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /ember-math-helpers/rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import { babel } from '@rollup/plugin-babel'; 2 | import copy from 'rollup-plugin-copy'; 3 | import { Addon } from '@embroider/addon-dev/rollup'; 4 | 5 | const addon = new Addon({ 6 | srcDir: 'src', 7 | destDir: 'dist', 8 | }); 9 | 10 | export default { 11 | // This provides defaults that work well alongside `publicEntrypoints` below. 12 | // You can augment this if you need to. 13 | output: addon.output(), 14 | 15 | plugins: [ 16 | // These are the modules that users should be able to import from your 17 | // addon. Anything not listed here may get optimized away. 18 | // By default all your JavaScript modules (**/*.js) will be importable. 19 | // But you are encouraged to tweak this to only cover the modules that make 20 | // up your addon's public API. Also make sure your package.json#exports 21 | // is aligned to the config here. 22 | // See https://github.com/embroider-build/embroider/blob/main/docs/v2-faq.md#how-can-i-define-the-public-exports-of-my-addon 23 | addon.publicEntrypoints(['**/*.js', 'index.js', 'template-registry.js']), 24 | 25 | // These are the modules that should get reexported into the traditional 26 | // "app" tree. Things in here should also be in publicEntrypoints above, but 27 | // not everything in publicEntrypoints necessarily needs to go here. 28 | addon.appReexports([ 29 | 'components/**/*.js', 30 | 'helpers/**/*.js', 31 | 'modifiers/**/*.js', 32 | 'services/**/*.js', 33 | ]), 34 | 35 | // Follow the V2 Addon rules about dependencies. Your code can import from 36 | // `dependencies` and `peerDependencies` as well as standard Ember-provided 37 | // package names. 38 | addon.dependencies(), 39 | 40 | // This babel config should *not* apply presets or compile away ES modules. 41 | // It exists only to provide development niceties for you, like automatic 42 | // template colocation. 43 | // 44 | // By default, this will load the actual babel config from the file 45 | // babel.config.json. 46 | babel({ 47 | extensions: ['.js', '.gjs', '.ts', '.gts'], 48 | babelHelpers: 'bundled', 49 | }), 50 | 51 | // Ensure that standalone .hbs files are properly integrated as Javascript. 52 | addon.hbs(), 53 | 54 | // Ensure that .gjs files are properly integrated as Javascript 55 | addon.gjs(), 56 | 57 | // Emit .d.ts declaration files 58 | addon.declarations('declarations'), 59 | 60 | // addons are allowed to contain imports of .css files, which we want rollup 61 | // to leave alone and keep in the published output. 62 | addon.keepAssets(['**/*.css']), 63 | 64 | // Remove leftover build artifacts when starting a new build. 65 | addon.clean(), 66 | 67 | // Copy Readme and License into published package 68 | copy({ 69 | targets: [ 70 | { src: '../README.md', dest: '.' }, 71 | { src: '../LICENSE.md', dest: '.' }, 72 | ], 73 | }), 74 | ], 75 | }; 76 | -------------------------------------------------------------------------------- /ember-math-helpers/src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobbieTheWagner/ember-math-helpers/d2d111bffc0b8d90543a835fb951a3ae90d87141/ember-math-helpers/src/.gitkeep -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/abs.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface AbsSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Uses `Math.abs` to take the absolute value of the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{abs a}} 15 | * ``` 16 | * 17 | * @function abs 18 | * @param {number} number The number to take the absolute value of 19 | * @return {number} The absolute value of the passed number 20 | */ 21 | export function abs([number]: [number]) { 22 | return Math.abs(number); 23 | } 24 | 25 | export default helper(abs); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/acos.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface AcosSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.acos` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{acos a}} 15 | * ``` 16 | * 17 | * @function acos 18 | * @param {number} number The number to pass to `Math.acos` 19 | * @return {number} The acos of the passed number 20 | */ 21 | export function acos([number]: [number]) { 22 | return Math.acos(number); 23 | } 24 | 25 | export default helper(acos); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/acosh.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface AcoshSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.acosh` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{acosh a}} 15 | * ``` 16 | * 17 | * @function acosh 18 | * @param {number} number The number to pass to `Math.acosh` 19 | * @return {number} The acosh of the passed number 20 | */ 21 | export function acosh([number]: [number]) { 22 | return Math.acosh(number); 23 | } 24 | 25 | export default helper(acosh); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/add.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface AddSignature { 4 | Args: { 5 | Positional: Array; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Sums two or more numbers 12 | * 13 | * ```hbs 14 | * {{add a b}} 15 | * ``` 16 | * 17 | * @function add 18 | * @param {number[]} numbers A list of numbers to sum 19 | * @return {number} The sum of all the passed numbers 20 | */ 21 | export function add(numbers: Array) { 22 | return numbers.reduce((a, b) => Number(a) + Number(b)); 23 | } 24 | 25 | export default helper(add); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/asin.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface AsinSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.asin` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{asin a}} 15 | * ``` 16 | * 17 | * @function asin 18 | * @param {number} number The number to pass to `Math.asin` 19 | * @return {number} The asin of the passed number 20 | */ 21 | export function asin([number]: [number]) { 22 | return Math.asin(number); 23 | } 24 | 25 | export default helper(asin); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/asinh.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface AsinhSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.asinh` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{asinh a}} 15 | * ``` 16 | * 17 | * @function asinh 18 | * @param {number} number The number to pass to `Math.asinh` 19 | * @return {number} The asinh of the passed number 20 | */ 21 | export function asinh([number]: [number]) { 22 | return Math.asinh(number); 23 | } 24 | 25 | export default helper(asinh); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/atan.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface AtanSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.atan` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{atan a}} 15 | * ``` 16 | * @function atan 17 | * @param {number} number The number to pass to `Math.atan` 18 | * @return {number} The atan of the passed number 19 | */ 20 | export function atan([number]: [number]) { 21 | return Math.atan(number); 22 | } 23 | 24 | export default helper(atan); 25 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/atan2.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface Atan2Signature { 4 | Args: { 5 | Positional: [number, number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.atan2` on the numbers passed to the helper. 12 | * 13 | * ```hbs 14 | * {{atan2 a b}} 15 | * ``` 16 | * 17 | * @function atan2 18 | * @param {number} number1 The first number to pass to `Math.atan2` 19 | * @param {number} number2 The second number to pass to `Math.atan2` 20 | * @return {number} The atan2 of the passed numbers 21 | */ 22 | export function atan2([number1, number2]: [number, number]) { 23 | return Math.atan2(number1, number2); 24 | } 25 | 26 | export default helper(atan2); 27 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/atanh.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface AtanhSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.atanh` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{atanh a}} 15 | * ``` 16 | * 17 | * @function atanh 18 | * @param {number} number The number to pass to `Math.atanh` 19 | * @return {number} The atanh of the passed number 20 | */ 21 | export function atanh([number]: [number]) { 22 | return Math.atanh(number); 23 | } 24 | 25 | export default helper(atanh); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/cbrt.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface CbrtSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.cbrt` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{cbrt a}} 15 | * ``` 16 | * 17 | * @function cbrt 18 | * @param {number} number The number to pass to `Math.cbrt` 19 | * @return {number} The cbrt of the passed number 20 | */ 21 | export function cbrt([number]: [number]) { 22 | return Math.cbrt(number); 23 | } 24 | 25 | export default helper(cbrt); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/ceil.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface CeilSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.ceil` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{ceil a}} 15 | * ``` 16 | * 17 | * @function ceil 18 | * @param {number} number The number to pass to `Math.ceil` 19 | * @return {number} The ceil of the passed number 20 | */ 21 | export function ceil([number]: [number]) { 22 | return Math.ceil(number); 23 | } 24 | 25 | export default helper(ceil); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/clz32.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface Clz32Signature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.clz32` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{clz32 a}} 15 | * ``` 16 | * 17 | * @function clz32 18 | * @param {number} number The number to pass to `Math.clz32` 19 | * @return {number} The clz32 of the passed number 20 | */ 21 | export function clz32([number]: [number]) { 22 | return Math.clz32(number); 23 | } 24 | 25 | export default helper(clz32); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/cos.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface CosSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.cos` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{cos a}} 15 | * ``` 16 | * 17 | * @function cos 18 | * @param {number} number The number to pass to `Math.cos` 19 | * @return {number} The cos of the passed number 20 | */ 21 | export function cos([number]: [number]) { 22 | return Math.cos(number); 23 | } 24 | 25 | export default helper(cos); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/cosh.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface CoshSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.cosh` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{cosh a}} 15 | * ``` 16 | * 17 | * @function cosh 18 | * @param {number} number The number to pass to `Math.cosh` 19 | * @return {number} The cosh of the passed number 20 | */ 21 | export function cosh([number]: [number]) { 22 | return Math.cosh(number); 23 | } 24 | 25 | export default helper(cosh); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/div.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface DivSignature { 4 | Args: { 5 | Positional: Array; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Divides two or more numbers 12 | * 13 | * ```hbs 14 | * {{div a b}} 15 | * ``` 16 | * 17 | * @function div 18 | * @param {number[]} numbers A list of numbers to divide 19 | * @return {number} The result of dividing all the passed numbers 20 | */ 21 | export function div(numbers: Array) { 22 | return numbers.reduce((a, b) => Number(a) / Number(b)); 23 | } 24 | 25 | export default helper(div); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/exp.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface ExpSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.exp` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{exp a}} 15 | * ``` 16 | * 17 | * @function exp 18 | * @param {number} number The number to pass to `Math.exp` 19 | * @return {number} The exp of the passed number 20 | */ 21 | export function exp([number]: [number]) { 22 | return Math.exp(number); 23 | } 24 | 25 | export default helper(exp); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/expm1.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface Expm1Signature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.expm1` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{expm1 a}} 15 | * ``` 16 | * 17 | * @function expm1 18 | * @param {number} number The number to pass to `Math.expm1` 19 | * @return {number} The expm1 of the passed number 20 | */ 21 | export function expm1([number]: [number]) { 22 | return Math.expm1(number); 23 | } 24 | 25 | export default helper(expm1); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/floor.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface FloorSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.floor` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{floor a}} 15 | * ``` 16 | * 17 | * @function floor 18 | * @param {number} number The number to pass to `Math.floor` 19 | * @return {number} The floor of the passed number 20 | */ 21 | export function floor([number]: [number]) { 22 | return Math.floor(number); 23 | } 24 | 25 | export default helper(floor); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/fround.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface FroundSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.fround` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{fround a}} 15 | * ``` 16 | * 17 | * @function fround 18 | * @param {number} number The number to pass to `Math.fround` 19 | * @return {number} The fround of the passed number 20 | */ 21 | export function fround([number]: [number]) { 22 | return Math.fround(number); 23 | } 24 | 25 | export default helper(fround); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/gcd.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface GcdSignature { 4 | Args: { 5 | Positional: [number, number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Returns the greatest positive integer that divides each of two integers 12 | * 13 | * ```hbs 14 | * {{gcd a b}} 15 | * ``` 16 | * 17 | * @function gcd 18 | * @param {number} number1 The first number 19 | * @param {number} number2 The second number 20 | * @return {number} The GCD of the two numbers passed 21 | */ 22 | export function gcd([number1 = 0, number2 = 0]) { 23 | const a = Math.abs(number1); 24 | const b = Math.abs(number2); 25 | 26 | if (a === 0) { 27 | return b; 28 | } 29 | 30 | if (b === 0) { 31 | return a; 32 | } 33 | 34 | return gcd([b, a % b]); 35 | } 36 | 37 | export default helper(gcd); 38 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/hypot.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface HypotSignature { 4 | Args: { 5 | Positional: Array; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Takes two or more numbers, and returns the square root of the sum of squares of them using `Math.hypot` 12 | * 13 | * ```hbs 14 | * {{max a b}} 15 | * ``` 16 | * 17 | * @function hypot 18 | * @param {number[]} numbers A list of numbers to pass to `Math.hypot` 19 | * @return {number} The hypot of the set of numbers 20 | */ 21 | export function hypot(numbers: Array) { 22 | return Math.hypot(...numbers); 23 | } 24 | 25 | export default helper(hypot); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/imul.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface ImulSignature { 4 | Args: { 5 | Positional: [number, number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.imul` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{imul a}} 15 | * ``` 16 | * 17 | * @function imul 18 | * @param {number} number1 The first number to pass to `Math.imul` 19 | * @param {number} number2 The second number to pass to `Math.imul` 20 | * @return {number} The imul of the passed numbers 21 | */ 22 | export function imul([number1, number2]: [number, number]) { 23 | return Math.imul(number1, number2); 24 | } 25 | 26 | export default helper(imul); 27 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/lcm.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | import { gcd } from './gcd.ts'; 4 | 5 | export interface LcmSignature { 6 | Args: { 7 | Positional: [number, number]; 8 | }; 9 | Return: number; 10 | } 11 | 12 | /** 13 | * Returns the smallest positive integer that is divisible by both number1 and number2 14 | * 15 | * ```hbs 16 | * {{lcm a b}} 17 | * ``` 18 | * 19 | * @function lcm 20 | * @param {number} number1 The first number 21 | * @param {number} number2 The second number 22 | * @return {number} The LCM of the two numbers passed 23 | */ 24 | export function lcm([number1 = 0, number2 = 0]) { 25 | return number1 === 0 || number2 === 0 26 | ? 0 27 | : Math.abs(number1 * number2) / gcd([number1, number2]); 28 | } 29 | 30 | export default helper(lcm); 31 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/log-e.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface LogESignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.log` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{log-e a}} 15 | * ``` 16 | * 17 | * @function log-e 18 | * @param {number} number The number to pass to `Math.log` 19 | * @return {number} The log of the passed number 20 | */ 21 | export function logE([number]: [number]) { 22 | return Math.log(number); 23 | } 24 | 25 | export default helper(logE); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/log10.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface Log10Signature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.log10` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{log10 a}} 15 | * ``` 16 | * 17 | * @function log10 18 | * @param {number} number The number to pass to `Math.log10` 19 | * @return {number} The log10 of the passed number 20 | */ 21 | export function log10([number]: [number]) { 22 | return Math.log10(number); 23 | } 24 | 25 | export default helper(log10); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/log1p.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface Log1pSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.log1p` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{log1p a}} 15 | * ``` 16 | * 17 | * @function log1p 18 | * @param {number} number The number to pass to `Math.log1p` 19 | * @return {number} The log1p of the passed number 20 | */ 21 | export function log1p([number]: [number]) { 22 | return Math.log1p(number); 23 | } 24 | 25 | export default helper(log1p); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/log2.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface Log2Signature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.log2` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{log2 a}} 15 | * ``` 16 | * 17 | * @function log2 18 | * @param {number} number The number to pass to `Math.log2` 19 | * @return {number} The log2 of the passed number 20 | */ 21 | export function log2([number]: [number]) { 22 | return Math.log2(number); 23 | } 24 | 25 | export default helper(log2); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/max.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface MaxSignature { 4 | Args: { 5 | Positional: Array; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Takes two or more numbers, and finds the max of the set using `Math.max` 12 | * 13 | * ```hbs 14 | * {{max a b}} 15 | * ``` 16 | * 17 | * @function max 18 | * @param {number[]} numbers A list of numbers to pass to `Math.max` 19 | * @return {number} The max of the set of numbers 20 | */ 21 | export function max(numbers: Array) { 22 | return Math.max(...numbers); 23 | } 24 | 25 | export default helper(max); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/min.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface MinSignature { 4 | Args: { 5 | Positional: Array; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Takes two or more numbers, and finds the min of the set using `Math.min` 12 | * 13 | * ```hbs 14 | * {{min a b}} 15 | * ``` 16 | * 17 | * @function min 18 | * @param {number[]} numbers A list of numbers to pass to `Math.min` 19 | * @return {number} The min of the set of numbers 20 | */ 21 | export function min(numbers: Array) { 22 | return Math.min(...numbers); 23 | } 24 | 25 | export default helper(min); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/mod.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface ModSignature { 4 | Args: { 5 | Positional: Array; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Takes the modulus of two or more numbers 12 | * 13 | * ```hbs 14 | * {{mod a b}} 15 | * ``` 16 | * 17 | * @function mod 18 | * @param {number[]} numbers A list of numbers to modulus 19 | * @return {number} The modulus of all the passed numbers 20 | */ 21 | export function mod(numbers: Array) { 22 | return numbers.reduce((a, b) => Number(a) % Number(b)); 23 | } 24 | 25 | export default helper(mod); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/mult.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface MultSignature { 4 | Args: { 5 | Positional: Array; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Multiplies two or more numbers 12 | * 13 | * ```hbs 14 | * {{mult a b}} 15 | * ``` 16 | * 17 | * @function mult 18 | * @param {number[]} numbers A list of numbers to multiply 19 | * @return {number} The product of all the passed numbers 20 | */ 21 | export function mult(numbers: Array) { 22 | return numbers.reduce((a, b) => Number(a) * Number(b)); 23 | } 24 | 25 | export default helper(mult); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/pow.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface PowSignature { 4 | Args: { 5 | Positional: Array; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Takes two or more numbers, using the first as the base number, 12 | * then using each subsequent number as an exponent to the previous value 13 | * 14 | * ```hbs 15 | * {{pow a b}} 16 | * ``` 17 | * 18 | * @function pow 19 | * @param {number[]} numbers A list of numbers to pass to `Math.pow` 20 | * @return {number} The base raised to all exponents 21 | */ 22 | export function pow(numbers: Array) { 23 | return numbers.reduce((base, exponent) => Math.pow(base, exponent)); 24 | } 25 | 26 | export default helper(pow); 27 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/random.ts: -------------------------------------------------------------------------------- 1 | import { isArray } from '@ember/array'; 2 | import { helper } from '@ember/component/helper'; 3 | 4 | export interface RandomSignature { 5 | Args: { 6 | Named: { decimals?: number }; 7 | Positional: [upperBound?: number, lowerBound?: number]; 8 | }; 9 | Return: number; 10 | } 11 | 12 | const { min, max } = Math; 13 | 14 | // @see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed#max(0, min(MAX_DECIMALS, decimals)))); 15 | const MAX_DECIMALS = 20; 16 | 17 | // 💡 Using Number.toFixed, we'll get rounding for free alongside 18 | // decimal precision. We'll default to whole-number rounding simply 19 | // by defaulting `decimals` to 0 20 | const DEFAULT_OPTS = { 21 | decimals: 0, 22 | }; 23 | 24 | /** 25 | * Executes `Math.random` with the provided upper-bounded randoms, lower- and upper-bounded randoms, 26 | * and the option to configure decimal precision. 27 | * 28 | * ```hbs 29 | * {{random}} or {{random decimals=4}} 30 | * ``` 31 | * 32 | * ```hbs 33 | * {{random 42}} or {{random 42 decimals=4}} 34 | * ``` 35 | * 36 | * ```hbs 37 | * {{random 21 1797}} or {{random 21 1797 decimals=4}} 38 | * ``` 39 | * 40 | * @function random 41 | * @param {number} upperBound 42 | * @param {number} lowerBound 43 | * @param {object} named The set of named arguments, currently just `decimals`. 44 | * @param {number} [named.decimals] An optional decimal precision value. 45 | * @return {number} The random generated number 46 | */ 47 | export function random( 48 | params: 49 | | RandomSignature['Args']['Named'] 50 | | RandomSignature['Args']['Positional'], 51 | { decimals }: RandomSignature['Args']['Named'] = DEFAULT_OPTS, 52 | ) { 53 | // no positional args, but only an options hash from named args 54 | if (typeof params === 'object' && !isArray(params)) { 55 | decimals = 56 | typeof params.decimals !== 'undefined' 57 | ? params.decimals 58 | : DEFAULT_OPTS.decimals; 59 | 60 | return +Math.random().toFixed(max(0, min(MAX_DECIMALS, decimals))); 61 | } 62 | 63 | // one positional arg: treat it as an upper bound 64 | if (params && params.length === 1) { 65 | const [upperBound] = params; 66 | 67 | if (typeof upperBound === 'number') { 68 | return +(Math.random() * upperBound).toFixed( 69 | max(0, min(MAX_DECIMALS, decimals ?? 0)), 70 | ); 71 | } 72 | } 73 | 74 | // two positional args: use them to derive upper and lower bounds 75 | if (params && params.length === 2) { 76 | let [lowerBound, upperBound] = params; 77 | 78 | if (typeof upperBound === 'number' && typeof lowerBound === 'number') { 79 | // for convenience, swap if a higher number is accidentally passed first 80 | if (upperBound < lowerBound) { 81 | [lowerBound, upperBound] = [upperBound, lowerBound]; 82 | } 83 | 84 | return +(lowerBound + Math.random() * (upperBound - lowerBound)).toFixed( 85 | max(0, min(MAX_DECIMALS, decimals ?? 0)), 86 | ); 87 | } 88 | } 89 | 90 | // no positional or named args: just return Math.random() w/ default decimal precision 91 | return +Math.random().toFixed(max(0, min(MAX_DECIMALS, decimals ?? 0))); 92 | } 93 | 94 | export default helper(random); 95 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/round.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface RoundSignature { 4 | Args: { 5 | Named: { decimals?: number; exp?: number }; 6 | Positional: [number]; 7 | }; 8 | Return: number; 9 | } 10 | 11 | // adapted from: 12 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round#Decimal_rounding 13 | /** 14 | * Decimal adjustment of a number. 15 | * 16 | * @private 17 | * @param value The number. 18 | * @param exp The exponent (the 10 logarithm of the adjustment base). 19 | * @return {number} The adjusted value. 20 | */ 21 | function decimalAdjust(value: number, exp: number): number { 22 | // If the exp is undefined or zero... 23 | if (typeof exp === 'undefined' || +exp === 0) { 24 | return Math.round(value); 25 | } 26 | 27 | value = +value; 28 | exp = +exp; 29 | 30 | // If the value is not a number or the exp is not an integer... 31 | if ( 32 | value === null || 33 | isNaN(value) || 34 | !(typeof exp === 'number' && exp % 1 === 0) 35 | ) { 36 | return NaN; 37 | } 38 | 39 | // If the value is negative... 40 | if (value < 0) { 41 | return -decimalAdjust(-value, exp); 42 | } 43 | 44 | // Shift 45 | let splitValue = value.toString().split('e'); 46 | value = Math.round( 47 | +`${splitValue[0]}e${splitValue[1] ? +splitValue[1] - exp : -exp}`, 48 | ); 49 | // Shift back 50 | splitValue = value.toString().split('e'); 51 | 52 | return +`${splitValue[0]}e${splitValue[1] ? +splitValue[1] + exp : exp}`; 53 | } 54 | 55 | /** 56 | * Executes `Math.round` on the number passed to the helper. 57 | * 58 | * ```hbs 59 | * {{round a}} 60 | * ``` 61 | * 62 | * You can provide optional named arguments for `decimals` and `exp` that will adjust 63 | * the number of decimals used for rounding and the exponent (the 10 logarithm of the adjustment base) accordingly. 64 | * 65 | * For example: 66 | * 67 | * ```hbs 68 | * {{round a decimals=2}} 69 | * ``` 70 | * 71 | * @function round 72 | * @param {number} number The number to pass to `Math.round` 73 | * @param {object} named The set of named arguments, currently `decimals` and `exp`. 74 | * @param {number} [named.decimals] An optional param to specify the number of decimals to round to. 75 | * @param {number} [named.exp] An optional param to specify the exponent (the 10 logarithm of the adjustment base). 76 | * @return {number} The number rounded based on the number of decimals specified. 77 | */ 78 | export function round( 79 | [number]: [number], 80 | namedArgs: RoundSignature['Args']['Named'], 81 | ) { 82 | if (namedArgs) { 83 | if (namedArgs.decimals) { 84 | return decimalAdjust(number, -namedArgs.decimals); 85 | } 86 | 87 | if (namedArgs.exp) { 88 | return decimalAdjust(number, namedArgs.exp); 89 | } 90 | } 91 | 92 | return Math.round(number); 93 | } 94 | 95 | export default helper(round); 96 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/sign.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface SignSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.sign` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{sign a}} 15 | * ``` 16 | * 17 | * @function sign 18 | * @param {number} number The number to pass to `Math.sign` 19 | * @return {number} The sign of the passed number 20 | */ 21 | export function sign([number]: [number]) { 22 | return Math.sign(number); 23 | } 24 | 25 | export default helper(sign); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/sin.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface SinSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.sin` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{sin a}} 15 | * ``` 16 | * 17 | * @function sin 18 | * @param {number} number The number to pass to `Math.sin` 19 | * @return {number} The sin of the passed number 20 | */ 21 | export function sin([number]: [number]) { 22 | return Math.sin(number); 23 | } 24 | 25 | export default helper(sin); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/sqrt.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface SqrtSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.sqrt` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{sqrt a}} 15 | * ``` 16 | * 17 | * @function sqrt 18 | * @param {number} number The number to pass to `Math.sqrt` 19 | * @return {number} The sqrt of the passed number 20 | */ 21 | export function sqrt([number]: [number]) { 22 | return Math.sqrt(number); 23 | } 24 | 25 | export default helper(sqrt); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/sub.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface SubSignature { 4 | Args: { 5 | Positional: Array; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Subtracts two or more numbers 12 | * 13 | * ```hbs 14 | * {{sub a b}} 15 | * ``` 16 | * 17 | * @function sub 18 | * @param {number[]} numbers A list of numbers to subtract 19 | * @return {number} The difference of all the passed numbers 20 | */ 21 | export function sub(numbers: Array) { 22 | return numbers.reduce((a, b) => Number(a) - Number(b)); 23 | } 24 | 25 | export default helper(sub); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/sum.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | import { add, type AddSignature } from './add.ts'; 4 | 5 | /** 6 | * Alias for {{add}} helper 7 | * 8 | * ```hbs 9 | * {{sum a b}} 10 | * ``` 11 | * 12 | * @function sum 13 | * @param {number[]} numbers A list of numbers to sum 14 | * @return {number} The sum of all the passed numbers 15 | */ 16 | export function sum(numbers: Array) { 17 | return add(numbers); 18 | } 19 | 20 | export default helper(sum); 21 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/tan.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface TanSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.tan` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{tan a}} 15 | * ``` 16 | * 17 | * @function tan 18 | * @param {number} number The number to pass to `Math.tan` 19 | * @return {number} The tan of the passed number 20 | */ 21 | export function tan([number]: [number]) { 22 | return Math.tan(number); 23 | } 24 | 25 | export default helper(tan); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/tanh.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface TanhSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.tanh` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{tanh a}} 15 | * ``` 16 | * 17 | * @function tanh 18 | * @param {number} number The number to pass to `Math.tanh` 19 | * @return {number} The tanh of the passed number 20 | */ 21 | export function tanh([number]: [number]) { 22 | return Math.tanh(number); 23 | } 24 | 25 | export default helper(tanh); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/helpers/trunc.ts: -------------------------------------------------------------------------------- 1 | import { helper } from '@ember/component/helper'; 2 | 3 | export interface TruncSignature { 4 | Args: { 5 | Positional: [number]; 6 | }; 7 | Return: number; 8 | } 9 | 10 | /** 11 | * Executes `Math.trunc` on the number passed to the helper. 12 | * 13 | * ```hbs 14 | * {{trunc a}} 15 | * ``` 16 | * 17 | * @function trunc 18 | * @param {number} number The number to pass to `Math.trunc` 19 | * @return {number} The trunc of the passed number 20 | */ 21 | export function trunc([number]: [number]) { 22 | return Math.trunc(number); 23 | } 24 | 25 | export default helper(trunc); 26 | -------------------------------------------------------------------------------- /ember-math-helpers/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as abs } from './helpers/abs.ts'; 2 | export { default as acos } from './helpers/acos.ts'; 3 | export { default as acosh } from './helpers/acosh.ts'; 4 | export { default as add } from './helpers/add.ts'; 5 | export { default as asin } from './helpers/asin.ts'; 6 | export { default as asinh } from './helpers/asinh.ts'; 7 | export { default as atan } from './helpers/atan.ts'; 8 | export { default as atan2 } from './helpers/atan2.ts'; 9 | export { default as atanh } from './helpers/atanh.ts'; 10 | export { default as cbrt } from './helpers/cbrt.ts'; 11 | export { default as ceil } from './helpers/ceil.ts'; 12 | export { default as clz32 } from './helpers/clz32.ts'; 13 | export { default as cos } from './helpers/cos.ts'; 14 | export { default as cosh } from './helpers/cosh.ts'; 15 | export { default as div } from './helpers/div.ts'; 16 | export { default as exp } from './helpers/exp.ts'; 17 | export { default as expm1 } from './helpers/expm1.ts'; 18 | export { default as floor } from './helpers/floor.ts'; 19 | export { default as fround } from './helpers/fround.ts'; 20 | export { default as gcd } from './helpers/gcd.ts'; 21 | export { default as hypot } from './helpers/hypot.ts'; 22 | export { default as imul } from './helpers/imul.ts'; 23 | export { default as lcm } from './helpers/lcm.ts'; 24 | export { default as loge } from './helpers/log-e.ts'; 25 | export { default as log1p } from './helpers/log1p.ts'; 26 | export { default as log2 } from './helpers/log2.ts'; 27 | export { default as log10 } from './helpers/log10.ts'; 28 | export { default as max } from './helpers/max.ts'; 29 | export { default as min } from './helpers/min.ts'; 30 | export { default as mod } from './helpers/mod.ts'; 31 | export { default as mult } from './helpers/mult.ts'; 32 | export { default as pow } from './helpers/pow.ts'; 33 | export { default as random } from './helpers/random.ts'; 34 | export { default as round } from './helpers/round.ts'; 35 | export { default as sign } from './helpers/sign.ts'; 36 | export { default as sin } from './helpers/sin.ts'; 37 | export { default as sqrt } from './helpers/sqrt.ts'; 38 | export { default as sub } from './helpers/sub.ts'; 39 | export { default as sum } from './helpers/sum.ts'; 40 | export { default as tan } from './helpers/tan.ts'; 41 | export { default as tanh } from './helpers/tanh.ts'; 42 | export { default as trunc } from './helpers/trunc.ts'; 43 | -------------------------------------------------------------------------------- /ember-math-helpers/src/template-registry.ts: -------------------------------------------------------------------------------- 1 | import type AbsHelper from './helpers/abs'; 2 | import type AcosHelper from './helpers/acos'; 3 | import type AcoshHelper from './helpers/acosh'; 4 | import type AddHelper from './helpers/add'; 5 | import type AsinHelper from './helpers/asin'; 6 | import type AsinhHelper from './helpers/asinh'; 7 | import type AtanHelper from './helpers/atan'; 8 | import type Atan2Helper from './helpers/atan2'; 9 | import type AtanhHelper from './helpers/atanh'; 10 | import type CbrtHelper from './helpers/cbrt'; 11 | import type CeilHelper from './helpers/ceil'; 12 | import type Clz32Helper from './helpers/clz32'; 13 | import type CosHelper from './helpers/cos'; 14 | import type CoshHelper from './helpers/cosh'; 15 | import type DivHelper from './helpers/div'; 16 | import type ExpHelper from './helpers/exp'; 17 | import type Expm1Helper from './helpers/expm1'; 18 | import type FloorHelper from './helpers/floor'; 19 | import type FroundHelper from './helpers/fround'; 20 | import type GcdHelper from './helpers/gcd'; 21 | import type HypotHelper from './helpers/hypot'; 22 | import type ImulHelper from './helpers/imul'; 23 | import type LcmHelper from './helpers/lcm'; 24 | import type LogEHelper from './helpers/log-e'; 25 | import type Log10Helper from './helpers/log10'; 26 | import type Log1PHelper from './helpers/log1p'; 27 | import type Log2Helper from './helpers/log2'; 28 | import type MaxHelper from './helpers/max'; 29 | import type MinHelper from './helpers/min'; 30 | import type ModHelper from './helpers/mod'; 31 | import type MultHelper from './helpers/mult'; 32 | import type PowHelper from './helpers/pow'; 33 | import type RandomHelper from './helpers/random'; 34 | import type RoundHelper from './helpers/round'; 35 | import type SignHelper from './helpers/sign'; 36 | import type SinHelper from './helpers/sin'; 37 | import type SqrtHelper from './helpers/sqrt'; 38 | import type SubHelper from './helpers/sub'; 39 | import type SumHelper from './helpers/sum'; 40 | import type TanHelper from './helpers/tan'; 41 | import type TanhHelper from './helpers/tanh'; 42 | import type TruncHelper from './helpers/trunc'; 43 | 44 | export default interface Registry { 45 | abs: typeof AbsHelper; 46 | acos: typeof AcosHelper; 47 | acosh: typeof AcoshHelper; 48 | add: typeof AddHelper; 49 | asin: typeof AsinHelper; 50 | asinh: typeof AsinhHelper; 51 | atan: typeof AtanHelper; 52 | atan2: typeof Atan2Helper; 53 | atanh: typeof AtanhHelper; 54 | cbrt: typeof CbrtHelper; 55 | ceil: typeof CeilHelper; 56 | clz32: typeof Clz32Helper; 57 | cos: typeof CosHelper; 58 | cosh: typeof CoshHelper; 59 | div: typeof DivHelper; 60 | exp: typeof ExpHelper; 61 | expm1: typeof Expm1Helper; 62 | floor: typeof FloorHelper; 63 | fround: typeof FroundHelper; 64 | gcd: typeof GcdHelper; 65 | hypot: typeof HypotHelper; 66 | imul: typeof ImulHelper; 67 | lcm: typeof LcmHelper; 68 | 'log-e': typeof LogEHelper; 69 | log10: typeof Log10Helper; 70 | log1p: typeof Log1PHelper; 71 | log2: typeof Log2Helper; 72 | max: typeof MaxHelper; 73 | min: typeof MinHelper; 74 | mod: typeof ModHelper; 75 | mult: typeof MultHelper; 76 | pow: typeof PowHelper; 77 | random: typeof RandomHelper; 78 | round: typeof RoundHelper; 79 | sign: typeof SignHelper; 80 | sin: typeof SinHelper; 81 | sqrt: typeof SqrtHelper; 82 | sub: typeof SubHelper; 83 | sum: typeof SumHelper; 84 | tan: typeof TanHelper; 85 | tanh: typeof TanhHelper; 86 | trunc: typeof TruncHelper; 87 | } 88 | -------------------------------------------------------------------------------- /ember-math-helpers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/ember/tsconfig.json", 3 | "include": ["src/**/*", "unpublished-development-types/**/*"], 4 | "glint": { 5 | "environment": ["ember-loose", "ember-template-imports"] 6 | }, 7 | "compilerOptions": { 8 | "allowJs": true, 9 | "declarationDir": "declarations", 10 | /** 11 | https://www.typescriptlang.org/tsconfig#noEmit 12 | 13 | We want to emit declarations, so this option must be set to `false`. 14 | @tsconfig/ember sets this to `true`, which is incompatible with our need to set `emitDeclarationOnly`. 15 | @tsconfig/ember is more optimized for apps, which wouldn't emit anything, only type check. 16 | */ 17 | "noEmit": false, 18 | /** 19 | https://www.typescriptlang.org/tsconfig#emitDeclarationOnly 20 | We want to only emit declarations as we use Rollup to emit JavaScript. 21 | */ 22 | "emitDeclarationOnly": true, 23 | 24 | /** 25 | https://www.typescriptlang.org/tsconfig#noEmitOnError 26 | Do not block emit on TS errors. 27 | */ 28 | "noEmitOnError": false, 29 | 30 | /** 31 | https://www.typescriptlang.org/tsconfig#rootDir 32 | "Default: The longest common path of all non-declaration input files." 33 | 34 | Because we want our declarations' structure to match our rollup output, 35 | we need this "rootDir" to match the "srcDir" in the rollup.config.mjs. 36 | 37 | This way, we can have simpler `package.json#exports` that matches 38 | imports to files on disk 39 | */ 40 | "rootDir": "./src", 41 | 42 | /** 43 | https://www.typescriptlang.org/tsconfig#allowImportingTsExtensions 44 | 45 | We want our tooling to know how to resolve our custom files so the appropriate plugins 46 | can do the proper transformations on those files. 47 | */ 48 | "allowImportingTsExtensions": true, 49 | 50 | "types": ["ember-source/types"] 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ember-math-helpers/unpublished-development-types/index.d.ts: -------------------------------------------------------------------------------- 1 | // Add any types here that you need for local development only. 2 | // These will *not* be published as part of your addon, so be careful that your published code does not rely on them! 3 | 4 | import '@glint/environment-ember-loose'; 5 | import '@glint/environment-ember-template-imports'; 6 | 7 | // Uncomment if you need to support consuming projects in loose mode 8 | // 9 | // declare module '@glint/environment-ember-loose/registry' { 10 | // export default interface Registry { 11 | // // Add any registry entries from other addons here that your addon itself uses (in non-strict mode templates) 12 | // // See https://typed-ember.gitbook.io/glint/using-glint/ember/using-addons 13 | // } 14 | // } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "repository": "https://github.com/RobbieTheWagner/ember-math-helpers", 4 | "license": "MIT", 5 | "author": { 6 | "name": "Robbie Wagner", 7 | "email": "rwwagner90@gmail.com", 8 | "url": "https://github.com/RobbieTheWagner" 9 | }, 10 | "scripts": { 11 | "build": "pnpm --filter ember-math-helpers build", 12 | "lint": "pnpm --filter '*' lint", 13 | "lint:fix": "pnpm --filter '*' lint:fix", 14 | "prepare": "pnpm build", 15 | "start": "concurrently 'pnpm:start:*' --restart-after 5000 --prefixColors auto", 16 | "start:addon": "pnpm --filter ember-math-helpers start --no-watch.clearScreen", 17 | "start:test-app": "pnpm --filter test-app start", 18 | "test": "pnpm --filter '*' test", 19 | "test:ember": "pnpm --filter '*' test:ember" 20 | }, 21 | "packageManager": "pnpm@10.7.1", 22 | "devDependencies": { 23 | "@glint/core": "^1.5.2", 24 | "concurrently": "^9.2.0", 25 | "npm-run-all": "^4.1.5", 26 | "prettier": "^3.6.2", 27 | "prettier-plugin-ember-template-tag": "^2.0.6", 28 | "release-plan": "^0.17.0" 29 | }, 30 | "pnpm": { 31 | "peerDependencyRules": { 32 | "ignoreMissing": [ 33 | "ember-cli-htmlbars" 34 | ] 35 | }, 36 | "overrides": { 37 | "ember-math-helpers": "workspace:*", 38 | "@glimmer/validator": "^0.84.3" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'ember-math-helpers' 3 | - 'test-app' 4 | -------------------------------------------------------------------------------- /test-app/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.hbs] 16 | insert_final_newline = false 17 | 18 | [*.{diff,md}] 19 | trim_trailing_whitespace = false 20 | -------------------------------------------------------------------------------- /test-app/.ember-cli: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Setting `isTypeScriptProject` to true will force the blueprint generators to generate TypeScript 4 | rather than JavaScript by default, when a TypeScript version of a given blueprint is available. 5 | */ 6 | "isTypeScriptProject": true 7 | } 8 | -------------------------------------------------------------------------------- /test-app/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist/ 3 | /declarations/ 4 | 5 | # dependencies 6 | /node_modules/ 7 | 8 | # misc 9 | /.env* 10 | /.pnp* 11 | /.eslintcache 12 | /coverage/ 13 | /npm-debug.log* 14 | /testem.log 15 | /yarn-error.log 16 | 17 | # ember-try 18 | /.node_modules.ember-try/ 19 | /npm-shrinkwrap.json.ember-try 20 | /package.json.ember-try 21 | /package-lock.json.ember-try 22 | /yarn.lock.ember-try 23 | 24 | # broccoli-debug 25 | /DEBUG/ 26 | 27 | # addon-docs 28 | /tmp/ 29 | -------------------------------------------------------------------------------- /test-app/.prettierignore: -------------------------------------------------------------------------------- 1 | # unconventional js 2 | /blueprints/*/files/ 3 | 4 | # compiled output 5 | /dist/ 6 | 7 | # misc 8 | /coverage/ 9 | !.* 10 | .*/ 11 | /pnpm-lock.yaml 12 | ember-cli-update.json 13 | *.html 14 | 15 | # ember-try 16 | /.node_modules.ember-try/ 17 | -------------------------------------------------------------------------------- /test-app/.prettierrc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | plugins: ['prettier-plugin-ember-template-tag'], 5 | overrides: [ 6 | { 7 | files: '*.{js,gjs,ts,gts,mjs,mts,cjs,cts}', 8 | options: { 9 | singleQuote: true, 10 | templateSingleQuote: false, 11 | }, 12 | }, 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /test-app/.stylelintignore: -------------------------------------------------------------------------------- 1 | # unconventional files 2 | /blueprints/*/files/ 3 | 4 | # compiled output 5 | /dist/ 6 | 7 | # addons 8 | /.node_modules.ember-try/ 9 | -------------------------------------------------------------------------------- /test-app/.stylelintrc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | extends: ['stylelint-config-standard', 'stylelint-prettier/recommended'], 5 | }; 6 | -------------------------------------------------------------------------------- /test-app/.template-lintrc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | extends: 'recommended', 5 | rules: { 6 | 'no-builtin-form-components': false, 7 | 'no-curly-component-invocation': { 8 | allow: ['input', 'svg-jar'], 9 | }, 10 | // TODO turn this back on when fixed https://github.com/ember-template-lint/ember-template-lint/issues/1135 11 | 'no-quoteless-attributes': false, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /test-app/.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["dist"] 3 | } 4 | -------------------------------------------------------------------------------- /test-app/README.md: -------------------------------------------------------------------------------- 1 | # test-app 2 | 3 | This README outlines the details of collaborating on this Ember application. 4 | A short introduction of this app could easily go here. 5 | 6 | ## Prerequisites 7 | 8 | You will need the following things properly installed on your computer. 9 | 10 | - [Git](https://git-scm.com/) 11 | - [Node.js](https://nodejs.org/) 12 | - [pnpm](https://pnpm.io/) 13 | - [Ember CLI](https://cli.emberjs.com/release/) 14 | - [Google Chrome](https://google.com/chrome/) 15 | 16 | ## Installation 17 | 18 | - `git clone ` this repository 19 | - `cd test-app` 20 | - `pnpm install` 21 | 22 | ## Running / Development 23 | 24 | - `pnpm start` 25 | - Visit your app at [http://localhost:4200](http://localhost:4200). 26 | - Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests). 27 | 28 | ### Code Generators 29 | 30 | Make use of the many generators for code, try `ember help generate` for more details 31 | 32 | ### Running Tests 33 | 34 | - `pnpm test` 35 | - `pnpm test:ember --server` 36 | 37 | ### Linting 38 | 39 | - `pnpm lint` 40 | - `pnpm lint:fix` 41 | 42 | ### Building 43 | 44 | - `pnpm ember build` (development) 45 | - `pnpm build` (production) 46 | 47 | ### Deploying 48 | 49 | Specify what it takes to deploy your app. 50 | 51 | ## Further Reading / Useful Links 52 | 53 | - [ember.js](https://emberjs.com/) 54 | - [ember-cli](https://cli.emberjs.com/release/) 55 | - Development Browser Extensions 56 | - [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) 57 | - [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/) 58 | -------------------------------------------------------------------------------- /test-app/app/app.ts: -------------------------------------------------------------------------------- 1 | import Application from '@ember/application'; 2 | import Resolver from 'ember-resolver'; 3 | import loadInitializers from 'ember-load-initializers'; 4 | import config from 'test-app/config/environment'; 5 | import { importSync, isDevelopingApp, macroCondition } from '@embroider/macros'; 6 | 7 | if (macroCondition(isDevelopingApp())) { 8 | importSync('./deprecation-workflow'); 9 | } 10 | 11 | export default class App extends Application { 12 | modulePrefix = config.modulePrefix; 13 | podModulePrefix = config.podModulePrefix; 14 | Resolver = Resolver; 15 | } 16 | 17 | loadInitializers(App, config.modulePrefix); 18 | -------------------------------------------------------------------------------- /test-app/app/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobbieTheWagner/ember-math-helpers/d2d111bffc0b8d90543a835fb951a3ae90d87141/test-app/app/components/.gitkeep -------------------------------------------------------------------------------- /test-app/app/components/editable-templates.hbs: -------------------------------------------------------------------------------- 1 |

2 | Basic Arithmetic 3 |

4 | 5 | 23 | 24 | 42 | 43 | 61 | 62 | 80 | 81 | 99 | 100 |

101 | Advanced Arithmetic 102 |

103 | 104 | 122 | 123 |

124 | Composable Examples 125 |

126 | 127 | 145 | 146 | 163 | 164 |

165 | Min, Max, Round 166 |

167 | 168 | 186 | 187 | 205 | 206 | 224 | 225 |

226 | Random Numbers 227 |

228 | 229 | 247 | 248 | 266 | 267 | 285 | 286 | 304 | 305 | 323 | 324 | -------------------------------------------------------------------------------- /test-app/app/components/editable-templates.js: -------------------------------------------------------------------------------- 1 | import Component from '@glimmer/component'; 2 | import { tracked } from '@glimmer/tracking'; 3 | 4 | export default class EditableTemplates extends Component { 5 | @tracked addTemplate = '{{add 1 2}}'; 6 | @tracked divTemplate = '{{div 20 10}}'; 7 | @tracked modTemplate = '{{mod 11 10}}'; 8 | @tracked multTemplate = '{{mult 6 6}}'; 9 | @tracked subTemplate = '{{sub 10 2}}'; 10 | 11 | @tracked gcdTemplate = '{{gcd 10 2}}'; 12 | 13 | @tracked composableSub = '{{sub 10 1 2 3}}'; 14 | @tracked composableComplex = '{{mult (div (add 15 5) 2) 10}}'; 15 | 16 | @tracked maxTemplate = '{{max 5 2 134 125 1234 5234 2}}'; 17 | @tracked minTemplate = '{{min 2 3 5 3 26 7 123}}'; 18 | 19 | @tracked randomTemplate = '{{random}}'; 20 | @tracked randomSingleBound = '{{random 42}}'; 21 | @tracked randomTwoBounds = '{{random 21 1797}}'; 22 | @tracked randomFloatTwoDecimals = '{{random decimals=2}}'; 23 | @tracked randomFloatFourDecimals = '{{random decimals=4}}'; 24 | @tracked randomBoundedAndDecimal = '{{random 93 20 decimals=1}}'; 25 | @tracked roundTemplate = '{{round 21.23}}'; 26 | 27 | classString = `docs-transition 28 | focus:docs-outline-0 29 | docs-border docs-border-transparent 30 | focus:docs-bg-white 31 | focus:docs-border-grey-light 32 | docs-placeholder-grey-darkest 33 | docs-rounded 34 | docs-bg-grey-lighter 35 | docs-py-2 docs-pr-4 36 | docs-pl-10 37 | docs-block 38 | docs-w-2/3 39 | docs-appearance-none 40 | docs-leading-normal 41 | docs-ds-input`; 42 | } 43 | -------------------------------------------------------------------------------- /test-app/app/components/render-template.hbs: -------------------------------------------------------------------------------- 1 | {{#if this.compileResult}} 2 | 3 | {{/if}} -------------------------------------------------------------------------------- /test-app/app/components/render-template.js: -------------------------------------------------------------------------------- 1 | import Component from '@glimmer/component'; 2 | import * as helpers from 'ember-math-helpers'; 3 | import { cached } from '@glimmer/tracking'; 4 | import { 5 | importSync, 6 | macroCondition, 7 | dependencySatisfies, 8 | } from '@embroider/macros'; 9 | 10 | export default class RenderTemplate extends Component { 11 | @cached 12 | get compileResult() { 13 | if (macroCondition(dependencySatisfies('ember-source', '>= 5.0.0'))) { 14 | const { compileHBS } = importSync('ember-repl/formats/hbs'); 15 | return compileHBS(this.args.templateString, { 16 | scope: { ...helpers }, 17 | }); 18 | } 19 | 20 | return false; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test-app/app/config/environment.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Type declarations for 3 | * import config from 'test-app/config/environment' 4 | */ 5 | declare const config: { 6 | environment: string; 7 | modulePrefix: string; 8 | podModulePrefix: string; 9 | locationType: 'history' | 'hash' | 'none'; 10 | rootURL: string; 11 | APP: Record; 12 | }; 13 | 14 | export default config; 15 | -------------------------------------------------------------------------------- /test-app/app/controllers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobbieTheWagner/ember-math-helpers/d2d111bffc0b8d90543a835fb951a3ae90d87141/test-app/app/controllers/.gitkeep -------------------------------------------------------------------------------- /test-app/app/deprecation-workflow.ts: -------------------------------------------------------------------------------- 1 | import setupDeprecationWorkflow from 'ember-cli-deprecation-workflow'; 2 | 3 | /** 4 | * Docs: https://github.com/ember-cli/ember-cli-deprecation-workflow 5 | */ 6 | setupDeprecationWorkflow({ 7 | /** 8 | false by default, but if a developer / team wants to be more aggressive about being proactive with 9 | handling their deprecations, this should be set to "true" 10 | */ 11 | throwOnUnhandled: false, 12 | workflow: [ 13 | /* ... handlers ... */ 14 | /* to generate this list, run your app for a while (or run the test suite), 15 | * and then run in the browser console: 16 | * 17 | * deprecationWorkflow.flushDeprecations() 18 | * 19 | * And copy the handlers here 20 | */ 21 | /* example: */ 22 | /* { handler: 'silence', matchId: 'template-action' }, */ 23 | ], 24 | }); 25 | -------------------------------------------------------------------------------- /test-app/app/helpers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobbieTheWagner/ember-math-helpers/d2d111bffc0b8d90543a835fb951a3ae90d87141/test-app/app/helpers/.gitkeep -------------------------------------------------------------------------------- /test-app/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TestApp 6 | 7 | 8 | 9 | {{content-for "head"}} 10 | 11 | 12 | 13 | 14 | {{content-for "head-footer"}} 15 | 16 | 17 | {{content-for "body"}} 18 | 19 | 20 | 21 | 22 | {{content-for "body-footer"}} 23 | 24 | 25 | -------------------------------------------------------------------------------- /test-app/app/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobbieTheWagner/ember-math-helpers/d2d111bffc0b8d90543a835fb951a3ae90d87141/test-app/app/models/.gitkeep -------------------------------------------------------------------------------- /test-app/app/router.js: -------------------------------------------------------------------------------- 1 | import AddonDocsRouter, { docsRoute } from 'ember-cli-addon-docs/router'; 2 | import config from 'test-app/config/environment'; 3 | 4 | const Router = AddonDocsRouter.extend({ 5 | location: config.locationType, 6 | rootURL: config.rootURL, 7 | }); 8 | 9 | Router.map(function () { 10 | docsRoute(this, function () { 11 | this.route('configuration'); 12 | this.route('playground'); 13 | this.route('usage'); 14 | 15 | this.route('not-found', { path: '/*path' }); 16 | }); 17 | }); 18 | 19 | export default Router; 20 | -------------------------------------------------------------------------------- /test-app/app/routes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobbieTheWagner/ember-math-helpers/d2d111bffc0b8d90543a835fb951a3ae90d87141/test-app/app/routes/.gitkeep -------------------------------------------------------------------------------- /test-app/app/styles/app.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --brand-primary: #ef898b; 3 | } 4 | 5 | body { 6 | background-color: white !important; 7 | } 8 | 9 | .hero { 10 | padding: 0 2rem; 11 | } 12 | -------------------------------------------------------------------------------- /test-app/app/templates/application.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | {{outlet}} 6 | 7 | 8 |
9 |
-------------------------------------------------------------------------------- /test-app/app/templates/docs.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | {{outlet}} 15 |
16 |
17 |
18 |
-------------------------------------------------------------------------------- /test-app/app/templates/docs/index.md: -------------------------------------------------------------------------------- 1 | # ember-math-helpers 2 | 3 | Ship Shape 4 | 5 | **[ember-math-helpers is built and maintained by Ship Shape. Contact us for Ember.js consulting, development, and training for your project](https://shipshape.io/ember-consulting/)**. 6 | 7 | [![npm version](https://badge.fury.io/js/ember-math-helpers.svg)](http://badge.fury.io/js/ember-math-helpers) 8 | ![Download count all time](https://img.shields.io/npm/dt/ember-math-helpers.svg) 9 | [![npm](https://img.shields.io/npm/dm/ember-math-helpers.svg)]() 10 | [![Ember Observer Score](http://emberobserver.com/badges/ember-math-helpers.svg)](http://emberobserver.com/addons/ember-math-helpers) 11 | [![CI](https://github.com/RobbieTheWagner/ember-math-helpers/actions/workflows/ci.yml/badge.svg)](https://github.com/RobbieTheWagner/ember-math-helpers/actions/workflows/ci.yml) 12 | 13 | HTMLBars template helpers for doing basic arithmetic operations 14 | 15 | ## Installation 16 | 17 | ```sh 18 | ember install ember-math-helpers 19 | ``` 20 | -------------------------------------------------------------------------------- /test-app/app/templates/docs/playground.md: -------------------------------------------------------------------------------- 1 | # Playground 2 | 3 | Here are a few interactive examples. Try changing the numbers in the templates 4 | and you should see the results update! 5 | 6 | 7 | -------------------------------------------------------------------------------- /test-app/app/templates/docs/usage.md: -------------------------------------------------------------------------------- 1 | ## Usage 2 | 3 | ### Advanced Arithmetic 4 | 5 | #### Greatest Common Divisor 6 | 7 | The `gcd` helper uses [the Euclidean Algorithm](https://en.wikipedia.org/wiki/Greatest_common_divisor#Using_Euclid's_algorithm) to find the largest positive integer that divides two integers. 8 | 9 | ```hbs 10 | {{gcd 100 48}} 11 | 12 | 13 | {{gcd 6 -10}} 14 | 15 | ``` 16 | 17 | If no arguments are passed, the helper will return 0. If one argument is passed, the helper will simply reflect it back. 18 | 19 | #### Least common multiple 20 | 21 | The `lcm` helper calculates the smallest positive integer that is divisible by both a and b. 22 | 23 | ```hbs 24 | {{lcm 15 12}} 25 | 26 | ``` 27 | 28 | ### Special Cases 29 | 30 | Right now, there is one special case: the `round` helper will also take either 31 | a `decimals` property or an `exp` property. `decimals` will round to the 32 | specified number of decimals, while `exp` will round to the given power of ten. 33 | For example: 34 | 35 | ```handlebars 36 | {{round 35.855 decimals=2}} {{! prints "35.86" }} 37 | ``` 38 | 39 | ```handlebars 40 | {{round 1234567 exp=3}} {{! prints "1235000" }} 41 | ``` 42 | 43 | ### Random 44 | 45 | | Helper | JavaScript | HTMLBars | 46 | | -------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------- | 47 | | random (No Args) [, decimals] | `Math.random()`, `decimals` sets precision from 0-20 (default: 0) | `{{random}}` or `{{random decimals=4}}` | 48 | | random (Upper Bound) [, round] | capped `Math.random()`, `decimals` sets precision from 0-20 (default: 0) | `{{random 42}}` or `{{random 42 decimals=4}}` | 49 | | random (Upper Bound, Lower Bound) [, round]) | bounded `Math.random()`, `decimals` sets precision from 0-20 (default: 0) | `{{random 21 1797}}` or `{{random 21 1797 decimals=4}}` | 50 | 51 | ## Composable Helpers 52 | 53 | There is full support for using all of the helpers together, to do complex math, 54 | even though complex calculations may be better left to JS. 55 | 56 | For something like `(15 + 5) / 2 * 10` you could do: 57 | 58 | ```hbs 59 | {{mult (div (add 15 5) 2) 10}} 60 | ``` 61 | -------------------------------------------------------------------------------- /test-app/app/templates/not-found.hbs: -------------------------------------------------------------------------------- 1 |
2 |

Not found

3 |

This page doesn't exist. Head home?

4 |
-------------------------------------------------------------------------------- /test-app/config/addon-docs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const AddonDocsConfig = require('ember-cli-addon-docs/lib/config'); 4 | 5 | module.exports = class extends AddonDocsConfig { 6 | // See https://ember-learn.github.io/ember-cli-addon-docs/docs/deploying 7 | // for details on configuration you can override here. 8 | getPrimaryBranch() { 9 | return 'main'; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /test-app/config/deploy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function (deployTarget) { 4 | let ENV = { 5 | build: {}, 6 | git: { 7 | repo: 'git@github.com:RobbieTheWagner/ember-math-helpers.git', 8 | }, 9 | }; 10 | 11 | if (deployTarget === 'development') { 12 | ENV.build.environment = 'development'; 13 | // configure other plugins for development deploy target here 14 | } 15 | 16 | if (deployTarget === 'staging') { 17 | ENV.build.environment = 'production'; 18 | // configure other plugins for staging deploy target here 19 | } 20 | 21 | if (deployTarget === 'production') { 22 | ENV.build.environment = 'production'; 23 | // configure other plugins for production deploy target here 24 | } 25 | 26 | // Note: if you need to build some configuration asynchronously, you can return 27 | // a promise that resolves with the ENV object instead of returning the 28 | // ENV object synchronously. 29 | return ENV; 30 | }; 31 | -------------------------------------------------------------------------------- /test-app/config/ember-cli-update.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": "1.0.0", 3 | "packages": [ 4 | { 5 | "name": "ember-cli", 6 | "version": "6.3.0", 7 | "blueprints": [ 8 | { 9 | "name": "app", 10 | "outputRepo": "https://github.com/ember-cli/ember-new-output", 11 | "codemodsSource": "ember-app-codemods-manifest@1", 12 | "isBaseBlueprint": true, 13 | "options": [ 14 | "--no-welcome", 15 | "--pnpm", 16 | "--ci-provider=github", 17 | "--typescript" 18 | ] 19 | } 20 | ] 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /test-app/config/ember-try.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const getChannelURL = require('ember-source-channel-url'); 4 | const { embroiderSafe, embroiderOptimized } = require('@embroider/test-setup'); 5 | 6 | module.exports = async function () { 7 | return { 8 | usePnpm: true, 9 | buildManagerOptions() { 10 | return ['--ignore-scripts', '--no-frozen-lockfile']; 11 | }, 12 | scenarios: [ 13 | { 14 | name: 'ember-lts-4.12', 15 | npm: { 16 | devDependencies: { 17 | 'ember-source': '~4.12.0', 18 | }, 19 | }, 20 | }, 21 | { 22 | name: 'ember-lts-5.4', 23 | npm: { 24 | devDependencies: { 25 | 'ember-source': '~5.4.0', 26 | }, 27 | }, 28 | }, 29 | { 30 | name: 'ember-release', 31 | npm: { 32 | devDependencies: { 33 | 'ember-source': await getChannelURL('release'), 34 | }, 35 | }, 36 | }, 37 | { 38 | name: 'ember-beta', 39 | npm: { 40 | devDependencies: { 41 | 'ember-source': await getChannelURL('beta'), 42 | }, 43 | }, 44 | }, 45 | { 46 | name: 'ember-canary', 47 | npm: { 48 | devDependencies: { 49 | 'ember-source': await getChannelURL('canary'), 50 | }, 51 | }, 52 | }, 53 | embroiderSafe(), 54 | embroiderOptimized(), 55 | ], 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /test-app/config/environment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function (environment) { 4 | const ENV = { 5 | modulePrefix: 'test-app', 6 | environment, 7 | rootURL: '/', 8 | locationType: 'history', 9 | EmberENV: { 10 | EXTEND_PROTOTYPES: false, 11 | FEATURES: { 12 | // Here you can enable experimental features on an ember canary build 13 | // e.g. EMBER_NATIVE_DECORATOR_SUPPORT: true 14 | }, 15 | }, 16 | 17 | APP: { 18 | // Here you can pass flags/options to your application instance 19 | // when it is created 20 | }, 21 | }; 22 | 23 | if (environment === 'development') { 24 | // ENV.APP.LOG_RESOLVER = true; 25 | // ENV.APP.LOG_ACTIVE_GENERATION = true; 26 | // ENV.APP.LOG_TRANSITIONS = true; 27 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; 28 | // ENV.APP.LOG_VIEW_LOOKUPS = true; 29 | } 30 | 31 | if (environment === 'test') { 32 | // Testem prefers this... 33 | ENV.locationType = 'none'; 34 | 35 | // keep test console output quieter 36 | ENV.APP.LOG_ACTIVE_GENERATION = false; 37 | ENV.APP.LOG_VIEW_LOOKUPS = false; 38 | 39 | ENV.APP.rootElement = '#ember-testing'; 40 | ENV.APP.autoboot = false; 41 | } 42 | 43 | if (environment === 'production') { 44 | // Allow ember-cli-addon-docs to update the rootURL in compiled assets 45 | ENV.rootURL = '/ADDON_DOCS_ROOT_URL/'; 46 | } 47 | 48 | return ENV; 49 | }; 50 | -------------------------------------------------------------------------------- /test-app/config/optional-features.json: -------------------------------------------------------------------------------- 1 | { 2 | "application-template-wrapper": false, 3 | "default-async-observers": true, 4 | "jquery-integration": false, 5 | "template-only-glimmer-components": true, 6 | "no-implicit-route-model": true 7 | } 8 | -------------------------------------------------------------------------------- /test-app/config/targets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const browsers = [ 4 | 'last 1 Chrome versions', 5 | 'last 1 Firefox versions', 6 | 'last 1 Safari versions', 7 | ]; 8 | 9 | module.exports = { 10 | browsers, 11 | }; 12 | -------------------------------------------------------------------------------- /test-app/ember-cli-build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const EmberApp = require('ember-cli/lib/broccoli/ember-app'); 5 | 6 | module.exports = function (defaults) { 7 | // dist/index.js 8 | let mathHelpersEntry = require.resolve('ember-math-helpers'); 9 | 10 | // We can never assume a node_modules structure 11 | let mathHelpersDir = path.dirname(path.dirname(mathHelpersEntry)); 12 | 13 | const app = new EmberApp(defaults, { 14 | autoImport: { 15 | watchDependencies: ['ember-math-helpers'], 16 | }, 17 | 'ember-cli-babel': { enableTypeScriptTransform: true }, 18 | 'ember-cli-addon-docs': { 19 | documentingAddonAt: mathHelpersDir, 20 | }, 21 | webpack: { 22 | node: { 23 | global: false, 24 | __filename: true, 25 | __dirname: true, 26 | }, 27 | resolve: { 28 | fallback: { 29 | path: 'path-browserify', 30 | }, 31 | }, 32 | }, 33 | }); 34 | 35 | const { maybeEmbroider } = require('@embroider/test-setup'); 36 | 37 | return maybeEmbroider(app); 38 | }; 39 | -------------------------------------------------------------------------------- /test-app/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Debugging: 3 | * https://eslint.org/docs/latest/use/configure/debug 4 | * ---------------------------------------------------- 5 | * 6 | * Print a file's calculated configuration 7 | * 8 | * npx eslint --print-config path/to/file.js 9 | * 10 | * Inspecting the config 11 | * 12 | * npx eslint --inspect-config 13 | * 14 | */ 15 | import globals from 'globals'; 16 | import js from '@eslint/js'; 17 | 18 | import ts from 'typescript-eslint'; 19 | 20 | import ember from 'eslint-plugin-ember/recommended'; 21 | 22 | import eslintConfigPrettier from 'eslint-config-prettier'; 23 | import qunit from 'eslint-plugin-qunit'; 24 | import n from 'eslint-plugin-n'; 25 | 26 | import babelParser from '@babel/eslint-parser'; 27 | 28 | const parserOptions = { 29 | esm: { 30 | js: { 31 | ecmaFeatures: { modules: true }, 32 | ecmaVersion: 'latest', 33 | requireConfigFile: false, 34 | babelOptions: { 35 | plugins: [ 36 | [ 37 | '@babel/plugin-proposal-decorators', 38 | { decoratorsBeforeExport: true }, 39 | ], 40 | ], 41 | }, 42 | }, 43 | ts: { 44 | projectService: true, 45 | tsconfigRootDir: import.meta.dirname, 46 | }, 47 | }, 48 | }; 49 | 50 | export default ts.config( 51 | js.configs.recommended, 52 | ember.configs.base, 53 | ember.configs.gjs, 54 | ember.configs.gts, 55 | eslintConfigPrettier, 56 | /** 57 | * Ignores must be in their own object 58 | * https://eslint.org/docs/latest/use/configure/ignore 59 | */ 60 | { 61 | ignores: ['dist/', 'node_modules/', 'coverage/', 'tmp/', '!**/.*'], 62 | }, 63 | /** 64 | * https://eslint.org/docs/latest/use/configure/configuration-files#configuring-linter-options 65 | */ 66 | { 67 | linterOptions: { 68 | reportUnusedDisableDirectives: 'error', 69 | }, 70 | }, 71 | { 72 | files: ['**/*.js'], 73 | languageOptions: { 74 | parser: babelParser, 75 | }, 76 | }, 77 | { 78 | files: ['**/*.{js,gjs}'], 79 | languageOptions: { 80 | parserOptions: parserOptions.esm.js, 81 | globals: { 82 | ...globals.browser, 83 | }, 84 | }, 85 | }, 86 | { 87 | files: ['**/*.{ts,gts}'], 88 | languageOptions: { 89 | parser: ember.parser, 90 | parserOptions: parserOptions.esm.ts, 91 | }, 92 | extends: [...ts.configs.recommendedTypeChecked, ember.configs.gts], 93 | }, 94 | { 95 | files: ['tests/**/*-test.{js,gjs,ts,gts}'], 96 | plugins: { 97 | qunit, 98 | }, 99 | }, 100 | /** 101 | * CJS node files 102 | */ 103 | { 104 | files: [ 105 | '**/*.cjs', 106 | 'config/**/*.js', 107 | 'tests/dummy/config/**/*.js', 108 | 'testem.js', 109 | 'testem*.js', 110 | 'index.js', 111 | '.prettierrc.js', 112 | '.stylelintrc.js', 113 | '.template-lintrc.js', 114 | 'ember-cli-build.js', 115 | ], 116 | plugins: { 117 | n, 118 | }, 119 | 120 | languageOptions: { 121 | sourceType: 'script', 122 | ecmaVersion: 'latest', 123 | globals: { 124 | ...globals.node, 125 | }, 126 | }, 127 | }, 128 | /** 129 | * ESM node files 130 | */ 131 | { 132 | files: ['**/*.mjs'], 133 | plugins: { 134 | n, 135 | }, 136 | 137 | languageOptions: { 138 | sourceType: 'module', 139 | ecmaVersion: 'latest', 140 | parserOptions: parserOptions.esm.js, 141 | globals: { 142 | ...globals.node, 143 | }, 144 | }, 145 | }, 146 | ); 147 | -------------------------------------------------------------------------------- /test-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-app", 3 | "private": true, 4 | "description": "Test app for ember-math-helpers addon", 5 | "repository": "https://github.com/RobbieTheWagner/ember-math-helpers", 6 | "license": "MIT", 7 | "author": "", 8 | "directories": { 9 | "doc": "doc", 10 | "test": "tests" 11 | }, 12 | "scripts": { 13 | "build": "ember build --environment=production", 14 | "format": "prettier . --cache --write", 15 | "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\" --prefixColors auto", 16 | "lint:css": "stylelint \"**/*.css\"", 17 | "lint:css:fix": "concurrently \"pnpm:lint:css -- --fix\"", 18 | "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\" --prefixColors auto && pnpm format", 19 | "lint:format": "prettier . --cache --check", 20 | "lint:hbs": "ember-template-lint .", 21 | "lint:hbs:fix": "ember-template-lint . --fix", 22 | "lint:js": "eslint . --cache", 23 | "lint:js:fix": "eslint . --fix", 24 | "lint:types": "tsc --noEmit", 25 | "start": "ember serve", 26 | "test": "concurrently \"pnpm:lint\" \"pnpm:test:*\" --names \"lint,test:\" --prefixColors auto", 27 | "test:ember": "ember test" 28 | }, 29 | "dependencies": { 30 | "ember-math-helpers": "workspace:*" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "7.28.0", 34 | "@babel/eslint-parser": "^7.28.0", 35 | "@babel/plugin-proposal-decorators": "^7.28.0", 36 | "@ember-data/adapter": "~5.6.0", 37 | "@ember-data/graph": "~5.6.0", 38 | "@ember-data/json-api": "~5.6.0", 39 | "@ember-data/legacy-compat": "~5.6.0", 40 | "@ember-data/model": "~5.6.0", 41 | "@ember-data/request": "~5.6.0", 42 | "@ember-data/request-utils": "~5.6.0", 43 | "@ember-data/serializer": "~5.6.0", 44 | "@ember-data/store": "~5.6.0", 45 | "@ember-data/tracking": "~5.4.1", 46 | "@ember/optional-features": "^2.2.0", 47 | "@ember/string": "^3.1.1", 48 | "@ember/test-helpers": "^5.2.2", 49 | "@embroider/compat": "^3.8.5", 50 | "@embroider/core": "^3.5.5", 51 | "@embroider/macros": "^1.18.0", 52 | "@embroider/test-setup": "^4.0.0", 53 | "@embroider/webpack": "^4.1.1", 54 | "@eslint/js": "^9.30.1", 55 | "@glimmer/component": "^2.0.0", 56 | "@glimmer/tracking": "^1.1.2", 57 | "@glint/environment-ember-loose": "^1.5.2", 58 | "@glint/environment-ember-template-imports": "^1.5.2", 59 | "@glint/template": "^1.5.2", 60 | "@tsconfig/ember": "^3.0.10", 61 | "@types/eslint__js": "^8.42.3", 62 | "@types/qunit": "^2.19.12", 63 | "@types/rsvp": "^4.0.9", 64 | "@warp-drive/core-types": "~5.6.0", 65 | "broccoli-asset-rev": "^3.0.0", 66 | "concurrently": "^9.2.0", 67 | "ember-auto-import": "^2.10.0", 68 | "ember-cli": "~6.3.0", 69 | "ember-cli-addon-docs": "^8.0.8", 70 | "ember-cli-addon-docs-yuidoc": "^1.1.0", 71 | "ember-cli-app-version": "^7.0.0", 72 | "ember-cli-babel": "^8.2.0", 73 | "ember-cli-clean-css": "^3.0.0", 74 | "ember-cli-code-coverage": "^3.1.0", 75 | "ember-cli-dependency-checker": "^3.3.3", 76 | "ember-cli-deploy": "^2.0.0", 77 | "ember-cli-deploy-build": "^2.0.0", 78 | "ember-cli-deploy-git": "^1.3.4", 79 | "ember-cli-deploy-git-ci": "^1.0.1", 80 | "ember-cli-deprecation-workflow": "^3.4.0", 81 | "ember-cli-htmlbars": "^6.3.0", 82 | "ember-cli-inject-live-reload": "^2.1.0", 83 | "ember-cli-sri": "^2.1.1", 84 | "ember-cli-terser": "^4.0.2", 85 | "ember-data": "^5.6.0", 86 | "ember-fetch": "^8.1.2", 87 | "ember-load-initializers": "^3.0.1", 88 | "ember-math-helpers": "workspace:*", 89 | "ember-modifier": "^4.2.2", 90 | "ember-page-title": "^9.0.2", 91 | "ember-qunit": "^9.0.3", 92 | "ember-repl": "^6.0.0", 93 | "ember-resolver": "^13.1.1", 94 | "ember-source": "^6.5.0", 95 | "ember-source-channel-url": "^3.0.0", 96 | "ember-template-imports": "^4.3.0", 97 | "ember-template-lint": "^7.9.1", 98 | "ember-try": "^4.0.0", 99 | "eslint": "^9.30.1", 100 | "eslint-config-prettier": "^10.1.5", 101 | "eslint-plugin-ember": "^12.5.0", 102 | "eslint-plugin-n": "^17.21.0", 103 | "eslint-plugin-qunit": "^8.2.3", 104 | "globals": "^16.3.0", 105 | "loader.js": "^4.7.0", 106 | "pnpm-sync-dependencies-meta-injected": "^0.0.14", 107 | "prettier": "^3.6.2", 108 | "prettier-plugin-ember-template-tag": "^2.0.6", 109 | "qunit": "^2.24.1", 110 | "qunit-dom": "^3.4.0", 111 | "stylelint": "^16.21.1", 112 | "stylelint-config-standard": "^38.0.0", 113 | "stylelint-prettier": "^5.0.3", 114 | "tracked-built-ins": "^4.0.0", 115 | "typescript": "^5.8.3", 116 | "typescript-eslint": "^8.36.0", 117 | "webpack": "^5.100.0" 118 | }, 119 | "engines": { 120 | "node": ">= 18" 121 | }, 122 | "ember": { 123 | "edition": "octane" 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /test-app/public/img/ember-math-helpers.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /test-app/testem.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | test_page: 'tests/index.html?hidepassed', 5 | disable_watching: true, 6 | launch_in_ci: ['Chrome'], 7 | launch_in_dev: ['Chrome'], 8 | browser_start_timeout: 120, 9 | browser_args: { 10 | Chrome: { 11 | ci: [ 12 | // --no-sandbox is needed when running Chrome inside a container 13 | process.env.CI ? '--no-sandbox' : null, 14 | '--headless', 15 | '--disable-dev-shm-usage', 16 | '--disable-software-rasterizer', 17 | '--mute-audio', 18 | '--remote-debugging-port=0', 19 | '--window-size=1440,900', 20 | ].filter(Boolean), 21 | }, 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /test-app/tests/helpers/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | setupApplicationTest as upstreamSetupApplicationTest, 3 | setupRenderingTest as upstreamSetupRenderingTest, 4 | setupTest as upstreamSetupTest, 5 | } from 'ember-qunit'; 6 | 7 | // This file exists to provide wrappers around ember-qunit's 8 | // test setup functions. This way, you can easily extend the setup that is 9 | // needed per test type. 10 | 11 | function setupApplicationTest(hooks, options) { 12 | upstreamSetupApplicationTest(hooks, options); 13 | 14 | // Additional setup for application tests can be done here. 15 | // 16 | // For example, if you need an authenticated session for each 17 | // application test, you could do: 18 | // 19 | // hooks.beforeEach(async function () { 20 | // await authenticateSession(); // ember-simple-auth 21 | // }); 22 | // 23 | // This is also a good place to call test setup functions coming 24 | // from other addons: 25 | // 26 | // setupIntl(hooks, 'en-us'); // ember-intl 27 | // setupMirage(hooks); // ember-cli-mirage 28 | } 29 | 30 | function setupRenderingTest(hooks, options) { 31 | upstreamSetupRenderingTest(hooks, options); 32 | 33 | // Additional setup for rendering tests can be done here. 34 | } 35 | 36 | function setupTest(hooks, options) { 37 | upstreamSetupTest(hooks, options); 38 | 39 | // Additional setup for unit tests can be done here. 40 | } 41 | 42 | export { setupApplicationTest, setupRenderingTest, setupTest }; 43 | -------------------------------------------------------------------------------- /test-app/tests/helpers/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | setupApplicationTest as upstreamSetupApplicationTest, 3 | setupRenderingTest as upstreamSetupRenderingTest, 4 | setupTest as upstreamSetupTest, 5 | type SetupTestOptions, 6 | } from 'ember-qunit'; 7 | 8 | // This file exists to provide wrappers around ember-qunit's 9 | // test setup functions. This way, you can easily extend the setup that is 10 | // needed per test type. 11 | 12 | function setupApplicationTest(hooks: NestedHooks, options?: SetupTestOptions) { 13 | upstreamSetupApplicationTest(hooks, options); 14 | 15 | // Additional setup for application tests can be done here. 16 | // 17 | // For example, if you need an authenticated session for each 18 | // application test, you could do: 19 | // 20 | // hooks.beforeEach(async function () { 21 | // await authenticateSession(); // ember-simple-auth 22 | // }); 23 | // 24 | // This is also a good place to call test setup functions coming 25 | // from other addons: 26 | // 27 | // setupIntl(hooks, 'en-us'); // ember-intl 28 | // setupMirage(hooks); // ember-cli-mirage 29 | } 30 | 31 | function setupRenderingTest(hooks: NestedHooks, options?: SetupTestOptions) { 32 | upstreamSetupRenderingTest(hooks, options); 33 | 34 | // Additional setup for rendering tests can be done here. 35 | } 36 | 37 | function setupTest(hooks: NestedHooks, options?: SetupTestOptions) { 38 | upstreamSetupTest(hooks, options); 39 | 40 | // Additional setup for unit tests can be done here. 41 | } 42 | 43 | export { setupApplicationTest, setupRenderingTest, setupTest }; 44 | -------------------------------------------------------------------------------- /test-app/tests/helpers/range.js: -------------------------------------------------------------------------------- 1 | export default (start, end) => 2 | Array.from({ length: end - start + 1 }, (x, idx) => start + idx); 3 | -------------------------------------------------------------------------------- /test-app/tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TestApp Tests 6 | 7 | 8 | 9 | {{content-for "head"}} 10 | {{content-for "test-head"}} 11 | 12 | 13 | 14 | 15 | 16 | {{content-for "head-footer"}} 17 | {{content-for "test-head-footer"}} 18 | 19 | 20 | {{content-for "body"}} 21 | {{content-for "test-body"}} 22 | 23 |
24 |
25 |
26 |
27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {{content-for "body-footer"}} 37 | {{content-for "test-body-footer"}} 38 | 39 | 40 | -------------------------------------------------------------------------------- /test-app/tests/integration/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobbieTheWagner/ember-math-helpers/d2d111bffc0b8d90543a835fb951a3ae90d87141/test-app/tests/integration/.gitkeep -------------------------------------------------------------------------------- /test-app/tests/test-helper.ts: -------------------------------------------------------------------------------- 1 | import Application from 'test-app/app'; 2 | import config from 'test-app/config/environment'; 3 | import * as QUnit from 'qunit'; 4 | import { setApplication } from '@ember/test-helpers'; 5 | import { setup } from 'qunit-dom'; 6 | import { loadTests } from 'ember-qunit/test-loader'; 7 | import { start, setupEmberOnerrorValidation } from 'ember-qunit'; 8 | 9 | setApplication(Application.create(config.APP)); 10 | 11 | setup(QUnit.assert); 12 | setupEmberOnerrorValidation(); 13 | loadTests(); 14 | start(); 15 | -------------------------------------------------------------------------------- /test-app/tests/unit/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RobbieTheWagner/ember-math-helpers/d2d111bffc0b8d90543a835fb951a3ae90d87141/test-app/tests/unit/.gitkeep -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/abs-test.js: -------------------------------------------------------------------------------- 1 | import { abs } from 'ember-math-helpers/helpers/abs'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | abs', function () { 5 | test('absolute value works', function (assert) { 6 | let result; 7 | result = abs([-1]); 8 | assert.strictEqual(result, 1); 9 | result = abs([1]); 10 | assert.strictEqual(result, 1); 11 | }); 12 | 13 | test('absolute value of `null`, empty string, and empty array all equal 0', function (assert) { 14 | let result; 15 | result = abs([null]); 16 | assert.strictEqual(result, 0); 17 | result = abs(['']); 18 | assert.strictEqual(result, 0); 19 | result = abs([[]]); 20 | assert.strictEqual(result, 0); 21 | }); 22 | 23 | test('absolute value of empty object literal equals `NaN`', function (assert) { 24 | const result = abs([{}]); 25 | assert.ok(isNaN(result)); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/acos-test.js: -------------------------------------------------------------------------------- 1 | import { acos } from 'ember-math-helpers/helpers/acos'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | acos', function () { 5 | test('acos works', function (assert) { 6 | const result = acos([1]); 7 | assert.strictEqual(result, 0); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/acosh-test.js: -------------------------------------------------------------------------------- 1 | import { acosh } from 'ember-math-helpers/helpers/acosh'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | acosh', function () { 5 | test('acosh works', function (assert) { 6 | const result = acosh([1]); 7 | assert.strictEqual(result, 0); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/add-test.js: -------------------------------------------------------------------------------- 1 | import { add } from 'ember-math-helpers/helpers/add'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | add', function () { 5 | test('addition works', function (assert) { 6 | const result = add([20, 10]); 7 | assert.strictEqual(result, 30); 8 | }); 9 | 10 | test('addition of multiple arguments works', function (assert) { 11 | const result = add([1, 2, 3, 4, 5]); 12 | assert.strictEqual(result, 15); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/asin-test.js: -------------------------------------------------------------------------------- 1 | import { asin } from 'ember-math-helpers/helpers/asin'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | asin', function () { 5 | test('asin works', function (assert) { 6 | const result = asin([0]); 7 | assert.strictEqual(result, 0); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/asinh-test.js: -------------------------------------------------------------------------------- 1 | import { asinh } from 'ember-math-helpers/helpers/asinh'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | asinh', function () { 5 | test('asinh works', function (assert) { 6 | const result = asinh([0]); 7 | assert.strictEqual(result, 0); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/atan-test.js: -------------------------------------------------------------------------------- 1 | import { atan } from 'ember-math-helpers/helpers/atan'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | atan', function () { 5 | test('atan works', function (assert) { 6 | const result = atan([0]); 7 | assert.strictEqual(result, 0); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/atan2-test.js: -------------------------------------------------------------------------------- 1 | import { atan2 } from 'ember-math-helpers/helpers/atan2'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | atan2', function () { 5 | test('atan2 works', function (assert) { 6 | const result = atan2([0, 1]); 7 | assert.strictEqual(result, 0); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/atanh-test.js: -------------------------------------------------------------------------------- 1 | import { atanh } from 'ember-math-helpers/helpers/atanh'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | atanh', function () { 5 | test('atanh works', function (assert) { 6 | const result = atanh([0]); 7 | assert.strictEqual(result, 0); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/cbrt-test.js: -------------------------------------------------------------------------------- 1 | import { cbrt } from 'ember-math-helpers/helpers/cbrt'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | cbrt', function () { 5 | test('cbrt works', function (assert) { 6 | const result = cbrt([27]); 7 | assert.strictEqual(result, 3); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/ceil-test.js: -------------------------------------------------------------------------------- 1 | import { ceil } from 'ember-math-helpers/helpers/ceil'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | ceil', function () { 5 | test('it works', function (assert) { 6 | let result = ceil([1]); 7 | assert.strictEqual(result, 1); 8 | 9 | result = ceil([1.01]); 10 | assert.strictEqual(result, 2); 11 | 12 | result = ceil([1.5]); 13 | assert.strictEqual(result, 2); 14 | 15 | result = ceil([1.99]); 16 | assert.strictEqual(result, 2); 17 | 18 | result = ceil([2]); 19 | assert.strictEqual(result, 2); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/clz32-test.js: -------------------------------------------------------------------------------- 1 | import { clz32 } from 'ember-math-helpers/helpers/clz32'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | clz32', function () { 5 | test('clz32 works', function (assert) { 6 | const result = clz32([1000]); 7 | assert.strictEqual(result, 22); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/cos-test.js: -------------------------------------------------------------------------------- 1 | import { cos } from 'ember-math-helpers/helpers/cos'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | cos', function () { 5 | test('cos works', function (assert) { 6 | const result = cos([0]); 7 | assert.strictEqual(result, 1); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/cosh-test.js: -------------------------------------------------------------------------------- 1 | import { cosh } from 'ember-math-helpers/helpers/cosh'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | cosh', function () { 5 | test('cosh works', function (assert) { 6 | const result = cosh([0]); 7 | assert.strictEqual(result, 1); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/div-test.js: -------------------------------------------------------------------------------- 1 | import { div } from 'ember-math-helpers/helpers/div'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | div', function () { 5 | test('division works', function (assert) { 6 | const result = div([20, 10]); 7 | assert.strictEqual(result, 2); 8 | }); 9 | 10 | test('division of multiple arguments works works', function (assert) { 11 | const result = div([96, 2, 3, 2, 2, 2, 2]); 12 | assert.strictEqual(result, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/exp-test.js: -------------------------------------------------------------------------------- 1 | import { exp } from 'ember-math-helpers/helpers/exp'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | exp', function () { 5 | test('exp works', function (assert) { 6 | const result = exp([1]); 7 | assert.strictEqual(Number(result.toFixed(3)), 2.718); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/expm1-test.js: -------------------------------------------------------------------------------- 1 | import { expm1 } from 'ember-math-helpers/helpers/expm1'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | expm1', function () { 5 | test('expm1 works', function (assert) { 6 | const result = expm1([1]); 7 | assert.strictEqual(Number(result.toFixed(3)), 1.718); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/floor-test.js: -------------------------------------------------------------------------------- 1 | import { floor } from 'ember-math-helpers/helpers/floor'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | floor', function () { 5 | test('it works', function (assert) { 6 | let result = floor([1]); 7 | assert.strictEqual(result, 1); 8 | 9 | result = floor([1.01]); 10 | assert.strictEqual(result, 1); 11 | 12 | result = floor([1.5]); 13 | assert.strictEqual(result, 1); 14 | 15 | result = floor([1.99]); 16 | assert.strictEqual(result, 1); 17 | 18 | result = floor([2]); 19 | assert.strictEqual(result, 2); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/fround-test.js: -------------------------------------------------------------------------------- 1 | import { fround } from 'ember-math-helpers/helpers/fround'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | fround', function () { 5 | test('fround works', function (assert) { 6 | const result = fround([1.337]); 7 | assert.strictEqual(result, 1.3370000123977661); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/gcd-test.js: -------------------------------------------------------------------------------- 1 | import { gcd } from 'ember-math-helpers/helpers/gcd'; 2 | import { module, test } from 'qunit'; 3 | import { setupTest } from 'ember-qunit'; 4 | 5 | module('Unit | Helper | gcd', function (hooks) { 6 | setupTest(hooks); 7 | 8 | module('Two integers', function () { 9 | test('computing gcd for a larger and smaller integer', function (assert) { 10 | assert.strictEqual(gcd([100, 48]), 4); 11 | assert.strictEqual(gcd([100, 0]), 100); 12 | }); 13 | 14 | test('computing gcd for a smaller and larger integer', function (assert) { 15 | assert.strictEqual(gcd([48, 100]), 4); 16 | assert.strictEqual(gcd([48, 0]), 48); 17 | }); 18 | 19 | test('computing gcd for the absolute value of two integers ', function (assert) { 20 | assert.strictEqual(gcd([-100, 48]), 4); 21 | assert.strictEqual(gcd([-100, -48]), 4); 22 | assert.strictEqual(gcd([100, -48]), 4); 23 | assert.strictEqual(gcd([0, -48]), 48); 24 | }); 25 | }); 26 | 27 | module('Edge-case inputs', function () { 28 | test('returning 0 by default', function (assert) { 29 | const result = gcd([]); 30 | 31 | assert.strictEqual(result, 0); 32 | }); 33 | 34 | test('reflecting back single-integer inputs', function (assert) { 35 | const result = gcd([48]); 36 | 37 | assert.strictEqual(result, 48); 38 | }); 39 | 40 | test('handling numeric strings', function (assert) { 41 | const result = gcd(['2', '4']); 42 | 43 | assert.strictEqual(result, 2); 44 | }); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/hypot-test.js: -------------------------------------------------------------------------------- 1 | import { hypot } from 'ember-math-helpers/helpers/hypot'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | hypot', function () { 5 | test('hypot works', function (assert) { 6 | const result = hypot([3, 4, 5]); 7 | assert.strictEqual(result, 7.0710678118654755); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/imul-test.js: -------------------------------------------------------------------------------- 1 | import { imul } from 'ember-math-helpers/helpers/imul'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | imul', function () { 5 | test('imul works', function (assert) { 6 | const result = imul([0xfffffffe, 5]); 7 | assert.strictEqual(result, -10); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/lcm-test.js: -------------------------------------------------------------------------------- 1 | import { lcm } from 'ember-math-helpers/helpers/lcm'; 2 | import { module, test } from 'qunit'; 3 | import { setupTest } from 'ember-qunit'; 4 | 5 | module('Unit | Helper | lcm', function (hooks) { 6 | setupTest(hooks); 7 | 8 | module('Two integers', function () { 9 | test('computing lcm for a larger and smaller integer', function (assert) { 10 | assert.strictEqual(lcm([100, 48]), 1200); 11 | assert.strictEqual(lcm([48, 100]), 1200); 12 | assert.strictEqual(lcm([12, 18]), 36); 13 | assert.strictEqual(lcm([100, 0]), 0); 14 | }); 15 | test('computing lcm for the absolute value of two integers ', function (assert) { 16 | assert.strictEqual(lcm([-100, 48]), 1200); 17 | assert.strictEqual(lcm([100, -48]), 1200); 18 | assert.strictEqual(lcm([-12, 18]), 36); 19 | assert.strictEqual(lcm([0, -48]), 0); 20 | }); 21 | }); 22 | module('Edge-case inputs', function () { 23 | test('returning 0 by default', function (assert) { 24 | const result = lcm([]); 25 | 26 | assert.strictEqual(result, 0); 27 | }); 28 | test('reflecting back single-integer inputs', function (assert) { 29 | const result = lcm([48]); 30 | 31 | assert.strictEqual(result, 0); 32 | }); 33 | test('handling numeric strings', function (assert) { 34 | const result = lcm(['2', '4']); 35 | 36 | assert.strictEqual(result, 4); 37 | }); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/log-e-test.js: -------------------------------------------------------------------------------- 1 | import { logE } from 'ember-math-helpers/helpers/log-e'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | logE', function () { 5 | test('logE works', function (assert) { 6 | const result = logE([0.5]); 7 | assert.strictEqual(Number(result.toFixed(3)), -0.693); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/log10-test.js: -------------------------------------------------------------------------------- 1 | import { log10 } from 'ember-math-helpers/helpers/log10'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | log10', function () { 5 | test('log10 works', function (assert) { 6 | const result = log10([2]); 7 | assert.strictEqual(Number(result.toFixed(3)), 0.301); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/log1p-test.js: -------------------------------------------------------------------------------- 1 | import { log1p } from 'ember-math-helpers/helpers/log1p'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | log1p', function () { 5 | test('log1p works', function (assert) { 6 | const result = log1p([0.5]); 7 | assert.strictEqual(Number(result.toFixed(3)), 0.405); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/log2-test.js: -------------------------------------------------------------------------------- 1 | import { log2 } from 'ember-math-helpers/helpers/log2'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | log2', function () { 5 | test('log2 works', function (assert) { 6 | const result = log2([2]); 7 | assert.strictEqual(result, 1); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/max-test.js: -------------------------------------------------------------------------------- 1 | import { max } from 'ember-math-helpers/helpers/max'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | max', function () { 5 | test('max works', function (assert) { 6 | assert.strictEqual( 7 | max([1, 2, 3, 5, 6, 42, 3, 6, 7]), 8 | 42, 9 | 'accepts multiple arguments', 10 | ); 11 | 12 | assert.strictEqual(max([42]), 42, 'accepts one argument'); 13 | 14 | assert.strictEqual( 15 | max([]), 16 | Number.NEGATIVE_INFINITY, 17 | 'accepts zero arguments', 18 | ); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/min-test.js: -------------------------------------------------------------------------------- 1 | import { min } from 'ember-math-helpers/helpers/min'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | min', function () { 5 | test('min works', function (assert) { 6 | assert.strictEqual( 7 | min([3, 2, 3, 5, 6, 42, 3, 6, 7]), 8 | 2, 9 | 'accepts multiple arguments', 10 | ); 11 | 12 | assert.strictEqual(min([42]), 42, 'accepts one argument'); 13 | 14 | assert.strictEqual(min([]), Infinity, 'accepts zero arguments'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/mod-test.js: -------------------------------------------------------------------------------- 1 | import { mod } from 'ember-math-helpers/helpers/mod'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | mod', function () { 5 | test('modulus works', function (assert) { 6 | const result = mod([20, 10]); 7 | assert.strictEqual(result, 0); 8 | }); 9 | 10 | test('modulus of multiple arguments works', function (assert) { 11 | const result = mod([10, 7, 2]); 12 | assert.strictEqual(result, 1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/mult-test.js: -------------------------------------------------------------------------------- 1 | import { mult } from 'ember-math-helpers/helpers/mult'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | mult', function () { 5 | test('multiplication works', function (assert) { 6 | const result = mult([20, 10]); 7 | assert.strictEqual(result, 200); 8 | }); 9 | 10 | test('multiplication of multiple arguments works', function (assert) { 11 | const result = mult([2, 2, 2, 2, 2, 3]); 12 | assert.strictEqual(result, 96); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/pow-test.js: -------------------------------------------------------------------------------- 1 | import { pow } from 'ember-math-helpers/helpers/pow'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | pow', function () { 5 | test('pow works', function (assert) { 6 | const result = pow([7, 2]); 7 | assert.strictEqual(result, 49); 8 | }); 9 | 10 | test('negative base works', function (assert) { 11 | const result = pow([-7, 2]); 12 | assert.strictEqual(result, 49); 13 | }); 14 | 15 | test('negative exponent works', function (assert) { 16 | const result = pow([2, -2]); 17 | assert.strictEqual(result, 0.25); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/random-test.js: -------------------------------------------------------------------------------- 1 | import { random } from 'ember-math-helpers/helpers/random'; 2 | import range from '../../helpers/range'; 3 | import { module, test } from 'qunit'; 4 | 5 | const { floor } = Math; 6 | const SAMPLE_SIZE = 100; 7 | const PRECISION = 6; 8 | 9 | // 💡 Because precise decimals aren't zero-padded, we can 10 | // tolerate some percentage of failures when dealing with decimal length 11 | const TOLERANCE = 0.25; // 75% pass-rate 12 | 13 | let randVal, satisfied, passCount, message; 14 | 15 | module('Unit | Helper | random', function () { 16 | function isPassing(passCount, sampleSize, toleranceRatio) { 17 | return passCount >= floor(sampleSize * (1 - toleranceRatio)); 18 | } 19 | 20 | function numDecimals(floatingPointNum) { 21 | return floatingPointNum.toPrecision().split('.')[1].length; 22 | } 23 | 24 | test('no positional arguments', function (assert) { 25 | message = 'defaults to returning the whole numbers of either 0 or 1'; 26 | 27 | passCount = range(1, SAMPLE_SIZE).reduce((acc) => { 28 | randVal = random(); 29 | satisfied = randVal === 0 || randVal === 1; 30 | 31 | return satisfied ? acc + 1 : acc; 32 | }, 0); 33 | 34 | assert.ok(isPassing(passCount, SAMPLE_SIZE, TOLERANCE), message); 35 | 36 | message = 37 | 'returns a number between 0 and 1, with decimal precision specified by `decimals`'; 38 | 39 | passCount = range(1, SAMPLE_SIZE).reduce((acc) => { 40 | randVal = random({ decimals: PRECISION }); 41 | 42 | satisfied = 43 | randVal > 0 && randVal < 1 && numDecimals(randVal) <= PRECISION; 44 | 45 | return satisfied ? acc + 1 : acc; 46 | }, 0); 47 | 48 | assert.ok(isPassing(passCount, SAMPLE_SIZE, TOLERANCE), message); 49 | }); 50 | 51 | test('one positional argument', function (assert) { 52 | message = 'returns a random whole number between 0 and 42, inclusive'; 53 | 54 | passCount = range(1, SAMPLE_SIZE).reduce((acc) => { 55 | randVal = random([42]); 56 | 57 | satisfied = randVal >= 0 && randVal <= 42; 58 | 59 | return satisfied ? acc + 1 : acc; 60 | }, 0); 61 | 62 | assert.ok(isPassing(passCount, SAMPLE_SIZE, TOLERANCE), message); 63 | 64 | message = 65 | 'returns a random number between 0 and a single positional arg, with decimal precision specified by `decimals`'; 66 | passCount = range(1, SAMPLE_SIZE).reduce((acc) => { 67 | randVal = random([42], { decimals: PRECISION }); 68 | 69 | satisfied = 70 | randVal > 0 && randVal < 42 && numDecimals(randVal) <= PRECISION; 71 | 72 | return satisfied ? acc + 1 : acc; 73 | }, 0); 74 | 75 | assert.ok(isPassing(passCount, SAMPLE_SIZE, TOLERANCE), message); 76 | }); 77 | 78 | test('two positional arguments', function (assert) { 79 | message = 80 | 'returns a random whole number between two upper and lower bound postional args, inclusive'; 81 | passCount = range(1, SAMPLE_SIZE).reduce((acc) => { 82 | randVal = random([1797, 21]); 83 | 84 | satisfied = randVal >= 21 && randVal <= 1797; 85 | 86 | return satisfied ? acc + 1 : acc; 87 | }, 0); 88 | 89 | assert.ok(isPassing(passCount, SAMPLE_SIZE, TOLERANCE), message); 90 | 91 | message = 92 | 'returns a random number between two upper and lower bound postional args, with decimal precision specified by `decimals`'; 93 | passCount = range(1, SAMPLE_SIZE).reduce((acc) => { 94 | randVal = random([21, 1797], { decimals: PRECISION }); 95 | 96 | satisfied = 97 | randVal >= 21 && randVal <= 1797 && numDecimals(randVal) <= PRECISION; 98 | 99 | return satisfied ? acc + 1 : acc; 100 | }, 0); 101 | 102 | assert.ok(isPassing(passCount, SAMPLE_SIZE, TOLERANCE), message); 103 | }); 104 | 105 | test('bounding `decimals` between 0 and 20', function (assert) { 106 | randVal = random([42], { decimals: 100 }); 107 | 108 | satisfied = randVal > 0 && randVal < 42 && numDecimals(randVal) <= 20; 109 | 110 | assert.ok(satisfied); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/round-test.js: -------------------------------------------------------------------------------- 1 | import { round } from 'ember-math-helpers/helpers/round'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | round', function () { 5 | // Replace this with your real tests. 6 | test('it works', function (assert) { 7 | assert.strictEqual( 8 | round([20.49]), 9 | 20, 10 | 'It rounds values with a decimal place less than .5 down', 11 | ); 12 | 13 | assert.strictEqual( 14 | round([20.5]), 15 | 21, 16 | 'It rounds values with a decimal place greater than or equal to .5 up', 17 | ); 18 | 19 | assert.strictEqual( 20 | round([-20.5]), 21 | -20, 22 | 'It rounds negative numbers up appropriately', 23 | ); 24 | 25 | assert.strictEqual( 26 | round([-20.51]), 27 | -21, 28 | 'It rounds negative numbers down appropriately', 29 | ); 30 | 31 | assert.strictEqual( 32 | round([42]), 33 | 42, 34 | 'When given a whole number, the result stays the same', 35 | ); 36 | 37 | assert.strictEqual( 38 | round([35.855], { decimals: 2 }), 39 | 35.86, 40 | 'It rounds to a given number of decimal places', 41 | ); 42 | 43 | assert.strictEqual( 44 | round([123456], { exp: 3 }), 45 | 123000, 46 | 'It rounds to a given power of ten', 47 | ); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/sign-test.js: -------------------------------------------------------------------------------- 1 | import { sign } from 'ember-math-helpers/helpers/sign'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | sign', function () { 5 | test('it works', function (assert) { 6 | assert.strictEqual(sign([-5]), -1, 'Negative returns -1'); 7 | 8 | assert.strictEqual(sign([5]), 1, 'Positive returns 1'); 9 | 10 | assert.strictEqual(String(sign(['foo'])), 'NaN', 'Invalid returns NaN'); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/sin-test.js: -------------------------------------------------------------------------------- 1 | import { sin } from 'ember-math-helpers/helpers/sin'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | sin', function () { 5 | test('sin works', function (assert) { 6 | const result = sin([0]); 7 | assert.strictEqual(result, 0); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/sqrt-test.js: -------------------------------------------------------------------------------- 1 | import { sqrt } from 'ember-math-helpers/helpers/sqrt'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | sqrt', function () { 5 | test('square root works', function (assert) { 6 | const result = sqrt([25]); 7 | assert.strictEqual(result, 5); 8 | }); 9 | 10 | test('negative square root is NaN', function (assert) { 11 | const result = sqrt([-10]); 12 | assert.ok(isNaN(result)); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/sub-test.js: -------------------------------------------------------------------------------- 1 | import { sub } from 'ember-math-helpers/helpers/sub'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | sub', function () { 5 | test('subtraction works', function (assert) { 6 | const result = sub([20, 10]); 7 | assert.strictEqual(result, 10); 8 | }); 9 | 10 | test('subtraction of multiple arguments works', function (assert) { 11 | const result = sub([5, 4, 2, -9]); 12 | assert.strictEqual(result, 8); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/sum-test.js: -------------------------------------------------------------------------------- 1 | import { sum } from 'ember-math-helpers/helpers/sum'; 2 | import { add } from 'ember-math-helpers/helpers/add'; 3 | import { module, test } from 'qunit'; 4 | 5 | module('Unit | Helper | sum', function () { 6 | test('works as alias to add', function (assert) { 7 | const input = [20, 10]; 8 | assert.strictEqual(sum(input), add(input)); 9 | }); 10 | 11 | test('works as alias to add for multiple arguments', function (assert) { 12 | const input = [1, 2, 3, 4, 5]; 13 | assert.strictEqual(sum(input), add(input)); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/tan-test.js: -------------------------------------------------------------------------------- 1 | import { tan } from 'ember-math-helpers/helpers/tan'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | tan', function () { 5 | test('tan works', function (assert) { 6 | const result = tan([1]); 7 | assert.strictEqual(Number(result.toFixed(3)), 1.557); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/tanh-test.js: -------------------------------------------------------------------------------- 1 | import { tanh } from 'ember-math-helpers/helpers/tanh'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | tanh', function () { 5 | test('tanh works', function (assert) { 6 | const result = tanh([1]); 7 | assert.strictEqual(Number(result.toFixed(3)), 0.762); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test-app/tests/unit/helpers/trunc-test.js: -------------------------------------------------------------------------------- 1 | import { trunc } from 'ember-math-helpers/helpers/trunc'; 2 | import { module, test } from 'qunit'; 3 | 4 | module('Unit | Helper | trunc', function () { 5 | test('trunc works', function (assert) { 6 | let result; 7 | result = trunc([13.37]); 8 | assert.strictEqual(result, 13); 9 | result = trunc([0.123]); 10 | assert.strictEqual(result, 0); 11 | result = trunc([-1.123]); 12 | assert.strictEqual(result, -1); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/ember/tsconfig.json", 3 | "glint": { 4 | "environment": ["ember-loose", "ember-template-imports"] 5 | }, 6 | "compilerOptions": { 7 | "skipLibCheck": true, 8 | "noEmit": true, 9 | "noEmitOnError": false, 10 | "declaration": false, 11 | "declarationMap": false, 12 | // The combination of `baseUrl` with `paths` allows Ember's classic package 13 | // layout, which is not resolvable with the Node resolution algorithm, to 14 | // work with TypeScript. 15 | "baseUrl": ".", 16 | "paths": { 17 | "test-app/tests/*": ["tests/*"], 18 | "test-app/*": ["app/*"], 19 | "*": ["types/*"] 20 | }, 21 | "types": ["ember-source/types"] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test-app/types/global.d.ts: -------------------------------------------------------------------------------- 1 | import '@glint/environment-ember-loose'; 2 | --------------------------------------------------------------------------------