@davidsouther/jiffies 1.0.0-beta.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/build/components/button_bar.js +24 -13
  2. package/build/components/select.d.ts +1 -4
  3. package/build/display.js +9 -1
  4. package/build/dom/dom.js +1 -0
  5. package/build/dom/form/form.d.ts +9 -8
  6. package/build/dom/form/form.js +14 -5
  7. package/build/dom/provide.d.ts +3 -0
  8. package/build/dom/provide.js +7 -0
  9. package/build/equal.d.ts +5 -4
  10. package/build/equal.js +19 -4
  11. package/build/fs.d.ts +48 -0
  12. package/build/fs.js +144 -0
  13. package/build/{components/index.d.ts → fs.test.d.ts} +0 -0
  14. package/build/fs.test.js +43 -0
  15. package/build/log.js +16 -4
  16. package/build/result.d.ts +11 -11
  17. package/build/result.js +2 -2
  18. package/build/scope/execute.js +1 -1
  19. package/build/scope/expect.d.ts +1 -1
  20. package/build/scope/expect.js +4 -3
  21. package/build/server/http/css.d.ts +5 -0
  22. package/build/server/http/css.js +47 -0
  23. package/build/server/http/index.js +4 -2
  24. package/build/server/http/response.js +6 -3
  25. package/build/test_all.d.ts +7 -1
  26. package/build/test_all.js +7 -8
  27. package/package.json +5 -2
  28. package/src/components/button_bar.ts +32 -26
  29. package/src/display.ts +8 -2
  30. package/src/dom/dom.ts +1 -0
  31. package/src/dom/form/form.ts +30 -7
  32. package/src/dom/provide.ts +11 -0
  33. package/src/equal.ts +22 -11
  34. package/src/fs.test.ts +53 -0
  35. package/src/fs.ts +180 -0
  36. package/src/index.html +4 -4
  37. package/src/log.ts +8 -4
  38. package/src/pico/_variables.scss +66 -0
  39. package/src/pico/components/_accordion.scss +112 -0
  40. package/src/pico/components/_button-group.scss +51 -0
  41. package/src/pico/components/_card.scss +47 -0
  42. package/src/pico/components/_dropdown.scss +203 -0
  43. package/src/pico/components/_modal.scss +181 -0
  44. package/src/pico/components/_nav.scss +79 -0
  45. package/src/pico/components/_progress.scss +70 -0
  46. package/src/pico/components/_property.scss +34 -0
  47. package/src/pico/content/_button.scss +152 -0
  48. package/src/pico/content/_code.scss +63 -0
  49. package/src/pico/content/_embedded.scss +0 -0
  50. package/src/pico/content/_form-alt.scss +276 -0
  51. package/src/pico/content/_form.scss +259 -0
  52. package/src/pico/content/_misc.scss +0 -0
  53. package/src/pico/content/_table.scss +28 -0
  54. package/src/pico/content/_toggle.scss +132 -0
  55. package/src/pico/content/_typography.scss +232 -0
  56. package/src/pico/layout/_container.scss +40 -0
  57. package/src/pico/layout/_document.scss +0 -0
  58. package/src/pico/layout/_flex.scss +46 -0
  59. package/src/pico/layout/_grid.scss +24 -0
  60. package/src/pico/layout/_scroller.scss +16 -0
  61. package/src/pico/layout/_section.scss +8 -0
  62. package/src/pico/layout/_sectioning.scss +53 -0
  63. package/src/pico/pico.scss +60 -0
  64. package/src/pico/reset/_accessibility.scss +34 -0
  65. package/src/pico/reset/_button.scss +17 -0
  66. package/src/pico/reset/_code.scss +15 -0
  67. package/src/pico/reset/_document.scss +48 -0
  68. package/src/pico/reset/_embedded.scss +39 -0
  69. package/src/pico/reset/_form.scss +97 -0
  70. package/src/pico/reset/_misc.scss +23 -0
  71. package/src/pico/reset/_nav.scss +5 -0
  72. package/src/pico/reset/_progress.scss +4 -0
  73. package/src/pico/reset/_table.scss +8 -0
  74. package/src/pico/reset/_typography.scss +25 -0
  75. package/src/pico/themes/default/_colors.scss +65 -0
  76. package/src/pico/themes/default/_dark.scss +148 -0
  77. package/src/pico/themes/default/_light.scss +149 -0
  78. package/src/pico/themes/default/_styles.scss +272 -0
  79. package/src/pico/themes/default.scss +34 -0
  80. package/src/pico/utilities/_accessibility.scss +3 -0
  81. package/src/pico/utilities/_loading.scss +52 -0
  82. package/src/pico/utilities/_reduce-motion.scss +27 -0
  83. package/src/pico/utilities/_tooltip.scss +101 -0
  84. package/src/result.ts +16 -20
  85. package/src/scope/execute.ts +1 -1
  86. package/src/scope/expect.ts +10 -9
  87. package/src/server/http/css.ts +63 -0
  88. package/src/server/http/index.ts +4 -2
  89. package/src/server/http/response.ts +7 -4
  90. package/src/test_all.ts +7 -8
  91. package/src/zip/spec.txt +3260 -0
  92. package/build/components/index.js +0 -1
  93. package/build/index.d.ts +0 -13
  94. package/build/index.js +0 -13
  95. package/build/parcel_resolver.d.ts +0 -3
  96. package/build/parcel_resolver.js +0 -19
@@ -14,7 +14,9 @@ const MIME_TYPES = {
14
14
  woff2: "application/font-woff2",
15
15
  };
16
16
  const mime = (basename) => {
17
- const extension = basename.substr(basename.lastIndexOf(".") + 1);
17
+ const extension = basename
18
+ .substring(basename.lastIndexOf(".") + 1)
19
+ .toLowerCase();
18
20
  return MIME_TYPES[extension] ?? "application/octet-stream";
19
21
  };
20
22
  export const fileResponse = (filename, stat, status = 200) => async () => {
@@ -26,11 +28,12 @@ export const fileResponse = (filename, stat, status = 200) => async () => {
26
28
  const contentLength = stat.size;
27
29
  return { status, contentType, contentLength, content };
28
30
  };
31
+ const CHARSET = "utf-8";
29
32
  export const contentResponse = (content, contentType, status = 200) => async () => {
30
- const contentBuffer = Buffer.from(content, "utf-8");
33
+ const contentBuffer = Buffer.from(content, CHARSET);
31
34
  return {
32
35
  content: contentBuffer,
33
- contentType,
36
+ contentType: contentType.split(";")[0] + "; charset=" + CHARSET,
34
37
  status,
35
38
  contentLength: contentBuffer.length,
36
39
  };
@@ -1 +1,7 @@
1
- export {};
1
+ import "./context.test.js";
2
+ import "./equal.test.js";
3
+ import "./flags.test.js";
4
+ import "./fs.test.js";
5
+ import "./generator.test.js";
6
+ import "./lock.test.js";
7
+ import "./result.test.js";
package/build/test_all.js CHANGED
@@ -1,14 +1,13 @@
1
1
  // This file must be .js for imports to run. Unused imports in .ts files are
2
2
  // discarded during transpilation.
3
3
  import { describe, expect, it } from "./scope/index.js";
4
- await Promise.all([
5
- import("./context.test.js"),
6
- import("./equal.test.js"),
7
- import("./flags.test.js"),
8
- import("./generator.test.js"),
9
- import("./lock.test.js"),
10
- import("./result.test.js"),
11
- ]);
4
+ import "./context.test.js";
5
+ import "./equal.test.js";
6
+ import "./flags.test.js";
7
+ import "./fs.test.js";
8
+ import "./generator.test.js";
9
+ import "./lock.test.js";
10
+ import "./result.test.js";
12
11
  describe("Test executor", () => {
13
12
  it("matches equality", () => {
14
13
  expect(1).toBe(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@davidsouther/jiffies",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "displayName": "JEFRi Jiffies",
6
6
  "type": "module",
@@ -31,6 +31,9 @@
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^17.0.24",
34
- "typescript": "^4.7.0-dev.20220415"
34
+ "typescript": "4.7.1-rc"
35
+ },
36
+ "dependencies": {
37
+ "sass": "^1.49.9"
35
38
  }
36
39
  }
@@ -1,6 +1,9 @@
1
- import { Display, display } from "../display.js";
1
+ import { display } from "../display.js";
2
2
  import { FC } from "../dom/fc.js";
3
- import { a, li, ul } from "../dom/html.js";
3
+ import { fieldset, input, label } from "../dom/html.js";
4
+
5
+ let buttonBarId = 1;
6
+ let nextId = () => buttonBarId++;
4
7
 
5
8
  const ButtonBar = FC<{
6
9
  // T extends Display
@@ -10,29 +13,32 @@ const ButtonBar = FC<{
10
13
  values: T[];
11
14
  // @ts-ignore TODO(TFC)
12
15
  events: { onSelect: (current: T) => void };
13
- }>("button-bar", (el, { value, values, events }) =>
14
- ul(
15
- { class: "ButtonBar__wrapper" },
16
- ...values.map((option) =>
17
- li(
18
- a(
19
- {
20
- href: "#",
21
- class: `ButtonBar__${`${option}`.replace(/\s+/g, "_").toLowerCase()}
22
- ${option === value ? "" : "secondary"}
23
- `.replace(/[\n\s]+/, " "),
24
- events: {
25
- click: (e) => {
26
- e.preventDefault();
27
- events.onSelect(option);
16
+ }>("button-bar", (el, { value, values, events }) => {
17
+ const name = `button-bar-${nextId()}`;
18
+ return fieldset(
19
+ { class: "input-group" },
20
+ ...values
21
+ .map((option) => {
22
+ const opt = `${option}`.replace(/\s+/g, "_").toLowerCase();
23
+ const id = `${name}-${opt}`;
24
+ return [
25
+ label(
26
+ { role: "button", htmlFor: id },
27
+ input({
28
+ type: "radio",
29
+ id,
30
+ name,
31
+ value: option,
32
+ checked: option === value,
33
+ events: {
34
+ change: () => events.onSelect(option),
28
35
  },
29
- },
30
- },
31
- display(option)
32
- )
33
- )
34
- )
35
- )
36
- );
37
-
36
+ }),
37
+ display(option)
38
+ ),
39
+ ];
40
+ })
41
+ .flat()
42
+ );
43
+ });
38
44
  export default ButtonBar;
package/src/display.ts CHANGED
@@ -8,5 +8,11 @@ export const isDisplay = (/** @type unknown */ a: unknown): a is Display =>
8
8
  typeof (a as Display).toString === "function" ||
9
9
  typeof (a as Display) === "string";
10
10
 
11
- export const display = (a: unknown | Display): string =>
12
- isDisplay(a) ? a.toString() : JSON.stringify(a);
11
+ export const display = (a: unknown | Display): string => {
12
+ if (isDisplay(a)) {
13
+ const str = a.toString();
14
+ if (str === "[object Object]") return JSON.stringify(a);
15
+ return str;
16
+ }
17
+ return JSON.stringify(a);
18
+ };
package/src/dom/dom.ts CHANGED
@@ -115,6 +115,7 @@ export function update<E extends DOMElement>(
115
115
 
116
116
  let useAttributes =
117
117
  k.startsWith("aria-") ||
118
+ k == "role" ||
118
119
  element.namespaceURI != "http://www.w3.org/1999/xhtml";
119
120
 
120
121
  if (useAttributes) {
@@ -3,6 +3,7 @@ import { form, input, label, option, select } from "../html.js";
3
3
  import {
4
4
  FormAttributes,
5
5
  InputAttributes,
6
+ LabelAttributes,
6
7
  OptionAttributes,
7
8
  SelectAttributes,
8
9
  } from "../types/html.js";
@@ -19,8 +20,18 @@ export const Form = (attrs: FormAttributes, ...children: DenormChildren[]) => {
19
20
  };
20
21
  export const Input = (attrs: InputAttributes, ...children: DenormChildren[]) =>
21
22
  label(input(attrs as Attrs<HTMLInputElement>), ...children);
22
- export const Select = ({ options }: { options: string[] | {} }) =>
23
- label(select(...prepareOptions(options).map(Option)));
23
+
24
+ export const Select = (
25
+ attrs: { options: string[] | {}; selected?: string } & SelectAttributes &
26
+ LabelAttributes
27
+ ) =>
28
+ label(
29
+ { style: attrs.style ?? {} },
30
+ select(
31
+ { events: attrs.events ?? {} },
32
+ ...prepareOptions(attrs.options, attrs.selected).map(Option)
33
+ )
34
+ );
24
35
  export const Button = () => {};
25
36
 
26
37
  const prepareOptions = (
@@ -29,19 +40,31 @@ const prepareOptions = (
29
40
  | Record<
30
41
  string,
31
42
  string | { label: string; disabled?: boolean; selected?: boolean }
32
- >
43
+ >,
44
+ selected?: string
33
45
  ): Parameters<typeof Option>[0][] =>
34
46
  Array.isArray(attrs)
35
- ? attrs.map((value) => ({ value, label: value }))
47
+ ? attrs.map((value) => ({
48
+ value,
49
+ label: value,
50
+ selected: selected == value,
51
+ }))
36
52
  : Object.entries(attrs).map(([value, label]) =>
37
- typeof label === "string" ? { value, label } : { value, ...label }
53
+ typeof label === "string"
54
+ ? { value, label, selected: selected === value }
55
+ : { value, ...label }
38
56
  );
39
57
  export const Option = (attrs: OptionAttributes) =>
40
58
  option(attrs as Attrs<HTMLOptionElement>);
41
59
 
42
60
  export const Dropdown = (
43
- attrs: SelectAttributes | { options: Parameters<typeof prepareOptions>[0] }
44
- ) => {};
61
+ attrs: SelectAttributes | { selected?: string },
62
+ ...options: Parameters<typeof prepareOptions>[0][]
63
+ ) =>
64
+ Select({
65
+ ...attrs,
66
+ options: typeof options[0] == "string" ? options : options[0],
67
+ });
45
68
  export const Radios = () => {};
46
69
  export const Checks = () => {};
47
70
  export const Switches = () => {};
@@ -0,0 +1,11 @@
1
+ import { Option } from "../result.js";
2
+
3
+ let registry: Record<string, unknown> = {};
4
+
5
+ export function provide(items: Record<string, unknown>) {
6
+ registry = { ...registry, ...items };
7
+ }
8
+
9
+ export function retrieve<T>(key: string): Option<T> {
10
+ return registry[key] as T;
11
+ }
package/src/equal.ts CHANGED
@@ -1,31 +1,42 @@
1
1
  export function compareArrays<T>(
2
- equal: (a: T, b: T) => boolean
3
- ): (A: T[], B: T[]) => boolean {
4
- return (a: T[], b: T[]): boolean =>
5
- a.length === b.length && a.every((e, i) => equal(e, b[i]));
2
+ equal: (a: T, b: T, partial: boolean) => boolean
3
+ ): (A: T[], B: T[], partial?: boolean) => boolean {
4
+ return (a: T[], b: T[], partial = false): boolean =>
5
+ a.length === b.length && a.every((e, i) => equal(e, b[i], partial));
6
6
  }
7
7
 
8
8
  export const equalArrays = compareArrays(Object.is);
9
9
 
10
- export const matchArrays: <A>(a: A[], b: A[]) => boolean =
10
+ export const matchArrays: <A>(a: A[], b: A[], partial?: boolean) => boolean =
11
11
  compareArrays(equals);
12
12
 
13
13
  function asArray(a: Record<string, unknown>): [string, unknown][] {
14
14
  return Object.entries(a).sort((a, b) => a[0].localeCompare(b[0]));
15
15
  }
16
16
 
17
- export function equals<A>(a: A | A[], b: A | A[]): boolean {
17
+ export const matchObjects = (a: {}, b: {}, partial = true) => {
18
+ for (const [k, v] of Object.entries(a)) {
19
+ if (!b.hasOwnProperty(k) && partial) continue;
20
+ // @ts-ignore
21
+ if (!equals(v, b[k], partial)) return false;
22
+ }
23
+ return true;
24
+ };
25
+
26
+ export function equals<A>(a: A | A[], b: A | A[], partial = false): boolean {
18
27
  // runtime type checking
19
28
  switch (typeof a) {
20
29
  case "object":
30
+ if (b === undefined) {
31
+ return false;
32
+ }
21
33
  if (a instanceof Array && b instanceof Array) {
22
- return matchArrays(a, b);
34
+ return matchArrays(a, b, partial);
23
35
  } else {
24
- return matchArrays(
25
- asArray(a as Record<string, unknown>),
26
- asArray(b as Record<string, unknown>)
27
- );
36
+ return matchObjects(a, b, partial);
28
37
  }
38
+ case "function":
39
+ return a.name == (b as unknown as Function).name;
29
40
  default:
30
41
  return Object.is(a, b);
31
42
  }
package/src/fs.test.ts ADDED
@@ -0,0 +1,53 @@
1
+ import { FileSystem, ObjectFileSystemAdapter } from "./fs.js";
2
+ import { describe, it, expect } from "./scope/index.js";
3
+
4
+ describe("FileSystem", () => {
5
+ describe("Writing", () => {
6
+ it("Writes files", async () => {
7
+ const fsObj = {};
8
+ const fs = new FileSystem(new ObjectFileSystemAdapter(fsObj));
9
+ await fs.writeFile("hello", "world");
10
+
11
+ expect(fsObj).toEqual({ "/hello": "world" });
12
+ });
13
+
14
+ it("Writes deep files", async () => {
15
+ const fsObj = {};
16
+ const fs = new FileSystem(new ObjectFileSystemAdapter(fsObj));
17
+ await fs.writeFile("deep/hello", "world");
18
+
19
+ expect(fsObj).toEqual({ "/deep/hello": "world" });
20
+ });
21
+
22
+ it("Writes deep files from root", async () => {
23
+ const fsObj = {};
24
+ const fs = new FileSystem(new ObjectFileSystemAdapter(fsObj));
25
+ await fs.writeFile("/root/deep/hello", "world");
26
+
27
+ expect(fsObj).toEqual({ "/root/deep/hello": "world" });
28
+ });
29
+
30
+ it("Writes files after cd", async () => {
31
+ const fsObj = {};
32
+ const fs = new FileSystem(new ObjectFileSystemAdapter(fsObj));
33
+ await fs.cd("deep");
34
+ await fs.writeFile("hello", "world");
35
+
36
+ expect(fsObj).toEqual({ "/deep/hello": "world" });
37
+ });
38
+ });
39
+
40
+ describe("directory", () => {
41
+ it("returns directory listing", async () => {
42
+ const fsObj = {
43
+ "/deep/hello": "world",
44
+ "/deep/bonjour": "monde",
45
+ "/other/file": "text",
46
+ };
47
+ const fs = new FileSystem(new ObjectFileSystemAdapter(fsObj));
48
+
49
+ const dir = await fs.readdir("deep");
50
+ expect(dir.sort()).toEqual(["bonjour", "hello"]);
51
+ });
52
+ });
53
+ });
package/src/fs.ts ADDED
@@ -0,0 +1,180 @@
1
+ // Treat localstorage as a file system
2
+ export type PathLike = string;
3
+ export interface Stats {
4
+ isDirectory(): boolean;
5
+ isFile(): boolean;
6
+ }
7
+
8
+ function join(...paths: string[]): string {
9
+ const pathParts: string[] = [];
10
+ for (const path of paths) {
11
+ for (const part of path.split("/")) {
12
+ switch (part) {
13
+ case "":
14
+ case ".":
15
+ break;
16
+ case "..":
17
+ pathParts.pop();
18
+ break;
19
+ default:
20
+ pathParts.push(part);
21
+ }
22
+ }
23
+ }
24
+ return "/" + pathParts.join("/");
25
+ }
26
+
27
+ interface FileSystemAdapter {
28
+ stat(path: PathLike): Promise<Stats>;
29
+ readdir(path: PathLike): Promise<string[]>;
30
+ copyFile(from: PathLike, to: PathLike): Promise<void>;
31
+ readFile(path: PathLike): Promise<string>;
32
+ writeFile(path: PathLike, contents: string): Promise<void>;
33
+ rm(path: PathLike): Promise<void>;
34
+ }
35
+
36
+ export class FileSystem implements FileSystemAdapter {
37
+ protected wd = "/";
38
+ protected stack: string[] = [];
39
+
40
+ constructor(protected adapter = new ObjectFileSystemAdapter()) {}
41
+
42
+ cwd(): string {
43
+ return this.wd;
44
+ }
45
+
46
+ cd(dir: string) {
47
+ this.wd = this.p(dir);
48
+ }
49
+
50
+ pushd(dir: string) {
51
+ this.stack.push(this.wd);
52
+ this.cd(dir);
53
+ }
54
+
55
+ popd() {
56
+ if (this.stack.length > 0) {
57
+ this.wd = this.stack.pop()!;
58
+ }
59
+ }
60
+
61
+ stat(path: PathLike): Promise<Stats> {
62
+ return this.adapter.stat(join(this.cwd(), path));
63
+ }
64
+
65
+ readdir(path: PathLike): Promise<string[]> {
66
+ return this.adapter.readdir(this.p(path) + "/");
67
+ }
68
+
69
+ copyFile(from: PathLike, to: PathLike): Promise<void> {
70
+ return this.adapter.copyFile(this.p(from), this.p(to));
71
+ }
72
+
73
+ readFile(path: PathLike): Promise<string> {
74
+ return this.adapter.readFile(this.p(path));
75
+ }
76
+
77
+ writeFile(path: PathLike, contents: string): Promise<void> {
78
+ return this.adapter.writeFile(this.p(path), contents);
79
+ }
80
+
81
+ rm(path: PathLike): Promise<void> {
82
+ return this.adapter.rm(this.p(path));
83
+ }
84
+
85
+ private p(path: PathLike): string {
86
+ return path[0] == "/" ? path : join(this.cwd(), path);
87
+ }
88
+ }
89
+
90
+ export class ObjectFileSystemAdapter implements FileSystemAdapter {
91
+ constructor(private fs: Record<string, string> = {}) {}
92
+
93
+ stat(path: PathLike): Promise<Stats> {
94
+ return new Promise((resolve, reject) => {
95
+ if (this.fs[path] != null) {
96
+ resolve({
97
+ isDirectory() {
98
+ return false;
99
+ },
100
+ isFile() {
101
+ return true;
102
+ },
103
+ });
104
+ } else {
105
+ reject();
106
+ }
107
+ });
108
+ }
109
+
110
+ readdir(path: PathLike): Promise<string[]> {
111
+ return new Promise((resolve) => {
112
+ let dir: string[] = [];
113
+ for (const filename of Object.keys(this.fs)) {
114
+ if (filename.startsWith(path)) {
115
+ const end = filename.indexOf("/", path.length + 1);
116
+ const basename = filename.substring(
117
+ path.length,
118
+ end == -1 ? undefined : end
119
+ );
120
+ dir.push(basename);
121
+ }
122
+ }
123
+ return resolve(dir);
124
+ });
125
+ }
126
+
127
+ copyFile(from: PathLike, to: PathLike): Promise<void> {
128
+ return new Promise((resolve) => {
129
+ this.fs[to] = this.fs[from];
130
+ resolve();
131
+ });
132
+ }
133
+
134
+ readFile(path: PathLike): Promise<string> {
135
+ return new Promise((resolve, reject) => {
136
+ let file = this.fs[path];
137
+ if (file === undefined) {
138
+ reject();
139
+ } else {
140
+ resolve(file);
141
+ }
142
+ });
143
+ }
144
+
145
+ writeFile(path: PathLike, contents: string): Promise<void> {
146
+ return new Promise((resolve) => {
147
+ this.fs[path] = contents;
148
+ resolve();
149
+ });
150
+ }
151
+
152
+ rm(path: PathLike): Promise<void> {
153
+ return new Promise((resolve) => {
154
+ delete this.fs[path];
155
+ resolve();
156
+ });
157
+ }
158
+ }
159
+
160
+ export class LocalStorageFileSystemAdapter extends ObjectFileSystemAdapter {
161
+ constructor() {
162
+ super(window.localStorage);
163
+ }
164
+ }
165
+
166
+ export interface Tree {
167
+ [k: string]: string | Tree;
168
+ }
169
+
170
+ export async function reset(fs: FileSystem, tree: Tree): Promise<void> {
171
+ for (const [path, file] of Object.entries(tree)) {
172
+ if (typeof file == "string") {
173
+ await fs.writeFile(path, file);
174
+ } else {
175
+ fs.cd(path);
176
+ await reset(fs, file);
177
+ fs.cd("..");
178
+ }
179
+ }
180
+ }
package/src/index.html CHANGED
@@ -3,12 +3,12 @@
3
3
  <head>
4
4
  <title>Jiffies Tests</title>
5
5
  <base href="/" />
6
- <link rel="stylesheet" href="/pico/pico-1.4.1.css" />
6
+ <link rel="stylesheet" href="/pico/pico.css?$enable-viewport=none" />
7
7
  </head>
8
8
  <body>
9
- <header id="menu"></header>
9
+ <header></header>
10
10
 
11
- <main class="container">
11
+ <main>
12
12
  <article id="test_output"></article>
13
13
  </main>
14
14
 
@@ -67,7 +67,7 @@
67
67
  }));
68
68
 
69
69
  document
70
- .getElementById("menu")
70
+ .querySelector("body > header")
71
71
  .appendChild(
72
72
  nav(
73
73
  ul(li(strong("Jiffy Apps"))),
package/src/log.ts CHANGED
@@ -45,17 +45,21 @@ export function getLogger(name: string): Logger {
45
45
  export const DEFAULT_LOGGER = getLogger("default");
46
46
 
47
47
  export function debug(message: Display, data?: {}) {
48
- DEFAULT_LOGGER.debug(message, data);
48
+ if (data) DEFAULT_LOGGER.debug(message, data);
49
+ else DEFAULT_LOGGER.debug(message);
49
50
  }
50
51
 
51
52
  export function info(message: Display, data?: {}) {
52
- DEFAULT_LOGGER.info(message, data);
53
+ if (data) DEFAULT_LOGGER.info(message, data);
54
+ else DEFAULT_LOGGER.info(message);
53
55
  }
54
56
 
55
57
  export function warn(message: Display, data?: {}) {
56
- DEFAULT_LOGGER.warn(message, data);
58
+ if (data) DEFAULT_LOGGER.warn(message, data);
59
+ else DEFAULT_LOGGER.warn(message);
57
60
  }
58
61
 
59
62
  export function error(message: Display, data?: {}) {
60
- DEFAULT_LOGGER.error(message, data);
63
+ if (data) DEFAULT_LOGGER.error(message, data);
64
+ else DEFAULT_LOGGER.error(message);
61
65
  }
@@ -0,0 +1,66 @@
1
+ // Config
2
+ // ––––––––––––––––––––
3
+
4
+ // Enable <header>, <main>, <footer> inside <body> as a container
5
+ $enable-semantic-container: true !default;
6
+
7
+ // Enable .container and .container-fluid
8
+ $enable-class-container: false !default;
9
+
10
+ // Enable a centered viewport for <header>, <main>, <footer> inside <body>
11
+ // Options are "all" to center all, "main" to only center main, and "none" to treat all as fluid.
12
+ $enable-viewport: "main" !default;
13
+
14
+ // Enable responsive spacings for <header>, <main>, <footer>, <section>, <article>
15
+ // Fixed spacings if disabled
16
+ $enable-responsive-spacings: true !default;
17
+
18
+ // Enable responsive typography
19
+ // Fixed root element size if disabled
20
+ $enable-responsive-typography: true !default;
21
+
22
+ // Enable .classes
23
+ // .classless version if disabled
24
+ $enable-classes: true !default;
25
+
26
+ // Enable .grid class
27
+ $enable-grid: true !default;
28
+
29
+ // Enable transitions
30
+ $enable-transitions: true !default;
31
+
32
+ // Enable overriding with !important
33
+ $enable-important: true !default;
34
+
35
+ // Responsive
36
+ // ––––––––––––––––––––
37
+
38
+ // xs: Extra small (portrait phones)
39
+ // sm: Small (landscape phones)
40
+ // md: Medium (tablets)
41
+ // lg: Large (desktops)
42
+ // xl: Extra large (large desktops, TVs)
43
+
44
+ // NOTE:
45
+ // To provide an easy and fine styling on each breakpoint
46
+ // we didn't use @each, @mixin or @include.
47
+ // That means you need to edit each CSS selector file to add a breakpoint
48
+
49
+ // Breakpoints
50
+ // 'null' disable the breakpoint
51
+ $breakpoints: (
52
+ xs: 0,
53
+ sm: 576px,
54
+ md: 768px,
55
+ lg: 992px,
56
+ xl: 1200px,
57
+ ) !default;
58
+
59
+ // Viewports
60
+ $viewports: (
61
+ // 'null' disable the viewport on a breakpoint
62
+ sm: 510px,
63
+ md: 700px,
64
+ lg: 920px,
65
+ xl: 1130px
66
+ ) !default;