diff --git a/.gitignore b/.gitignore index d00e043..d7efc7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules/ dist/ +coverage/ *.tgz *.log .DS_Store diff --git a/coverage/lcov-report/base.css b/coverage/lcov-report/base.css deleted file mode 100644 index f418035..0000000 --- a/coverage/lcov-report/base.css +++ /dev/null @@ -1,224 +0,0 @@ -body, html { - margin:0; padding: 0; - height: 100%; -} -body { - font-family: Helvetica Neue, Helvetica, Arial; - font-size: 14px; - color:#333; -} -.small { font-size: 12px; } -*, *:after, *:before { - -webkit-box-sizing:border-box; - -moz-box-sizing:border-box; - box-sizing:border-box; - } -h1 { font-size: 20px; margin: 0;} -h2 { font-size: 14px; } -pre { - font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; - margin: 0; - padding: 0; - -moz-tab-size: 2; - -o-tab-size: 2; - tab-size: 2; -} -a { color:#0074D9; text-decoration:none; } -a:hover { text-decoration:underline; } -.strong { font-weight: bold; } -.space-top1 { padding: 10px 0 0 0; } -.pad2y { padding: 20px 0; } -.pad1y { padding: 10px 0; } -.pad2x { padding: 0 20px; } -.pad2 { padding: 20px; } -.pad1 { padding: 10px; } -.space-left2 { padding-left:55px; } -.space-right2 { padding-right:20px; } -.center { text-align:center; } -.clearfix { display:block; } -.clearfix:after { - content:''; - display:block; - height:0; - clear:both; - visibility:hidden; - } -.fl { float: left; } -@media only screen and (max-width:640px) { - .col3 { width:100%; max-width:100%; } - .hide-mobile { display:none!important; } -} - -.quiet { - color: #7f7f7f; - color: rgba(0,0,0,0.5); -} -.quiet a { opacity: 0.7; } - -.fraction { - font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; - font-size: 10px; - color: #555; - background: #E8E8E8; - padding: 4px 5px; - border-radius: 3px; - vertical-align: middle; -} - -div.path a:link, div.path a:visited { color: #333; } -table.coverage { - border-collapse: collapse; - margin: 10px 0 0 0; - padding: 0; -} - -table.coverage td { - margin: 0; - padding: 0; - vertical-align: top; -} -table.coverage td.line-count { - text-align: right; - padding: 0 5px 0 20px; -} -table.coverage td.line-coverage { - text-align: right; - padding-right: 10px; - min-width:20px; -} - -table.coverage td span.cline-any { - display: inline-block; - padding: 0 5px; - width: 100%; -} -.missing-if-branch { - display: inline-block; - margin-right: 5px; - border-radius: 3px; - position: relative; - padding: 0 4px; - background: #333; - color: yellow; -} - -.skip-if-branch { - display: none; - margin-right: 10px; - position: relative; - padding: 0 4px; - background: #ccc; - color: white; -} -.missing-if-branch .typ, .skip-if-branch .typ { - color: inherit !important; -} -.coverage-summary { - border-collapse: collapse; - width: 100%; -} -.coverage-summary tr { border-bottom: 1px solid #bbb; } -.keyline-all { border: 1px solid #ddd; } -.coverage-summary td, .coverage-summary th { padding: 10px; } -.coverage-summary tbody { border: 1px solid #bbb; } -.coverage-summary td { border-right: 1px solid #bbb; } -.coverage-summary td:last-child { border-right: none; } -.coverage-summary th { - text-align: left; - font-weight: normal; - white-space: nowrap; -} -.coverage-summary th.file { border-right: none !important; } -.coverage-summary th.pct { } -.coverage-summary th.pic, -.coverage-summary th.abs, -.coverage-summary td.pct, -.coverage-summary td.abs { text-align: right; } -.coverage-summary td.file { white-space: nowrap; } -.coverage-summary td.pic { min-width: 120px !important; } -.coverage-summary tfoot td { } - -.coverage-summary .sorter { - height: 10px; - width: 7px; - display: inline-block; - margin-left: 0.5em; - background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; -} -.coverage-summary .sorted .sorter { - background-position: 0 -20px; -} -.coverage-summary .sorted-desc .sorter { - background-position: 0 -10px; -} -.status-line { height: 10px; } -/* yellow */ -.cbranch-no { background: yellow !important; color: #111; } -/* dark red */ -.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } -.low .chart { border:1px solid #C21F39 } -.highlighted, -.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ - background: #C21F39 !important; -} -/* medium red */ -.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } -/* light red */ -.low, .cline-no { background:#FCE1E5 } -/* light green */ -.high, .cline-yes { background:rgb(230,245,208) } -/* medium green */ -.cstat-yes { background:rgb(161,215,106) } -/* dark green */ -.status-line.high, .high .cover-fill { background:rgb(77,146,33) } -.high .chart { border:1px solid rgb(77,146,33) } -/* dark yellow (gold) */ -.status-line.medium, .medium .cover-fill { background: #f9cd0b; } -.medium .chart { border:1px solid #f9cd0b; } -/* light yellow */ -.medium { background: #fff4c2; } - -.cstat-skip { background: #ddd; color: #111; } -.fstat-skip { background: #ddd; color: #111 !important; } -.cbranch-skip { background: #ddd !important; color: #111; } - -span.cline-neutral { background: #eaeaea; } - -.coverage-summary td.empty { - opacity: .5; - padding-top: 4px; - padding-bottom: 4px; - line-height: 1; - color: #888; -} - -.cover-fill, .cover-empty { - display:inline-block; - height: 12px; -} -.chart { - line-height: 0; -} -.cover-empty { - background: white; -} -.cover-full { - border-right: none !important; -} -pre.prettyprint { - border: none !important; - padding: 0 !important; - margin: 0 !important; -} -.com { color: #999 !important; } -.ignore-none { color: #999; font-weight: normal; } - -.wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -48px; -} -.footer, .push { - height: 48px; -} diff --git a/coverage/lcov-report/block-navigation.js b/coverage/lcov-report/block-navigation.js deleted file mode 100644 index 530d1ed..0000000 --- a/coverage/lcov-report/block-navigation.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-disable */ -var jumpToCode = (function init() { - // Classes of code we would like to highlight in the file view - var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; - - // Elements to highlight in the file listing view - var fileListingElements = ['td.pct.low']; - - // We don't want to select elements that are direct descendants of another match - var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` - - // Selector that finds elements on the page to which we can jump - var selector = - fileListingElements.join(', ') + - ', ' + - notSelector + - missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` - - // The NodeList of matching elements - var missingCoverageElements = document.querySelectorAll(selector); - - var currentIndex; - - function toggleClass(index) { - missingCoverageElements - .item(currentIndex) - .classList.remove('highlighted'); - missingCoverageElements.item(index).classList.add('highlighted'); - } - - function makeCurrent(index) { - toggleClass(index); - currentIndex = index; - missingCoverageElements.item(index).scrollIntoView({ - behavior: 'smooth', - block: 'center', - inline: 'center' - }); - } - - function goToPrevious() { - var nextIndex = 0; - if (typeof currentIndex !== 'number' || currentIndex === 0) { - nextIndex = missingCoverageElements.length - 1; - } else if (missingCoverageElements.length > 1) { - nextIndex = currentIndex - 1; - } - - makeCurrent(nextIndex); - } - - function goToNext() { - var nextIndex = 0; - - if ( - typeof currentIndex === 'number' && - currentIndex < missingCoverageElements.length - 1 - ) { - nextIndex = currentIndex + 1; - } - - makeCurrent(nextIndex); - } - - return function jump(event) { - if ( - document.getElementById('fileSearch') === document.activeElement && - document.activeElement != null - ) { - // if we're currently focused on the search input, we don't want to navigate - return; - } - - switch (event.which) { - case 78: // n - case 74: // j - goToNext(); - break; - case 66: // b - case 75: // k - case 80: // p - goToPrevious(); - break; - } - }; -})(); -window.addEventListener('keydown', jumpToCode); diff --git a/coverage/lcov-report/favicon.png b/coverage/lcov-report/favicon.png deleted file mode 100644 index c1525b8..0000000 Binary files a/coverage/lcov-report/favicon.png and /dev/null differ diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html deleted file mode 100644 index 115ecb5..0000000 --- a/coverage/lcov-report/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - -
-- Press n or j to go to the next uncovered block, b, p or k for the previous block. -
- -- Press n or j to go to the next uncovered block, b, p or k for the previous block. -
- -| 1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 | 1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -15x -2x -2x -15x -2x -2x -11x -11x -11x -11x -11x -11x -11x -11x -11x -11x -1x -1x -1x -1x -1x -1x -1x -1x -10x -10x -10x -10x -1x -1x -1x -1x -1x -1x -1x -1x -9x -9x -9x -9x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -9x -9x -9x -9x -9x -1x -1x -9x -1x -1x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -9x -6x -6x -9x -556x -556x -556x -556x -556x -556x -556x -556x -556x -556x -556x -6x -6x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -8x -8x -8x -8x -8x -8x -8x -8x -8x -8x -8x -8x - | /**
- * Qibla direction utilities. Pure math, zero external dependencies.
- *
- * Computes the initial bearing (forward azimuth) from any point on Earth to
- * the Ka'bah using the spherical law of cosines. Includes compass direction
- * lookup, great-circle interpolation, and haversine distance.
- *
- * Ka'bah coordinates sourced from verified GPS data.
- *
- * @module
- */
-
-export * from "./types.js";
-
-import {
- KAABA_LAT,
- KAABA_LNG,
- EARTH_RADIUS_KM,
- COMPASS_ABBR,
- COMPASS_NAMES,
- type CompassAbbr,
- type CompassName,
-} from "./types.js";
-
-const DEG = Math.PI / 180;
-
-/**
- * Qibla bearing in degrees clockwise from true north.
- *
- * Uses the forward azimuth formula from spherical trigonometry.
- * Result range: [0, 360).
- *
- * @param lat - Observer latitude in decimal degrees (-90 to 90).
- * @param lng - Observer longitude in decimal degrees (-180 to 180).
- * @returns Bearing in degrees clockwise from north (0 = N, 90 = E, 180 = S, 270 = W).
- * @throws {RangeError} If latitude is outside [-90, 90] or longitude outside [-180, 180].
- */
-export function qiblaAngle(lat: number, lng: number): number {
- if (lat < -90 || lat > 90) {
- throw new RangeError(`Latitude must be between -90 and 90, got ${lat}`);
- }
- if (lng < -180 || lng > 180) {
- throw new RangeError(`Longitude must be between -180 and 180, got ${lng}`);
- }
- const φ1 = lat * DEG,
- λ1 = lng * DEG;
- const φ2 = KAABA_LAT * DEG,
- λ2 = KAABA_LNG * DEG;
- const y = Math.sin(λ2 - λ1) * Math.cos(φ2);
- const x =
- Math.cos(φ1) * Math.sin(φ2) -
- Math.sin(φ1) * Math.cos(φ2) * Math.cos(λ2 - λ1);
- return (Math.atan2(y, x) / DEG + 360) % 360;
-}
-
-/**
- * Eight-point compass abbreviation for a bearing.
- *
- * @param bearing - Bearing in degrees (0-360).
- * @returns Two-letter compass abbreviation (N, NE, E, SE, S, SW, W, NW).
- */
-export function compassDir(bearing: number): CompassAbbr {
- // Non-null assertion: index is always 0-7 (Math.round(bearing/45) % 8), which is within COMPASS_ABBR bounds.
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return COMPASS_ABBR[Math.round(bearing / 45) % 8]!;
-}
-
-/**
- * Full compass direction name for a bearing.
- *
- * @param bearing - Bearing in degrees (0-360).
- * @returns Full direction name (North, Northeast, etc.).
- */
-export function compassName(bearing: number): CompassName {
- // Non-null assertion: index is always 0-7 (Math.round(bearing/45) % 8), which is within COMPASS_NAMES bounds.
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return COMPASS_NAMES[Math.round(bearing / 45) % 8]!;
-}
-
-/**
- * Great-circle waypoints from [lat, lng] to the Ka'bah.
- *
- * Uses the Slerp (spherical linear interpolation) formula. Useful for
- * drawing Qibla direction lines on maps.
- *
- * @param lat - Origin latitude in decimal degrees.
- * @param lng - Origin longitude in decimal degrees.
- * @param steps - Number of segments (default: 120, producing 121 points).
- * @returns Array of [latitude, longitude] pairs in degrees.
- * @throws {RangeError} If latitude is outside [-90, 90] or longitude outside [-180, 180].
- */
-export function qiblaGreatCircle(
- lat: number,
- lng: number,
- steps = 120,
-): [number, number][] {
- if (lat < -90 || lat > 90) {
- throw new RangeError(`Latitude must be between -90 and 90, got ${lat}`);
- }
- if (lng < -180 || lng > 180) {
- throw new RangeError(`Longitude must be between -180 and 180, got ${lng}`);
- }
- const φ1 = lat * DEG,
- λ1 = lng * DEG;
- const φ2 = KAABA_LAT * DEG,
- λ2 = KAABA_LNG * DEG;
-
- const d =
- 2 *
- Math.asin(
- Math.sqrt(
- Math.sin((φ2 - φ1) / 2) ** 2 +
- Math.cos(φ1) * Math.cos(φ2) * Math.sin((λ2 - λ1) / 2) ** 2,
- ),
- );
-
- if (d === 0) return [[lat, lng]];
-
- const points: [number, number][] = [];
- for (let i = 0; i <= steps; i++) {
- const f = i / steps;
- const A = Math.sin((1 - f) * d) / Math.sin(d);
- const B = Math.sin(f * d) / Math.sin(d);
- const x = A * Math.cos(φ1) * Math.cos(λ1) + B * Math.cos(φ2) * Math.cos(λ2);
- const y = A * Math.cos(φ1) * Math.sin(λ1) + B * Math.cos(φ2) * Math.sin(λ2);
- const z = A * Math.sin(φ1) + B * Math.sin(φ2);
- points.push([
- Math.atan2(z, Math.sqrt(x * x + y * y)) / DEG,
- Math.atan2(y, x) / DEG,
- ]);
- }
- return points;
-}
-
-/**
- * Haversine distance between two coordinate pairs.
- *
- * @param lat1 - First point latitude in decimal degrees.
- * @param lng1 - First point longitude in decimal degrees.
- * @param lat2 - Second point latitude in decimal degrees.
- * @param lng2 - Second point longitude in decimal degrees.
- * @returns Distance in kilometers (spherical Earth approximation).
- */
-export function distanceKm(
- lat1: number,
- lng1: number,
- lat2: number,
- lng2: number,
-): number {
- const dLat = (lat2 - lat1) * DEG;
- const dLng = (lng2 - lng1) * DEG;
- const a =
- Math.sin(dLat / 2) ** 2 +
- Math.cos(lat1 * DEG) * Math.cos(lat2 * DEG) * Math.sin(dLng / 2) ** 2;
- return EARTH_RADIUS_KM * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
-}
- |