[READ-ONLY] Mirror of https://github.com/probablykasper/starchart. GitHub star history graph starchart.kasper.space
chart github github-api github-star graph history star star-history stargazers stars
0

Configure Feed

Select the types of activity you want to include in your feed.

Format

Kasper (Mar 10, 2025, 1:38 AM +0100) c3c3041b 9bee2916

+260 -250
+1 -1
src/app.html
··· 1 - <!DOCTYPE html> 1 + <!doctype html> 2 2 <html lang="en"> 3 3 <head> 4 4 <meta charset="utf-8" />
+23 -21
src/routes/+page.svelte
··· 1 1 <script lang="ts"> 2 2 import { fly, slide } from 'svelte/transition' 3 - import { fetchStargazersPage } from './github' 3 + import { fetch_stargazers_page } from './github' 4 4 import { onMount } from 'svelte' 5 5 import '../app.sass' 6 6 import Nav from './Nav.svelte' 7 7 import ChartComponent from './Chart.svelte' 8 - import { getNextColorIndex, newChart, type Chart } from './chart' 8 + import { get_next_color_index, new_chart, type Chart } from './chart' 9 9 import type { UTCTimestamp } from 'lightweight-charts' 10 10 import Tooltip from './Tooltip.svelte' 11 11 ··· 13 13 14 14 let chart: Chart | undefined 15 15 16 - async function getStargazers(owner: string, repo: string) { 16 + async function get_stargazers(owner: string, repo: string) { 17 17 if (!chart || !$chart) { 18 - addError('Chart not initialized') 18 + add_error('Chart not initialized') 19 19 return 20 20 } 21 21 for (const line of $chart.lines) { ··· 24 24 } 25 25 } 26 26 let count = 0 27 - let endCursor: string | undefined 27 + let end_cursor: string | undefined 28 28 const line = chart.addLine({ 29 29 name: `${owner}/${repo}`, 30 - color: getNextColorIndex(), 30 + color: get_next_color_index(), 31 31 data: [], 32 32 }) 33 - let totalCount = 0 33 + let total_count = 0 34 34 do { 35 35 if (line.deleted) { 36 36 return // abort 37 37 } 38 - const { error, stargazers } = await fetchStargazersPage(owner, repo, 'forward', endCursor) 38 + const { error, stargazers } = await fetch_stargazers_page(owner, repo, 'forward', end_cursor) 39 39 if (!stargazers) { 40 - addError(error) 40 + add_error(error) 41 41 chart.deleteLine(line) 42 42 return 43 43 } 44 44 45 45 if (stargazers.pageInfo.hasNextPage) { 46 - endCursor = stargazers.pageInfo.endCursor 46 + end_cursor = stargazers.pageInfo.endCursor 47 47 } else { 48 - endCursor = undefined 48 + end_cursor = undefined 49 49 } 50 - totalCount = stargazers.totalCount 50 + total_count = stargazers.totalCount 51 51 52 - const newData = stargazers.starTimes.map((starTime) => { 52 + const new_data = stargazers.starTimes.map((star_time) => { 53 53 count++ 54 54 return { 55 - t: Math.floor(new Date(starTime).getTime() / 1000) as UTCTimestamp, 55 + t: Math.floor(new Date(star_time).getTime() / 1000) as UTCTimestamp, 56 56 v: count, 57 57 } 58 58 }) 59 - chart.appendStargazers(line, newData) 60 - } while (endCursor) 59 + chart.appendStargazers(line, new_data) 60 + } while (end_cursor) 61 61 chart.addFinal(line, { 62 62 t: Math.floor(new Date().getTime() / 1000) as UTCTimestamp, 63 - v: totalCount, 63 + v: total_count, 64 64 }) 65 65 chart.save() 66 66 } 67 67 68 68 let errors: { id: number; msg: string }[] = [] 69 - function addError(msg: string) { 69 + function add_error(msg: string) { 70 70 const id = Math.random() 71 71 errors.push({ id, msg }) 72 72 errors = errors ··· 81 81 82 82 let container: HTMLDivElement 83 83 onMount(() => { 84 - chart = newChart(container, { width, height }) 84 + chart = new_chart(container, { width, height }) 85 85 }) 86 86 $: $chart?.instance.applyOptions({ 87 87 width, ··· 89 89 }) 90 90 </script> 91 91 92 - <Nav bind:owner bind:repo onSubmit={() => getStargazers(owner, repo)} /> 92 + <Nav bind:owner bind:repo on_submit={() => get_stargazers(owner, repo)} /> 93 93 94 94 {#each errors as error, i (error.id)} 95 95 <div class="error-container" transition:slide={{ duration: 200 }}> 96 96 <div class="error" transition:fly={{ duration: 200, opacity: 0, y: -40 }}> 97 97 {error.msg} 98 98 <button 99 + type="button" 100 + aria-label="Dismiss error" 99 101 on:click={() => { 100 102 errors.splice(i, 1) 101 103 errors = errors ··· 124 126 <ChartComponent bind:chart /> 125 127 {/if} 126 128 <div class="chart" bind:clientWidth={width}> 127 - <div bind:this={container} class:hidden={!$chart || $chart.lines.length === 0} /> 129 + <div bind:this={container} class:hidden={!$chart || $chart.lines.length === 0}></div> 128 130 {#if chart && $chart && $chart.lines.length > 0} 129 131 <Tooltip {chart} /> 130 132 {/if}
+12 -10
src/routes/AccessToken.svelte
··· 3 3 import { token } from './github' 4 4 import Modal from 'modal-svelte' 5 5 6 - let tokenInput = $token 7 - let editToken = false 6 + let token_intup = $token 7 + let edit_token = false 8 8 9 9 function save() { 10 10 token.set($token) 11 - editToken = false 12 - $token = tokenInput 11 + edit_token = false 12 + $token = token_intup 13 13 } 14 14 </script> 15 15 16 16 {#if browser} 17 17 <button 18 + type="button" 18 19 class="bordered button rounded" 19 20 class:yellow={!$token} 20 - on:click={() => (editToken = true)} 21 + on:click={() => (edit_token = true)} 21 22 > 22 23 {$token ? 'Auth token' : 'Set auth token'} 23 24 </button> 24 25 {/if} 25 - {#if editToken} 26 - <Modal title="Access token" onCancel={() => (editToken = false)} form={save} let:focus> 26 + {#if edit_token} 27 + <Modal title="Access token" onCancel={() => (edit_token = false)} form={save}> 27 28 <p> 28 29 You'll want a GitHub access token to avoid rate limiting. 29 30 <a href="https://github.com/settings/tokens/new?description=Starchart" 30 31 >Generate your access token</a 31 32 > 32 33 </p> 34 + <!-- svelte-ignore a11y_autofocus --> 33 35 <input 34 36 type="text" 35 37 class="bordered rounded" 36 - bind:value={tokenInput} 38 + bind:value={token_intup} 37 39 placeholder="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" 38 - use:focus 40 + autofocus 39 41 /> 40 42 <div slot="buttons"> 41 - <button class="save bordered button rounded highlight">Save</button> 43 + <button type="submit" class="save bordered button rounded highlight">Save</button> 42 44 </div> 43 45 </Modal> 44 46 {/if}
+1 -1
src/routes/Chart.svelte
··· 53 53 {#each $chart.lines as line (line.name)} 54 54 <Label 55 55 {line} 56 - onDelete={() => { 56 + on_delete={() => { 57 57 chart.deleteLine(line) 58 58 chart.save() 59 59 }}
+6 -6
src/routes/Label.svelte
··· 2 2 import { cubicOut } from 'svelte/easing' 3 3 import { fade, scale } from 'svelte/transition' 4 4 import type { Line } from './chart' 5 - import { hexColors } from './color' 5 + import { hex_colors } from './color' 6 6 7 7 export let line: Line 8 - $: hex = hexColors[line.color] 9 - export let onDelete: () => void 8 + $: hex = hex_colors[line.color] 9 + export let on_delete: () => void 10 10 </script> 11 11 12 12 <span ··· 22 22 line.instance.applyOptions({ visible: !line.hidden }) 23 23 e.preventDefault() 24 24 } else if (e.key === 'Backspace' || e.key === 'Delete') { 25 - onDelete() 25 + on_delete() 26 26 e.preventDefault() 27 27 } 28 28 }} ··· 39 39 > 40 40 {line.name} 41 41 </button> 42 - <button type="button" class="x" class:loading={!line.final} on:click={onDelete} tabindex="-1"> 42 + <button type="button" class="x" class:loading={!line.final} on:click={on_delete} tabindex="-1"> 43 43 <svg 44 44 fill="currentColor" 45 45 width="18" ··· 56 56 > 57 57 {#if !line.final} 58 58 <div class="spinner" transition:fade={{ duration: 150 }}> 59 - <div class="circle" /> 59 + <div class="circle"></div> 60 60 </div> 61 61 {/if} 62 62 </button>
+4 -4
src/routes/Nav.svelte
··· 4 4 5 5 export let owner: string 6 6 export let repo: string 7 - export let onSubmit: () => void 7 + export let on_submit: () => void 8 8 </script> 9 9 10 10 <nav> ··· 12 12 <h1>Starchart</h1> 13 13 </span> 14 14 <div class="repo-input first"> 15 - <RepoInput bind:owner bind:repo {onSubmit} /> 15 + <RepoInput bind:owner bind:repo {on_submit} /> 16 16 </div> 17 17 <div class="menu"> 18 18 <AccessToken /> 19 - <a href="https://github.com/probablykasper/starchart"> 19 + <a href="https://github.com/probablykasper/starchart" aria-label="GitHub repository"> 20 20 <svg 21 21 height="24" 22 22 viewBox="-2 -2 28 28" ··· 36 36 </a> 37 37 </div> 38 38 <div class="repo-input second"> 39 - <RepoInput bind:owner bind:repo {onSubmit} /> 39 + <RepoInput bind:owner bind:repo {on_submit} /> 40 40 </div> 41 41 </nav> 42 42
+21 -21
src/routes/RepoInput.svelte
··· 1 1 <script lang="ts"> 2 - import { checkShortcut } from './shortcuts' 2 + import { check_shortcut } from './shortcuts' 3 3 4 4 export let owner: string 5 5 export let repo: string 6 - export let onSubmit: () => void 7 - let repoElement: HTMLInputElement 6 + export let on_submit: () => void 7 + let repo_element: HTMLInputElement 8 8 9 - $: owner, parseOwnerField() 10 - async function parseOwnerField() { 9 + $: owner, parse_owner_field() 10 + async function parse_owner_field() { 11 11 owner = owner.replace(/^https?:\/\//, '').replace('github.com/', '') 12 - const slashIndex = owner.indexOf('/') 13 - if (slashIndex >= 0) { 14 - const newOwner = owner.slice(0, slashIndex) 15 - const newRepo = owner.slice(slashIndex + 1) 16 - owner = newOwner 17 - if (newRepo !== '') { 18 - repo = newRepo 19 - repoElement.focus() 12 + const slash_index = owner.indexOf('/') 13 + if (slash_index >= 0) { 14 + const new_owner = owner.slice(0, slash_index) 15 + const new_repo = owner.slice(slash_index + 1) 16 + owner = new_owner 17 + if (new_repo !== '') { 18 + repo = new_repo 19 + repo_element.focus() 20 20 } else { 21 - repoElement.select() 21 + repo_element.select() 22 22 } 23 23 } 24 24 } 25 25 26 - function inputKeydown(e: KeyboardEvent) { 27 - if (checkShortcut(e, 'Enter')) { 28 - onSubmit() 26 + function input_keydown(e: KeyboardEvent) { 27 + if (check_shortcut(e, 'Enter')) { 28 + on_submit() 29 29 } 30 30 } 31 31 </script> ··· 37 37 type="text" 38 38 bind:value={owner} 39 39 placeholder="probablykasper" 40 - on:keydown={inputKeydown} 40 + on:keydown={input_keydown} 41 41 /> 42 42 <div><span class="bordered slash">/</span></div> 43 43 <input 44 44 class="bordered repo" 45 45 type="text" 46 - bind:this={repoElement} 46 + bind:this={repo_element} 47 47 bind:value={repo} 48 48 placeholder="cpc" 49 - on:keydown={inputKeydown} 49 + on:keydown={input_keydown} 50 50 /> 51 51 </div> 52 - <button class="bordered button" on:click={() => onSubmit()}>Load</button> 52 + <button type="button" class="bordered button" on:click={() => on_submit()}>Load</button> 53 53 </div> 54 54 55 55 <style lang="sass">
+35 -32
src/routes/Tooltip.svelte
··· 2 2 import type { BusinessDay, MouseEventParams, UTCTimestamp } from 'lightweight-charts' 3 3 import { onDestroy } from 'svelte' 4 4 import type { Chart, DataPoint, Line } from './chart' 5 - import { brightColors } from './color' 5 + import { bright_colors } from './color' 6 6 7 7 export let chart: Chart 8 8 ··· 13 13 let left: number 14 14 let top: number 15 15 16 - $: starScale = $chart.instance.priceScale('right') 17 - $: timeScale = $chart.instance.timeScale() 16 + $: star_scale = $chart.instance.priceScale('right') 17 + $: time_scale = $chart.instance.timeScale() 18 18 19 - function onTouchMove() { 19 + function on_touch_move() { 20 20 left = 10 21 21 top = 10 22 22 } 23 - function onMouseMove(e: { clientX: number; clientY: number }) { 23 + function on_mouse_move(e: { clientX: number; clientY: number }) { 24 24 const bounds = $chart.container.getBoundingClientRect() 25 25 const x = e.clientX - bounds.left 26 26 const y = e.clientY - bounds.top 27 27 left = x + margin 28 - if (left > $chart.container.clientWidth - width - starScale.width()) { 28 + if (left > $chart.container.clientWidth - width - star_scale.width()) { 29 29 left = x - width - margin 30 30 } 31 31 32 32 top = y + margin 33 - if (top > $chart.container.clientHeight - height - timeScale.height()) { 33 + if (top > $chart.container.clientHeight - height - time_scale.height()) { 34 34 top = y - height - margin 35 35 } 36 36 } 37 - $chart.container.addEventListener('mousemove', onMouseMove) 38 - $chart.container.addEventListener('touchmove', onTouchMove) 37 + $chart.container.addEventListener('mousemove', on_mouse_move) 38 + $chart.container.addEventListener('touchmove', on_touch_move) 39 39 onDestroy(() => { 40 - $chart.container.removeEventListener('mousemove', onMouseMove) 41 - $chart.container.removeEventListener('touchmove', onTouchMove) 40 + $chart.container.removeEventListener('mousemove', on_mouse_move) 41 + $chart.container.removeEventListener('touchmove', on_touch_move) 42 42 }) 43 43 44 44 /** Binary search */ 45 - function findLatestDataPoint(arr: DataPoint[], max: UTCTimestamp) { 45 + function find_latest_data_point(arr: DataPoint[], max: UTCTimestamp) { 46 46 let start = 0 47 47 let end = arr.length - 1 48 48 let result: DataPoint | null = null ··· 60 60 return result 61 61 } 62 62 63 - function updateTooltipOnMouseEvent(param: MouseEventParams) { 63 + function update_tooltip_on_mouse_event(param: MouseEventParams) { 64 64 values = [] 65 65 if ( 66 66 param.point === undefined || ··· 80 80 const time = param.time as BusinessDay 81 81 82 82 for (const line of $chart.lines) { 83 - const maxDate = new Date(time.year, time.month - 1, time.day, 23, 59, 59, 999) 84 - const maxTimestamp = (maxDate.getTime() / 1000) as UTCTimestamp 85 - const dataPoint = findLatestDataPoint(line.data, maxTimestamp) 83 + const max_date = new Date(time.year, time.month - 1, time.day, 23, 59, 59, 999) 84 + const max_timestamp = (max_date.getTime() / 1000) as UTCTimestamp 85 + const data_point = find_latest_data_point(line.data, max_timestamp) 86 86 87 - if (dataPoint) { 87 + if (data_point) { 88 88 values.push({ 89 89 line: line, 90 - value: dataPoint.v, 90 + value: data_point.v, 91 91 }) 92 92 } 93 93 } 94 94 values.sort((a, b) => b.value - a.value) 95 95 values = values 96 96 } 97 - $chart.instance.subscribeCrosshairMove(updateTooltipOnMouseEvent) 97 + $chart.instance.subscribeCrosshairMove(update_tooltip_on_mouse_event) 98 98 onDestroy(() => { 99 - $chart.instance.unsubscribeCrosshairMove(updateTooltipOnMouseEvent) 99 + $chart.instance.unsubscribeCrosshairMove(update_tooltip_on_mouse_event) 100 100 }) 101 101 </script> 102 102 ··· 109 109 bind:clientHeight={height} 110 110 > 111 111 <table> 112 - {#each values as tooltipValue} 113 - {#if !tooltipValue.line.hidden} 114 - <tr> 115 - <td class="name" style:color={brightColors[tooltipValue.line.color]} 116 - >{tooltipValue.line.name}</td 117 - > 118 - <td class="value"> 119 - {tooltipValue.value} 120 - </td> 121 - </tr> 122 - {/if} 123 - {/each} 112 + <tbody> 113 + <!-- svelte-ignore svelte/require-each-key --> 114 + {#each values as tooltip_value} 115 + {#if !tooltip_value.line.hidden} 116 + <tr> 117 + <td class="name" style:color={bright_colors[tooltip_value.line.color]} 118 + >{tooltip_value.line.name}</td 119 + > 120 + <td class="value"> 121 + {tooltip_value.value} 122 + </td> 123 + </tr> 124 + {/if} 125 + {/each} 126 + </tbody> 124 127 </table> 125 128 </div> 126 129
+132 -129
src/routes/chart.ts
··· 1 1 import { 2 - createChart as createChartInstance, 2 + createChart as create_chart_instance, 3 3 PriceScaleMode, 4 4 TickMarkType, 5 5 type BusinessDay, ··· 11 11 type UTCTimestamp, 12 12 } from 'lightweight-charts' 13 13 import { writable } from 'svelte/store' 14 - import { bottomColors, hexColors, topColors } from './color' 14 + import { bottom_colors, hex_colors, top_colors } from './color' 15 15 16 16 export type DataPoint = { t: UTCTimestamp; v: number } 17 17 type LineBase = { ··· 38 38 } 39 39 40 40 /** Used to invalidate old localStorage */ 41 - const jsonTypeVersion = 3 41 + const json_type_version = 3 42 42 type Json = { 43 43 lines: LineJson[] 44 44 align: boolean ··· 47 47 expiry: number 48 48 } 49 49 50 - let nextColorIndex = 0 51 - export function getNextColorIndex() { 52 - const value = nextColorIndex 53 - nextColorIndex = (nextColorIndex + 1) % hexColors.length 50 + let next_color_index = 0 51 + export function get_next_color_index() { 52 + const value = next_color_index 53 + next_color_index = (next_color_index + 1) % hex_colors.length 54 54 return value 55 55 } 56 56 57 - function loadJson() { 57 + function load_json() { 58 58 try { 59 - const seriesLocalStorage = JSON.parse(localStorage.getItem('starchart-series') || '{}') 60 - if (seriesLocalStorage?.v === jsonTypeVersion && seriesLocalStorage?.expiry > Date.now()) { 61 - const json = seriesLocalStorage as Json 62 - const lineBases = json.lines.map( 59 + const series_local_storage = JSON.parse(localStorage.getItem('starchart-series') || '{}') 60 + if ( 61 + series_local_storage?.v === json_type_version && 62 + series_local_storage?.expiry > Date.now() 63 + ) { 64 + const json = series_local_storage as Json 65 + const line_bases = json.lines.map( 63 66 (line): LineBase => ({ 64 67 color: line.color, 65 - data: line.data.map((utcTimestamp, i): DataPoint => { 68 + data: line.data.map((utc_timestamp, i): DataPoint => { 66 69 return { 67 - t: utcTimestamp, 70 + t: utc_timestamp, 68 71 v: i + 1, 69 72 } 70 73 }), 71 74 final: line.final, 72 75 name: line.name, 73 - }) 76 + }), 74 77 ) 75 78 return { 76 - lines: lineBases, 79 + lines: line_bases, 77 80 align: json.align, 78 81 logScale: json.logScale, 79 82 } ··· 97 100 logScale: boolean 98 101 container: HTMLElement 99 102 } 100 - export type Chart = ReturnType<typeof newChart> 103 + export type Chart = ReturnType<typeof new_chart> 101 104 102 105 const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 103 106 104 - export function newChart(container: HTMLElement, options: DeepPartial<ChartOptions>) { 107 + export function new_chart(container: HTMLElement, options: DeepPartial<ChartOptions>) { 105 108 const chart: ChartData = { 106 - instance: createChartInstance(container, options), 109 + instance: create_chart_instance(container, options), 107 110 container, 108 111 align: false, 109 112 logScale: false, ··· 111 114 } 112 115 const { subscribe, set } = writable(chart) 113 116 114 - const json = loadJson() 117 + const json = load_json() 115 118 chart.align = json.align 116 119 117 - function setDefaultFormatting() { 120 + function set_default_formatting() { 118 121 chart.instance.applyOptions({ 119 122 localization: { 120 123 timeFormatter: (time: BusinessDay) => { ··· 127 130 }, 128 131 }) 129 132 } 130 - setDefaultFormatting() 133 + set_default_formatting() 131 134 132 - function setAlignedFormatting() { 133 - const startDate = new Date(2001, 0) 135 + function set_aligned_formatting() { 136 + const start_date = new Date(2001, 0) 134 137 const day = 1000 * 3600 * 24 135 - const startDay = Math.ceil(startDate.getTime() / day) 138 + const start_day = Math.ceil(start_date.getTime() / day) 136 139 chart.instance.applyOptions({ 137 140 localization: { 138 141 timeFormatter: (time: BusinessDay) => { 139 142 const date = new Date(time.year, time.month - 1, time.day) 140 - return Math.ceil(date.getTime() / day) - startDay + ' days' 143 + return Math.ceil(date.getTime() / day) - start_day + ' days' 141 144 }, 142 145 }, 143 146 timeScale: { 144 - tickMarkFormatter: (time: BusinessDay, tickMarkType: TickMarkType) => { 147 + tickMarkFormatter: (time: BusinessDay, tick_mark_type: TickMarkType) => { 145 148 const date = new Date(time.year, time.month - 1, time.day) 146 - if (tickMarkType === TickMarkType.DayOfMonth) { 147 - return Math.ceil(date.getTime() / day) - startDay + 'd' 149 + if (tick_mark_type === TickMarkType.DayOfMonth) { 150 + return Math.ceil(date.getTime() / day) - start_day + 'd' 148 151 } 149 - const years = date.getFullYear() - startDate.getFullYear() 150 - if (tickMarkType === TickMarkType.Month) { 151 - return date.getMonth() - startDate.getMonth() + 12 * years + 'm' 152 - } else if (tickMarkType === TickMarkType.Year) { 152 + const years = date.getFullYear() - start_date.getFullYear() 153 + if (tick_mark_type === TickMarkType.Month) { 154 + return date.getMonth() - start_date.getMonth() + 12 * years + 'm' 155 + } else if (tick_mark_type === TickMarkType.Year) { 153 156 switch (years) { 154 157 case 0: 155 158 return '0d' ··· 166 169 }) 167 170 } 168 171 if (chart.align) { 169 - setAlignedFormatting() 172 + set_aligned_formatting() 170 173 } else { 171 - setDefaultFormatting() 174 + set_default_formatting() 172 175 } 173 176 174 - const fillerLine = chart.instance.addAreaSeries({ 177 + const filler_line = chart.instance.addAreaSeries({ 175 178 priceScaleId: '', 176 179 visible: false, 177 180 }) 178 181 179 - function updateFiller(data: Line[]) { 182 + function update_filler(data: Line[]) { 180 183 if (chart.align && data.length > 0) { 181 - fillerLine.setData([]) 184 + filler_line.setData([]) 182 185 } else { 183 - fillerLine.setData(getFiller(data, new Date())) 186 + filler_line.setData(get_filler(data, new Date())) 184 187 } 185 188 } 186 189 187 190 const store = { 188 191 subscribe, 189 192 190 - addLine(lineJson: LineBase) { 193 + addLine(line_json: LineBase) { 191 194 const series = chart.instance.addAreaSeries({ 192 195 priceLineVisible: false, 193 - topColor: topColors[lineJson.color], 194 - bottomColor: bottomColors[lineJson.color], 195 - lineColor: hexColors[lineJson.color], 196 + topColor: top_colors[line_json.color], 197 + bottomColor: bottom_colors[line_json.color], 198 + lineColor: hex_colors[line_json.color], 196 199 priceFormat: { 197 200 type: 'custom', 198 201 formatter: (price: number) => { ··· 202 205 }) 203 206 204 207 const line: Line = { 205 - ...lineJson, 208 + ...line_json, 206 209 instance: series, 207 210 deleted: false, 208 211 } 209 - if (lineJson.data.length >= 1) { 210 - const start = lineJson.data[0] 211 - const end = lineJson.final ?? lineJson.data[lineJson.data.length - 1] 212 - let chartSeries = toChartSeries(lineJson.data, start, end) 212 + if (line_json.data.length >= 1) { 213 + const start = line_json.data[0] 214 + const end = line_json.final ?? line_json.data[line_json.data.length - 1] 215 + let chart_series = to_chart_series(line_json.data, start, end) 213 216 214 217 if (chart.align) { 215 - chartSeries = alignChartSeries(chartSeries) 218 + chart_series = align_chart_series(chart_series) 216 219 } 217 - line.lastChartSeriesDate = chartSeries[chartSeries.length - 1].time 218 - series.setData(chartSeries) 220 + line.lastChartSeriesDate = chart_series[chart_series.length - 1].time 221 + series.setData(chart_series) 219 222 } 220 223 chart.lines.push(line) 221 - updateFiller(chart.lines) 222 - if (lineJson.data.length >= 1) { 224 + update_filler(chart.lines) 225 + if (line_json.data.length >= 1) { 223 226 store.resetZoom() 224 227 } 225 228 set(chart) ··· 234 237 } 235 238 const start = line.data[0] 236 239 const end = line.data[line.data.length - 1] 237 - const chartSeries = toChartSeries(line.data, start, end) 238 - const alignedChartSeries = alignChartSeries(chartSeries) 239 - line.instance.setData(alignedChartSeries) 240 - line.lastChartSeriesDate = alignedChartSeries[alignedChartSeries.length - 1].time 240 + const chart_series = to_chart_series(line.data, start, end) 241 + const aligned_chart_series = align_chart_series(chart_series) 242 + line.instance.setData(aligned_chart_series) 243 + line.lastChartSeriesDate = aligned_chart_series[aligned_chart_series.length - 1].time 241 244 } 242 - setAlignedFormatting() 243 - updateFiller(chart.lines) 245 + set_aligned_formatting() 246 + update_filler(chart.lines) 244 247 this.resetZoom() 245 248 set(chart) 246 249 }, ··· 253 256 } 254 257 const start = line.data[0] 255 258 const end = line.data[line.data.length - 1] 256 - const chartSeries = toChartSeries(line.data, start, end) 257 - line.instance.setData(chartSeries) 258 - line.lastChartSeriesDate = chartSeries[chartSeries.length - 1].time 259 + const chart_series = to_chart_series(line.data, start, end) 260 + line.instance.setData(chart_series) 261 + line.lastChartSeriesDate = chart_series[chart_series.length - 1].time 259 262 } 260 - setDefaultFormatting() 263 + set_default_formatting() 261 264 this.resetZoom() 262 265 set(chart) 263 266 }, 264 267 265 - setLogScale(logScale: boolean) { 268 + setLogScale(log_scale: boolean) { 266 269 chart.instance.applyOptions({ 267 270 rightPriceScale: { 268 - mode: logScale ? PriceScaleMode.Logarithmic : PriceScaleMode.Normal, 271 + mode: log_scale ? PriceScaleMode.Logarithmic : PriceScaleMode.Normal, 269 272 }, 270 273 }) 271 - chart.logScale = logScale 274 + chart.logScale = log_scale 272 275 set(chart) 273 276 }, 274 277 ··· 285 288 } 286 289 const start = data[0] 287 290 const end = data[data.length - 1] 288 - const chartSeries = toChartSeries(data, start, end) 291 + const chart_series = to_chart_series(data, start, end) 289 292 const fresh = line.data.length === 0 290 293 if (fresh) { 291 - const alignedChartSeries = alignChartSeries(chartSeries) 292 - line.instance.setData(alignedChartSeries) 293 - line.lastChartSeriesDate = alignedChartSeries[alignedChartSeries.length - 1].time 294 + const aigned_chart_series = align_chart_series(chart_series) 295 + line.instance.setData(aigned_chart_series) 296 + line.lastChartSeriesDate = aigned_chart_series[aigned_chart_series.length - 1].time 294 297 } else { 295 - const startDay = line.lastChartSeriesDate 296 - if (!startDay) { 298 + const start_day = line.lastChartSeriesDate 299 + if (!start_day) { 297 300 throw new Error('no lastChartSeriesDate') 298 301 } 299 - const startDate = new Date(startDay.year, startDay.month - 1, startDay.day) 300 - const alignedChartSeries = alignChartSeries(chartSeries, startDate) 301 - line.lastChartSeriesDate = alignedChartSeries[alignedChartSeries.length - 1].time 302 + const start_date = new Date(start_day.year, start_day.month - 1, start_day.day) 303 + const aligned_chart_series = align_chart_series(chart_series, start_date) 304 + line.lastChartSeriesDate = aligned_chart_series[aligned_chart_series.length - 1].time 302 305 303 - for (const dataPoint of alignedChartSeries) { 304 - line.instance.update(dataPoint) 306 + for (const data_point of aligned_chart_series) { 307 + line.instance.update(data_point) 305 308 } 306 309 } 307 310 }, ··· 314 317 } 315 318 const start = line.data[line.data.length - 1] ?? data[0] 316 319 const end = line.final ?? data[data.length - 1] 317 - const chartSeries = toChartSeries(data, start, end) 318 - line.lastChartSeriesDate = chartSeries[chartSeries.length - 1].time 320 + const chart_series = to_chart_series(data, start, end) 321 + line.lastChartSeriesDate = chart_series[chart_series.length - 1].time 319 322 const fresh = line.data.length === 0 320 323 321 324 if (fresh) { 322 - line.instance.setData(chartSeries) 325 + line.instance.setData(chart_series) 323 326 } else { 324 - for (const dataPoint of chartSeries) { 325 - line.instance.update(dataPoint) 327 + for (const data_point of chart_series) { 328 + line.instance.update(data_point) 326 329 } 327 330 } 328 331 }, ··· 332 335 store._appendChartData(line, data) 333 336 line.data.push(...data) 334 337 if (fresh) { 335 - updateFiller(chart.lines) 338 + update_filler(chart.lines) 336 339 store.resetZoom() 337 340 } 338 341 set(chart) ··· 341 344 addFinal(line: Line, data: DataPoint) { 342 345 store._appendChartData(line, [data]) 343 346 line.final = data 344 - updateFiller(chart.lines) 347 + update_filler(chart.lines) 345 348 set(chart) 346 349 }, 347 350 ··· 356 359 357 360 store.setLogScale(json.logScale) 358 361 359 - for (const jsonLine of json.lines) { 360 - store.addLine(jsonLine) 362 + for (const json_line of json.lines) { 363 + store.addLine(json_line) 361 364 } 362 365 if (json.lines[json.lines.length - 1]) { 363 - const lastColor = json.lines[json.lines.length - 1].color 364 - const lastColorIndex = hexColors.findIndex((color) => color === hexColors[lastColor]) 365 - nextColorIndex = (lastColorIndex + 1) % hexColors.length 366 + const last_color = json.lines[json.lines.length - 1].color 367 + const last_color_index = hex_colors.findIndex((color) => color === hex_colors[last_color]) 368 + next_color_index = (last_color_index + 1) % hex_colors.length 366 369 } 367 370 368 371 return store 369 372 } 370 373 371 374 /** Used to keep the full chart size even when some lines are hidden */ 372 - function getFiller(data: Line[], now: Date) { 373 - let lowestDate = (Date.now() / 1000) as UTCTimestamp 375 + function get_filler(data: Line[], now: Date) { 376 + let lowest_date = (Date.now() / 1000) as UTCTimestamp 374 377 for (const series of data) { 375 - const dataPoint = series.data[0] 376 - if (dataPoint && dataPoint.t < lowestDate) { 377 - lowestDate = dataPoint.t 378 + const data_point = series.data[0] 379 + if (data_point && data_point.t < lowest_date) { 380 + lowest_date = data_point.t 378 381 } 379 382 } 380 - const dt = new Date(lowestDate * 1000) 383 + const dt = new Date(lowest_date * 1000) 381 384 const date = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate()) 382 385 383 386 const dates = [date] ··· 386 389 new Date( 387 390 dates[dates.length - 1].getFullYear(), 388 391 dates[dates.length - 1].getMonth(), 389 - dates[dates.length - 1].getDate() + 1 390 - ) 392 + dates[dates.length - 1].getDate() + 1, 393 + ), 391 394 ) 392 395 } 393 396 return dates.map((date) => { ··· 410 413 return 411 414 } 412 415 413 - const jsonLines = chart.lines.map( 416 + const json_lines = chart.lines.map( 414 417 (line): LineJson => ({ 415 418 name: line.name, 416 - data: line.data.map((dataPoint) => dataPoint.t), 419 + data: line.data.map((data_point) => data_point.t), 417 420 color: line.color, 418 421 final: line.final, 419 - }) 422 + }), 420 423 ) 421 424 const json: Json = { 422 - lines: jsonLines, 423 - v: jsonTypeVersion, 425 + lines: json_lines, 426 + v: json_type_version, 424 427 align: chart.align, 425 428 logScale: chart.logScale, 426 429 expiry: Date.now() + day * 1, ··· 436 439 } 437 440 value: number 438 441 } 439 - function toChartSeries(data: DataPoint[], start: DataPoint, final: DataPoint): ChartSeries[] { 440 - const dataPoints: { date: Date; value: number }[] = [] 442 + function to_chart_series(data: DataPoint[], start: DataPoint, final: DataPoint): ChartSeries[] { 443 + const data_points: { date: Date; value: number }[] = [] 441 444 442 - for (const dataPoint of [start, ...data, final]) { 443 - const dt = new Date(dataPoint.t * 1000) 445 + for (const data_point of [start, ...data, final]) { 446 + const dt = new Date(data_point.t * 1000) 444 447 const date = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate()) 445 448 446 - let lastDataPoint = (dataPoints as Partial<typeof dataPoints>)[dataPoints.length - 1] 447 - if (lastDataPoint) { 448 - while (lastDataPoint.date < date) { 449 - dataPoints.push({ 449 + let last_data_piont = (data_points as Partial<typeof data_points>)[data_points.length - 1] 450 + if (last_data_piont) { 451 + while (last_data_piont.date < date) { 452 + data_points.push({ 450 453 date: new Date( 451 - lastDataPoint.date.getFullYear(), 452 - lastDataPoint.date.getMonth(), 453 - lastDataPoint.date.getDate() + 1 454 + last_data_piont.date.getFullYear(), 455 + last_data_piont.date.getMonth(), 456 + last_data_piont.date.getDate() + 1, 454 457 ), 455 - value: lastDataPoint.value, 458 + value: last_data_piont.value, 456 459 }) 457 - lastDataPoint = dataPoints[dataPoints.length - 1] 460 + last_data_piont = data_points[data_points.length - 1] 458 461 } 459 462 } 460 - if (lastDataPoint && lastDataPoint.date.getTime() === date.getTime()) { 461 - dataPoints[dataPoints.length - 1].value = dataPoint.v 463 + if (last_data_piont && last_data_piont.date.getTime() === date.getTime()) { 464 + data_points[data_points.length - 1].value = data_point.v 462 465 } else { 463 - dataPoints.push({ 466 + data_points.push({ 464 467 date: date, 465 - value: dataPoint.v, 468 + value: data_point.v, 466 469 }) 467 470 } 468 471 } 469 472 470 - return dataPoints.map((dataPoint) => { 473 + return data_points.map((data_point) => { 471 474 return { 472 475 time: { 473 - year: dataPoint.date.getFullYear(), 474 - month: dataPoint.date.getMonth() + 1, 475 - day: dataPoint.date.getDate(), 476 + year: data_point.date.getFullYear(), 477 + month: data_point.date.getMonth() + 1, 478 + day: data_point.date.getDate(), 476 479 }, 477 - value: dataPoint.value, 480 + value: data_point.value, 478 481 } satisfies SingleValueData 479 482 }) 480 483 } 481 484 482 - function alignChartSeries(chartSeries: ChartSeries[], start = new Date(2001, 0)): ChartSeries[] { 485 + function align_chart_series(chart_series: ChartSeries[], start = new Date(2001, 0)): ChartSeries[] { 483 486 const date = start 484 - return chartSeries.map((seriesPoint): ChartSeries => { 485 - const alignedSeriesPoint: ChartSeries = { 487 + return chart_series.map((series_point): ChartSeries => { 488 + const aligned_series_point: ChartSeries = { 486 489 time: { 487 490 day: date.getDate(), 488 491 month: date.getMonth() + 1, 489 492 year: date.getFullYear(), 490 493 }, 491 - value: seriesPoint.value, 494 + value: series_point.value, 492 495 } 493 496 date.setDate(date.getDate() + 1) 494 - return alignedSeriesPoint 497 + return aligned_series_point 495 498 }) 496 499 }
+8 -8
src/routes/color.ts
··· 11 11 'hsl(306, 100%, 52%)', 12 12 'hsl(0, 0%, 100%)', 13 13 ] 14 - export const hexColors = colors.map((hexColor) => { 15 - const color = new TinyColor(hexColor) 14 + export const hex_colors = colors.map((hex_color) => { 15 + const color = new TinyColor(hex_color) 16 16 return color.brighten(10).toHexString() 17 17 }) 18 - export const topColors = colors.map((hexColor) => { 19 - const color = new TinyColor(hexColor) 18 + export const top_colors = colors.map((hex_color) => { 19 + const color = new TinyColor(hex_color) 20 20 color.setAlpha(0.5) 21 21 return color.saturate(100).toHslString() 22 22 }) 23 - export const bottomColors = colors.map((hexColor) => { 24 - const color = new TinyColor(hexColor) 23 + export const bottom_colors = colors.map((hex_color) => { 24 + const color = new TinyColor(hex_color) 25 25 color.setAlpha(0) 26 26 return color.darken(0).toHslString() 27 27 }) 28 28 29 - export const brightColors = colors.map((hexColor) => { 30 - const color = new TinyColor(hexColor) 29 + export const bright_colors = colors.map((hex_color) => { 30 + const color = new TinyColor(hex_color) 31 31 return color.brighten(10).toHslString() 32 32 })
+7 -7
src/routes/github.ts
··· 4 4 import { get, writable } from 'svelte/store' 5 5 import { browser } from '$app/environment' 6 6 7 - const loadedToken = browser ? localStorage.getItem('starchart-token') : undefined 8 - export const token = writable(loadedToken || '') 7 + const loaded_token = browser ? localStorage.getItem('starchart-token') : undefined 8 + export const token = writable(loaded_token || '') 9 9 if (browser) { 10 10 token.subscribe((value) => { 11 11 if (value === '') { ··· 21 21 throttle: { enabled: false }, 22 22 }) 23 23 24 - export async function fetchStargazersPage( 24 + export async function fetch_stargazers_page( 25 25 owner: string, 26 26 repo: string, 27 27 direction: 'forward' | 'back', 28 - cursor?: string 28 + cursor?: string, 29 29 ) { 30 - const responsePromise = octokit.graphql<{ 30 + const response_promise = octokit.graphql<{ 31 31 repository: { 32 32 stargazers: { 33 33 totalCount: number ··· 64 64 before: direction === 'back' ? cursor : undefined, 65 65 first: direction === 'forward' ? 100 : undefined, 66 66 last: direction === 'back' ? 100 : undefined, 67 - } 67 + }, 68 68 ) 69 69 70 - const response = await responsePromise.catch((error) => { 70 + const response = await response_promise.catch((error) => { 71 71 if (error instanceof GraphqlResponseError && error.errors) { 72 72 return { 73 73 error: error.errors.map((error) => error.message).join('/n'),
+10 -10
src/routes/shortcuts.ts
··· 3 3 alt?: boolean 4 4 cmdOrCtrl?: boolean 5 5 } 6 - let isMac: boolean | undefined 6 + let is_mac: boolean | undefined 7 7 8 - export function checkModifiers(e: KeyboardEvent | MouseEvent, options: ShortcutOptions = {}) { 9 - if (isMac === undefined) { 10 - isMac = navigator.userAgent.indexOf('Mac') != -1 8 + export function check_modifiers(e: KeyboardEvent | MouseEvent, options: ShortcutOptions = {}) { 9 + if (is_mac === undefined) { 10 + is_mac = navigator.userAgent.indexOf('Mac') != -1 11 11 } 12 12 13 13 const target = { 14 14 shift: options.shift || false, 15 15 alt: options.alt || false, 16 - ctrl: (!isMac && options.cmdOrCtrl) || false, 17 - meta: (isMac && options.cmdOrCtrl) || false, 16 + ctrl: (!is_mac && options.cmdOrCtrl) || false, 17 + meta: (is_mac && options.cmdOrCtrl) || false, 18 18 } 19 19 20 20 const pressed = { ··· 32 32 ) 33 33 } 34 34 35 - export function checkShortcut(e: KeyboardEvent, key: string, options: ShortcutOptions = {}) { 35 + export function check_shortcut(e: KeyboardEvent, key: string, options: ShortcutOptions = {}) { 36 36 if (e.key.toUpperCase() !== key.toUpperCase()) return false 37 - return checkModifiers(e, options) 37 + return check_modifiers(e, options) 38 38 } 39 - export function checkMouseShortcut(e: MouseEvent, options: ShortcutOptions = {}) { 40 - return checkModifiers(e, options) 39 + export function check_mouse_shortcut(e: MouseEvent, options: ShortcutOptions = {}) { 40 + return check_modifiers(e, options) 41 41 }