+2
-2
.gitignore
+2
-2
.gitignore
+38
scripts/ColorScheme.svelte
+38
scripts/ColorScheme.svelte
···
···
1
+
<script>
2
+
import { stringIsTheme, Theme } from './preferences'
3
+
import { assert } from './utils'
4
+
5
+
const themes = [Theme.System, Theme.Light, Theme.Dark] as const
6
+
7
+
const descriptions: Record<Theme, string> = {
8
+
system: 'match <abbr title="operating system">OS</abbr>',
9
+
light: 'light',
10
+
dark: 'dark',
11
+
}
12
+
13
+
function selectTheme(event: Event) {
14
+
assert(event.target instanceof HTMLInputElement, 'badly configured theme chooser')
15
+
assert(stringIsTheme(event.target.value), 'badly configured theme component')
16
+
17
+
onSelectTheme(event.target.value)
18
+
}
19
+
20
+
export let selectedTheme: Theme
21
+
export let onSelectTheme: (newTheme: Theme) => void
22
+
</script>
23
+
24
+
<fieldset>
25
+
<legend>Color scheme</legend>
26
+
27
+
{#each themes as theme}
28
+
<label for={theme}>{@html descriptions[theme]}</label>
29
+
<input
30
+
type="radio"
31
+
name="theme"
32
+
id={theme}
33
+
value={theme}
34
+
on:input={selectTheme}
35
+
checked={theme === selectedTheme}
36
+
/>
37
+
{/each}
38
+
</fieldset>
+12
scripts/Icons/Adjust.svelte
+12
scripts/Icons/Adjust.svelte
···
+9
scripts/Icons/Close.svelte
+9
scripts/Icons/Close.svelte
+51
scripts/Preferences.svelte
+51
scripts/Preferences.svelte
···
···
1
+
<script>
2
+
import ColorScheme from './ColorScheme.svelte'
3
+
import Adjust from './Icons/Adjust.svelte'
4
+
import Close from './Icons/Close.svelte'
5
+
import ReadingMode from './ReadingMode.svelte'
6
+
7
+
import {
8
+
Theme,
9
+
loadPreferences,
10
+
persistTheme,
11
+
persistReadingMode,
12
+
} from './preferences'
13
+
14
+
let showPreferences = false
15
+
let { theme = Theme.System, readingMode = false } = loadPreferences()
16
+
17
+
// At initialization, make sure the initial values are set correctly.
18
+
persistTheme(theme)
19
+
persistReadingMode(readingMode)
20
+
21
+
const updateTheme = (newTheme: Theme) => {
22
+
persistTheme(newTheme)
23
+
theme = newTheme
24
+
}
25
+
26
+
const updateReadingMode = (newValue: boolean) => {
27
+
persistReadingMode(newValue)
28
+
readingMode = newValue
29
+
}
30
+
</script>
31
+
32
+
{#if !showPreferences}
33
+
<button on:click={(_) => (showPreferences = true)} class="preferences-button"><Adjust
34
+
/></button>
35
+
{/if}
36
+
37
+
{#if showPreferences}
38
+
<div class="panel">
39
+
<button
40
+
on:click={(_) => (showPreferences = false)}
41
+
class="preferences-button preferences-button--close"
42
+
>
43
+
<Close />
44
+
</button>
45
+
46
+
<form>
47
+
<ColorScheme selectedTheme={theme} onSelectTheme={updateTheme} />
48
+
<ReadingMode inReadingMode={readingMode} onSetReadingMode={updateReadingMode} />
49
+
</form>
50
+
</div>
51
+
{/if}
+22
scripts/ReadingMode.svelte
+22
scripts/ReadingMode.svelte
···
···
1
+
<script lang="typescript">
2
+
import { assert } from './utils'
3
+
4
+
function setReadingMode(event: Event) {
5
+
assert(event.target instanceof HTMLInputElement, 'badly configured reading mode')
6
+
onSetReadingMode(event.target.checked)
7
+
}
8
+
9
+
export let onSetReadingMode: (newValue: boolean) => void
10
+
export let inReadingMode: boolean
11
+
</script>
12
+
13
+
<fieldset>
14
+
<label for="reading-mode">Reading mode</label>
15
+
<input
16
+
type="checkbox"
17
+
name="reading-mode"
18
+
id="reading-mode"
19
+
checked={inReadingMode}
20
+
on:change={setReadingMode}
21
+
/>
22
+
</fieldset>
+8
scripts/main.js
+8
scripts/main.js
+81
scripts/preferences.ts
+81
scripts/preferences.ts
···
···
1
+
import { assert, selectorFor } from './utils'
2
+
3
+
const ROOT_EL = document.querySelector(selectorFor('root'))
4
+
assert(ROOT_EL instanceof HTMLElement, 'missing root element')
5
+
6
+
const PREFERENCES_EL = document.querySelector(selectorFor('preferences'))
7
+
assert(PREFERENCES_EL instanceof HTMLElement, 'missing preferences mount element')
8
+
PREFERENCES_EL.classList.remove('no-js-hidden')
9
+
10
+
export interface Preferences {
11
+
theme: Theme
12
+
readingMode: boolean
13
+
}
14
+
15
+
export enum Theme {
16
+
System = 'system',
17
+
Light = 'light',
18
+
Dark = 'dark',
19
+
}
20
+
21
+
const THEME_VALUES: string[] = [Theme.System, Theme.Light, Theme.Dark]
22
+
23
+
export const stringIsTheme = (s: string): s is Theme => THEME_VALUES.includes(s)
24
+
25
+
/**
26
+
Update the style class on the root (`html`) element.
27
+
28
+
@param root The `html` element
29
+
@param newTheme The new theme to set on that `html` element.
30
+
*/
31
+
const updateThemeClass = (newTheme: Theme): void => {
32
+
THEME_VALUES.forEach((className) => ROOT_EL.classList.remove(className))
33
+
if (newTheme !== Theme.System) ROOT_EL.classList.add(newTheme)
34
+
}
35
+
36
+
const updateReadingModeClass = (inReadingMode: boolean): void => {
37
+
if (inReadingMode) {
38
+
ROOT_EL.classList.add('reading-mode')
39
+
} else {
40
+
ROOT_EL.classList.remove('reading-mode')
41
+
}
42
+
}
43
+
44
+
const enum LocalStorage {
45
+
Theme = 'sympolymathesy:theme',
46
+
ReadingMode = 'sympolymathesy:reading-mode',
47
+
}
48
+
49
+
// If the user chooses to follow the OS, simply delete the key from local storage: there
50
+
// is no need to *store* "use the OS".
51
+
const saveThemePreference = (theme: Theme): void =>
52
+
theme === Theme.System
53
+
? localStorage.removeItem(LocalStorage.Theme)
54
+
: localStorage.setItem(LocalStorage.Theme, theme)
55
+
56
+
const saveReadingModePreference = (inReadingMode: boolean): void =>
57
+
inReadingMode
58
+
? localStorage.setItem(LocalStorage.ReadingMode, 'true')
59
+
: localStorage.removeItem(LocalStorage.ReadingMode)
60
+
61
+
export const loadPreferences = (): Preferences => {
62
+
const themeFromStorage = localStorage.getItem(LocalStorage.Theme)
63
+
const theme =
64
+
themeFromStorage && stringIsTheme(themeFromStorage)
65
+
? themeFromStorage
66
+
: Theme.System
67
+
68
+
const readingMode = localStorage.getItem(LocalStorage.ReadingMode) === 'true'
69
+
70
+
return { theme, readingMode }
71
+
}
72
+
73
+
export const persistTheme = (newTheme: Theme): void => {
74
+
updateThemeClass(newTheme)
75
+
saveThemePreference(newTheme)
76
+
}
77
+
78
+
export const persistReadingMode = (inReadingMode: boolean): void => {
79
+
updateReadingModeClass(inReadingMode)
80
+
saveReadingModePreference(inReadingMode)
81
+
}
+13
scripts/tsconfig.json
+13
scripts/tsconfig.json
···
···
1
+
{
2
+
"extends": "../tsconfig.base.json",
3
+
"compilerOptions": {
4
+
"removeComments": true,
5
+
"lib": ["dom", "es2019"],
6
+
"noEmit": false,
7
+
"inlineSources": true,
8
+
"sourceMap": true,
9
+
"baseUrl": "scripts"
10
+
},
11
+
"files": ["preferences.ts"],
12
+
"include": ["scripts"]
13
+
}
+7
scripts/utils.ts
+7
scripts/utils.ts
+12
-8
site/_includes/base.njk
+12
-8
site/_includes/base.njk
···
2
{% import 'components/social.njk' as social %}
3
4
<!DOCTYPE html>
5
-
<html>
6
<head>
7
<meta charset='utf-8'/>
8
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
···
28
<link rel='alternate' href='/essays/feed.json' type='application/json' title='Essays - Sympolymathesy (JSON)'>
29
<link rel='alternate' href='/journal/feed.json' type='application/json' title='Journal - Sympolymathesy (JSON)'>
30
<link rel='alternate' href='/library/feed.json' type='application/json' title='Library - Sympolymathesy (JSON)'>
31
-
<link rel='alternate' href='/photos/feed.json' type='application/json' title='Elsewhere - Sympolymathesy (JSON)'>
32
-
<link rel='alternate' href='/elsewhere/feed.json' type='application/json' title='Elsewhere - Sympolymathesy (JSON)'>
33
<link rel='alternate' href='/notes/feed.json' type='application/json' title='Notes - Sympolymathesy (JSON)'>
34
{% endif -%}
35
36
<link rel='alternate' href='/feed.xml' type='application/atom+xml' title='Sympolymathesy (Atom)'>
···
40
<link rel='alternate' href='/essays/feed.xml' type='application/atom+xml' title='Essays - Sympolymathesy (Atom)'>
41
<link rel='alternate' href='/journal/feed.xml' type='application/atom+xml' title='Journal - Sympolymathesy (Atom)'>
42
<link rel='alternate' href='/library/feed.xml' type='application/atom+xml' title='Library - Sympolymathesy (Atom)'>
43
-
<link rel='alternate' href='/photos/feed.xml' type='application/atom+xml' title='Elsewhere - Sympolymathesy (Atom)'>
44
-
<link rel='alternate' href='/elsewhere/feed.xml' type='application/atom+xml' title='Elsewhere - Sympolymathesy (Atom)'>
45
<link rel='alternate' href='/notes/feed.xml' type='application/atom+xml' title='Notes - Sympolymathesy (Atom)'>
46
{% endif -%}
47
48
{% for link in config.author.links -%}
···
54
55
{% block extra_links %}{% endblock extra_links %}
56
57
-
{% block meta %}{{ social.meta(page, config) }}
58
-
{% endblock meta%}
59
</head>
60
<body>
61
<main>
···
87
{%- endfor -%}
88
</ul>
89
</nav>
90
</body>
91
-
</html>
···
2
{% import 'components/social.njk' as social %}
3
4
<!DOCTYPE html>
5
+
<html data-sympolymathesy='root'>
6
<head>
7
<meta charset='utf-8'/>
8
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
···
28
<link rel='alternate' href='/essays/feed.json' type='application/json' title='Essays - Sympolymathesy (JSON)'>
29
<link rel='alternate' href='/journal/feed.json' type='application/json' title='Journal - Sympolymathesy (JSON)'>
30
<link rel='alternate' href='/library/feed.json' type='application/json' title='Library - Sympolymathesy (JSON)'>
31
+
<link rel='alternate' href='/photos/feed.json' type='application/json' title='Photos - Sympolymathesy (JSON)'>
32
<link rel='alternate' href='/notes/feed.json' type='application/json' title='Notes - Sympolymathesy (JSON)'>
33
+
<link rel='alternate' href='/elsewhere/feed.json' type='application/json' title='Elsewhere - Sympolymathesy (JSON)'>
34
{% endif -%}
35
36
<link rel='alternate' href='/feed.xml' type='application/atom+xml' title='Sympolymathesy (Atom)'>
···
40
<link rel='alternate' href='/essays/feed.xml' type='application/atom+xml' title='Essays - Sympolymathesy (Atom)'>
41
<link rel='alternate' href='/journal/feed.xml' type='application/atom+xml' title='Journal - Sympolymathesy (Atom)'>
42
<link rel='alternate' href='/library/feed.xml' type='application/atom+xml' title='Library - Sympolymathesy (Atom)'>
43
+
<link rel='alternate' href='/photos/feed.xml' type='application/atom+xml' title='Photos - Sympolymathesy (Atom)'>
44
<link rel='alternate' href='/notes/feed.xml' type='application/atom+xml' title='Notes - Sympolymathesy (Atom)'>
45
+
<link rel='alternate' href='/elsewhere/feed.xml' type='application/atom+xml' title='Elsewhere - Sympolymathesy (Atom)'>
46
{% endif -%}
47
48
{% for link in config.author.links -%}
···
54
55
{% block extra_links %}{% endblock extra_links %}
56
57
+
<link rel='preload' as='script' type='application/javascript' href='/assets/js/main.js'>
58
+
59
+
{% block meta %}{{ social.meta(page, config) }}{% endblock meta%}
60
</head>
61
<body>
62
<main>
···
88
{%- endfor -%}
89
</ul>
90
</nav>
91
+
92
+
<div data-sympolymathesy='preferences' class='preferences no-js-hidden'></div>
93
+
<script src='/assets/js/main.js'></script>
94
</body>
95
+
</html>
+3
-2
site/_includes/styles/_layout.scss
+3
-2
site/_includes/styles/_layout.scss
···
11
--padding: #{ms(-8)};
12
margin: var(--padding);
13
width: calc(100% - 2 * var(--padding));
14
}
15
16
@media screen {
···
27
28
@media (min-height: 600px) {
29
main {
30
-
transition: 0.7s margin ease-out, 0.7s max-width ease-out;
31
--padding: #{ms(-1)};
32
33
margin: {
···
47
top: 0;
48
right: 0;
49
bottom: 0;
50
}
51
52
.reading-mode {
53
main {
54
-
transition: 0.7s margin ease-out, 0.7s max-width ease-out;
55
--padding: 0.25em;
56
max-width: calc(100vw - 0.5em - 2px);
57
}
58
59
nav {
60
right: -25vw;
61
}
62
}
63
}
···
11
--padding: #{ms(-8)};
12
margin: var(--padding);
13
width: calc(100% - 2 * var(--padding));
14
+
transition: 0.7s margin ease-out, 0.7s max-width ease-out;
15
}
16
17
@media screen {
···
28
29
@media (min-height: 600px) {
30
main {
31
--padding: #{ms(-1)};
32
33
margin: {
···
47
top: 0;
48
right: 0;
49
bottom: 0;
50
+
transition: 0.7s right ease-out;
51
}
52
53
.reading-mode {
54
main {
55
--padding: 0.25em;
56
max-width: calc(100vw - 0.5em - 2px);
57
}
58
59
nav {
60
right: -25vw;
61
+
transition: 0.7s right ease-out;
62
}
63
}
64
}
+2
-1
site/_includes/styles/_utils.scss
+2
-1
site/_includes/styles/_utils.scss
+12
site/_includes/styles/components/_preferences.scss
+12
site/_includes/styles/components/_preferences.scss
+1
site/_includes/styles/style.scss
+1
site/_includes/styles/style.scss
+12
-20
site/journal/notes-on-color-scheme-handling.md
site/journal/2020/Color Schemes.md
+12
-20
site/journal/notes-on-color-scheme-handling.md
site/journal/2020/Color Schemes.md
···
1
---
2
title: Color Schemes!
3
subtitle: >
4
-
A few notes on pairing <code>prefers-color-scheme</code> and user configurability.
5
-
date: 2019-12-07T11:45
6
tags:
7
- JavaScript
8
- TypeScript
···
11
12
---
13
14
-
When redesigning this site, I knew I wanted to take advantage of macOS' and Windows' recent ability to support dark mode in the website (with the new CSS media query [`prefers-color-scheme`]). However, I also knew that I wanted to make things user-configurable. As same time I publish this post, I have also added a tiny bit of JavaScript to the site that lets users override their operating system default to view the site in its light or dark theme as they please.
15
-
16
-
[`prefers-color-scheme`]: TODO
17
18
-
*[CSS]: cascading style sheets
19
20
As is my habit when I deal with a question of how to implement something like this, I built out a table to capture how this should work:
21
···
31
| dark | light | light |
32
| dark | dark | dark |
33
34
-
This isn't complicated, <i>per se</i>… but it it *does* require some thought to make sure it works just right and that the CSS and JS interact correctly.
35
-
36
-
*[JS]: JavaScript
37
38
-
## CSS
39
40
-
On the CSS side of things, it was important that there be *one* definition of what the light and dark color schemes are, and then that the `prefers-color-scheme` and a CSS class both use that same definition. That way, I don't have to try to keep multiple definitions in sync.
41
42
-
To make this work, I combined the power of [CSS Custom Properties] and an [SCSS] mixin. The custom properties define the set of colors in play throughout the site: foreground, background, borders, link colors, etc. The mixin then applies those custom properties to the style selectors. As a simplified example:
43
44
```scss
45
@mixin light {
···
66
}
67
```
68
69
-
[CSS Custom Properties]: TODO
70
-
[SCSS]: TODO
71
-
72
-
*[SCSS]: TODO
73
74
## JavaScript
75
76
-
Because I did the hard work of pushing all the complexity into the CSS, the JS ends up being very simple. It only really has two responsibilities:
77
78
-
1. setting or clearing the `.light` or `.dark` classes when the user interacts with the UI element
79
2. if the user has specified an override, storing that decision somewhere to look it up when the site loads
80
-
81
-
*[UI]: user interface
82
83
### Responding to the user setting
84
···
1
---
2
title: Color Schemes!
3
subtitle: >
4
+
A few notes on pairing `prefers-color-scheme` and user configurability.
5
+
date: 2020-12-30T12:00
6
tags:
7
- JavaScript
8
- TypeScript
···
11
12
---
13
14
+
When redesigning this site, I knew I wanted to take advantage of macOS' and Windows' recently-added ability to support dark mode in the website (with the new <abbr title="cascading style sheets">CSS</abbr> media query [`prefers-color-scheme`]). However, I also knew that I wanted to make it user-configurable. It took me over a year, but at last—at the same time as same time I publish this post—I have also added a tiny bit of JavaScript to the site that lets users override their operating system default to view the site in its light or dark theme as they please.
15
16
+
[`prefers-color-scheme`]: http://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
17
18
As is my habit when I deal with a question of how to implement something like this, I built out a table to capture how this should work:
19
···
29
| dark | light | light |
30
| dark | dark | dark |
31
32
+
This isn't complicated, <i>per se</i>… but it it *does* require some thought to make sure it works just right and that the <abbr>CSS</abbr> and <abbr title="JavaScript">JS</abbr> interact correctly.
33
34
+
## <abbr>CSS</abbr>
35
36
+
On the <abbr>CSS</abbr> side of things, it was important that there be *one* definition of what the light and dark color schemes are, and then that the `prefers-color-scheme` and a <abbr>CSS</abbr> class both use that same definition. That way, I don't have to try to keep multiple definitions in sync.
37
38
+
To make this work, I combined the power of [<abbr>CSS</abbr> Custom Properties][custom-properties] and an [<abbr title="sassy CSS">SCSS</abbr>][SCSS] mixin. The custom properties define the set of colors in play throughout the site: foreground, background, borders, link colors, etc. The mixin then applies those custom properties to the style selectors. As a simplified example:
39
40
```scss
41
@mixin light {
···
62
}
63
```
64
65
+
[custom-properties]: http://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
66
+
[SCSS]: https://sass-lang.com
67
68
## JavaScript
69
70
+
Because I did the hard work of pushing all the complexity into the <abbr>CSS</abbr>, the <abbr>JS</abbr> ends up being very simple. It only really has two responsibilities:
71
72
+
1. setting or clearing the `.light` or `.dark` classes when the user interacts with the <abbr title="user interface">UI</abbr> element
73
2. if the user has specified an override, storing that decision somewhere to look it up when the site loads
74
75
### Responding to the user setting
76
-5
svelte.config.js
-5
svelte.config.js
+37
tsconfig.base.json
+37
tsconfig.base.json
···
···
1
+
{
2
+
"compilerOptions": {
3
+
/* Basic Options */
4
+
"target": "es2019",
5
+
"module": "commonjs",
6
+
"lib": ["es2019"] /* Specify library files to be included in the compilation. */,
7
+
"checkJs": true /* Report errors in .js files. */,
8
+
"allowJs": true,
9
+
10
+
/* Strict Type-Checking Options */
11
+
"strict": true /* Enable all strict type-checking options. */,
12
+
13
+
/* Additional Checks */
14
+
"noUnusedLocals": true /* Report errors on unused locals. */,
15
+
"noUnusedParameters": true /* Report errors on unused parameters. */,
16
+
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
17
+
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
18
+
19
+
/* Module Resolution Options */
20
+
"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
21
+
"paths": {
22
+
"*": ["types/*"]
23
+
} /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */,
24
+
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
25
+
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
26
+
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
27
+
28
+
/* Source Map Options */
29
+
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
30
+
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
31
+
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
32
+
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
33
+
34
+
/* Experimental Options */
35
+
"experimentalDecorators": true /* Enables experimental support for ES7 decorators. */
36
+
}
37
+
}
+3
-48
tsconfig.json
+3
-48
tsconfig.json
···
1
{
2
"compilerOptions": {
3
-
/* Basic Options */
4
-
"target": "es2018" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
5
-
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
6
-
"lib": ["es2019"] /* Specify library files to be included in the compilation. */,
7
-
"checkJs": true /* Report errors in .js files. */,
8
-
"allowJs": true,
9
-
// "declaration": true, /* Generates corresponding '.d.ts' file. */
10
-
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
11
-
// "sourceMap": true, /* Generates corresponding '.map' file. */
12
-
// "outFile": "./", /* Concatenate and emit output to single file. */
13
-
// "outDir": "./", /* Redirect output structure to the directory. */
14
-
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
15
-
// "composite": true, /* Enable project compilation */
16
-
// "incremental": true, /* Enable incremental compilation */
17
-
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
18
-
// "removeComments": true, /* Do not emit comments to output. */
19
-
"noEmit": true /* Do not emit outputs. (BECAUSE WE'RE USING TS-NODE!) */,
20
-
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
21
-
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
22
-
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
23
-
24
-
/* Strict Type-Checking Options */
25
-
"strict": true /* Enable all strict type-checking options. */,
26
-
27
-
/* Additional Checks */
28
-
"noUnusedLocals": true /* Report errors on unused locals. */,
29
-
"noUnusedParameters": true /* Report errors on unused parameters. */,
30
-
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
31
-
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
32
-
33
-
/* Module Resolution Options */
34
-
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
35
-
"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
36
-
"paths": {
37
-
"*": ["types/*"]
38
-
} /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */,
39
-
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
40
-
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
41
-
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
42
-
43
-
/* Source Map Options */
44
-
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
45
-
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
46
-
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
47
-
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
48
-
49
-
/* Experimental Options */
50
-
"experimentalDecorators": true /* Enables experimental support for ES7 decorators. */
51
},
52
"include": ["site/**/*.11ty.js", "lib", "eleventy", "types", ".eleventy.ts"],
53
"exclude": ["site/_data/build.js"]