docs: reorganize docs (#2658)

This commit is contained in:
Leo Kettmeir 2022-11-25 12:40:23 +01:00 committed by GitHub
parent 4d16c30f38
commit aba5017d43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
141 changed files with 4514 additions and 6593 deletions

View File

@ -1,63 +0,0 @@
# Usage
## Tar
```ts
import { Tar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
import { Buffer } from "https://deno.land/std@$STD_VERSION/io/buffer.ts";
import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
const tar = new Tar();
const content = new TextEncoder().encode("Deno.land");
await tar.append("deno.txt", {
reader: new Buffer(content),
contentSize: content.byteLength,
});
// Or specifying a filePath.
await tar.append("land.txt", {
filePath: "./land.txt",
});
// use tar.getReader() to read the contents.
const writer = await Deno.open("./out.tar", { write: true, create: true });
await copy(tar.getReader(), writer);
writer.close();
```
## Untar
```ts
import { Untar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
import { ensureFile } from "https://deno.land/std@$STD_VERSION/fs/ensure_file.ts";
import { ensureDir } from "https://deno.land/std@$STD_VERSION/fs/ensure_dir.ts";
import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
const reader = await Deno.open("./out.tar", { read: true });
const untar = new Untar(reader);
for await (const entry of untar) {
console.log(entry); // metadata
/*
fileName: "archive/deno.txt",
fileMode: 33204,
mtime: 1591657305,
uid: 0,
gid: 0,
size: 24400,
type: 'file'
*/
if (entry.type === "directory") {
await ensureDir(entry.fileName);
continue;
}
await ensureFile(entry.fileName);
const file = await Deno.open(entry.fileName, { write: true });
// <entry> is a reader.
await copy(entry, file);
}
reader.close();
```

View File

@ -33,61 +33,6 @@
* Provides a `Tar` and `Untar` classes for compressing and decompressing
* arbitrary data.
*
* ## Examples
*
* ### Tar
*
* ```ts
* import { Tar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
* import { Buffer } from "https://deno.land/std@$STD_VERSION/io/buffer.ts";
* import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
*
* const tar = new Tar();
* const content = new TextEncoder().encode("Deno.land");
* await tar.append("deno.txt", {
* reader: new Buffer(content),
* contentSize: content.byteLength,
* });
*
* // Or specifying a filePath.
* await tar.append("land.txt", {
* filePath: "./land.txt",
* });
*
* // use tar.getReader() to read the contents.
*
* const writer = await Deno.open("./out.tar", { write: true, create: true });
* await copy(tar.getReader(), writer);
* writer.close();
* ```
*
* ### Untar
*
* ```ts
* import { Untar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
* import { ensureFile } from "https://deno.land/std@$STD_VERSION/fs/ensure_file.ts";
* import { ensureDir } from "https://deno.land/std@$STD_VERSION/fs/ensure_dir.ts";
* import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
*
* const reader = await Deno.open("./out.tar", { read: true });
* const untar = new Untar(reader);
*
* for await (const entry of untar) {
* console.log(entry); // metadata
*
* if (entry.type === "directory") {
* await ensureDir(entry.fileName);
* continue;
* }
*
* await ensureFile(entry.fileName);
* const file = await Deno.open(entry.fileName, { write: true });
* // <entry> is a reader.
* await copy(entry, file);
* }
* reader.close();
* ```
*
* @module
*/
@ -368,6 +313,31 @@ interface TarEntry extends TarMeta {}
/**
* A class to create a tar archive
*
* @example
* ```ts
* import { Tar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
* import { Buffer } from "https://deno.land/std@$STD_VERSION/io/buffer.ts";
* import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
*
* const tar = new Tar();
* const content = new TextEncoder().encode("Deno.land");
* await tar.append("deno.txt", {
* reader: new Buffer(content),
* contentSize: content.byteLength,
* });
*
* // Or specifying a filePath.
* await tar.append("land.txt", {
* filePath: "./land.txt",
* });
*
* // use tar.getReader() to read the contents.
*
* const writer = await Deno.open("./out.tar", { write: true, create: true });
* await copy(tar.getReader(), writer);
* writer.close();
* ```
*/
export class Tar {
data: TarDataWithSource[];
@ -592,6 +562,32 @@ class TarEntry implements Reader {
/**
* A class to extract a tar archive
*
* @example
* ```ts
* import { Untar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
* import { ensureFile } from "https://deno.land/std@$STD_VERSION/fs/ensure_file.ts";
* import { ensureDir } from "https://deno.land/std@$STD_VERSION/fs/ensure_dir.ts";
* import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
*
* const reader = await Deno.open("./out.tar", { read: true });
* const untar = new Untar(reader);
*
* for await (const entry of untar) {
* console.log(entry); // metadata
*
* if (entry.type === "directory") {
* await ensureDir(entry.fileName);
* continue;
* }
*
* await ensureFile(entry.fileName);
* const file = await Deno.open(entry.fileName, { write: true });
* // <entry> is a reader.
* await copy(entry, file);
* }
* reader.close();
* ```
*/
export class Untar {
reader: Reader;

View File

@ -1,238 +0,0 @@
# async
async is a module to provide help with asynchronous tasks.
# Usage
The following functions and class are exposed in `mod.ts`:
## abortable
The `abortable` is a wrapper function that makes `Promise` and `AsyncIterable`
cancelable.
For example, in the case of `Promise`, it looks like this
```typescript
import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
const p = delay(1000);
const c = new AbortController();
setTimeout(() => c.abort(), 100);
// Below throws `DOMException` after 100 ms
await abortable(p, c.signal);
```
and for `AsyncIterable` as follows
```typescript
import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
const p = async function* () {
yield "Hello";
await delay(1000);
yield "World";
};
const c = new AbortController();
setTimeout(() => c.abort(), 100);
// Below throws `DOMException` after 100 ms
// and items become `["Hello"]`
const items: string[] = [];
for await (const item of abortable(p(), c.signal)) {
items.push(item);
}
```
## abortablePromise
`abortablePromise` takes the promise and `AbortSignal` and returns the
cancelable version of the promise.
```typescript
import { abortablePromise } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
const request = fetch("https://example.com");
const c = new AbortController();
setTimeout(() => c.abort(), 100);
const p = abortablePromise(request, c.signal);
// The below throws if the request didn't resolve in 100ms
await p;
```
## abortableAsyncIterable
`abortableAsyncIterable` takes the async iterable and `AbortSignal` and returns
the cancelable version of the async iterable.
```typescript
import { abortableAsyncIterable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
const p = async function* () {
yield "Hello";
await delay(1000);
yield "World";
};
const c = new AbortController();
setTimeout(() => c.abort(), 100);
// Below throws `DOMException` after 100 ms
// and items become `["Hello"]`
const items: string[] = [];
for await (const item of abortableAsyncIterable(p(), c.signal)) {
items.push(item);
}
```
## debounce
Debounces a given function by a given time.
```typescript
import { debounce } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
const p = debounce(
(value: string) =>
console.log("Function debounced after 200ms with %s", value),
200,
);
p("foo");
p("bar");
p("baz");
// wait 200ms ...
// output: Function debounced after 200ms with baz
```
## deferred
Create a Promise with the `reject` and `resolve` functions.
```typescript
import { deferred } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
const p = deferred<number>();
// ...
p.resolve(42);
```
## delay
Resolve a Promise after a given amount of milliseconds.
```typescript
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
// ...
const delayedPromise = delay(100);
const result = await delayedPromise;
// ...
```
To allow the process to continue to run as long as the timer exists. Requires
`--unstable` flag.
```typescript
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
// ...
await delay(100, { persistent: false });
// ...
```
## MuxAsyncIterator
The MuxAsyncIterator class multiplexes multiple async iterators into a single
stream.
The class makes an assumption that the final result (the value returned and not
yielded from the iterator) does not matter. If there is any result, it is
discarded.
```typescript
import { MuxAsyncIterator } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
async function* gen123(): AsyncIterableIterator<number> {
yield 1;
yield 2;
yield 3;
}
async function* gen456(): AsyncIterableIterator<number> {
yield 4;
yield 5;
yield 6;
}
const mux = new MuxAsyncIterator<number>();
mux.add(gen123());
mux.add(gen456());
for await (const value of mux) {
// ...
}
// ..
```
## pooledMap
Transform values from an (async) iterable into another async iterable. The
transforms are done concurrently, with a max concurrency defined by the
poolLimit.
```typescript
import { pooledMap } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
const results = pooledMap(
2,
[1, 2, 3],
(i) => new Promise((r) => setTimeout(() => r(i), 1000)),
);
for await (const value of results) {
// ...
}
```
## tee
Branches the given async iterable into the n branches.
```typescript
import { tee } from "https://deno.land/std@$STD_VERSION/async/tee.ts";
const gen = async function* gen() {
yield 1;
yield 2;
yield 3;
};
const [branch1, branch2] = tee(gen());
for await (const n of branch1) {
console.log(n); // => 1, 2, 3
}
for await (const n of branch2) {
console.log(n); // => 1, 2, 3
}
```
## deadline
Create a promise which will be rejected with `DeadlineError` when a given delay
is exceeded.
```typescript
import { deadline } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
const delayedPromise = delay(1000);
// Below throws `DeadlineError` after 10 ms
const result = await deadline(delayedPromise, 10);
```

View File

@ -1,8 +1,47 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { deferred } from "./deferred.ts";
/** Make Promise or AsyncIterable abortable with the given signal. */
/**
* Make Promise abortable with the given signal.
*
* @example
* ```typescript
* import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
* import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
* const p = delay(1000);
* const c = new AbortController();
* setTimeout(() => c.abort(), 100);
*
* // Below throws `DOMException` after 100 ms
* await abortable(p, c.signal);
* ```
*/
export function abortable<T>(p: Promise<T>, signal: AbortSignal): Promise<T>;
/**
* Make AsyncIterable abortable with the given signal.
*
* @example
* ```typescript
* import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
* import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
* const p = async function* () {
* yield "Hello";
* await delay(1000);
* yield "World";
* };
* const c = new AbortController();
* setTimeout(() => c.abort(), 100);
*
* // Below throws `DOMException` after 100 ms
* // and items become `["Hello"]`
* const items: string[] = [];
* for await (const item of abortable(p(), c.signal)) {
* items.push(item);
* }
* ```
*/
export function abortable<T>(
p: AsyncIterable<T>,
signal: AbortSignal,
@ -18,7 +57,24 @@ export function abortable<T>(
}
}
/** Make Promise abortable with the given signal. */
/**
* Make Promise abortable with the given signal.
*
* @example
* ```typescript
* import { abortablePromise } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
* const request = fetch("https://example.com");
*
* const c = new AbortController();
* setTimeout(() => c.abort(), 100);
*
* const p = abortablePromise(request, c.signal);
*
* // The below throws if the request didn't resolve in 100ms
* await p;
* ```
*/
export function abortablePromise<T>(
p: Promise<T>,
signal: AbortSignal,
@ -37,7 +93,30 @@ export function abortablePromise<T>(
]);
}
/** Make AsyncIterable abortable with the given signal. */
/**
* Make AsyncIterable abortable with the given signal.
*
* @example
* ```typescript
* import { abortableAsyncIterable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
* import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
* const p = async function* () {
* yield "Hello";
* await delay(1000);
* yield "World";
* };
* const c = new AbortController();
* setTimeout(() => c.abort(), 100);
*
* // Below throws `DOMException` after 100 ms
* // and items become `["Hello"]`
* const items: string[] = [];
* for await (const item of abortableAsyncIterable(p(), c.signal)) {
* items.push(item);
* }
* ```
*/
export async function* abortableAsyncIterable<T>(
p: AsyncIterable<T>,
signal: AbortSignal,

View File

@ -11,7 +11,17 @@ export class DeadlineError extends Error {
}
/**
* Create a promise which will be rejected with DeadlineError when a given delay is exceeded.
* Create a promise which will be rejected with {@linkcode DeadlineError} when a given delay is exceeded.
*
* @example
* ```typescript
* import { deadline } from "https://deno.land/std@$STD_VERSION/async/deadline.ts";
* import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
*
* const delayedPromise = delay(1000);
* // Below throws `DeadlineError` after 10 ms
* const result = await deadline(delayedPromise, 10);
* ```
*/
export function deadline<T>(p: Promise<T>, delay: number): Promise<T> {
const d = deferred<never>();

View File

@ -12,7 +12,7 @@ export interface DebouncedFunction<T extends Array<unknown>> {
clear(): void;
/** Clears the debounce timeout and calls the debounced function immediately. */
flush(): void;
/** Returns a boolean wether a debounce call is pending or not. */
/** Returns a boolean whether a debounce call is pending or not. */
readonly pending: boolean;
}
@ -22,6 +22,7 @@ export interface DebouncedFunction<T extends Array<unknown>> {
* again before the timeout expires, the previous call will be
* aborted.
*
* @example
* ```
* import { debounce } from "https://deno.land/std@$STD_VERSION/async/debounce.ts";
*
@ -34,6 +35,8 @@ export interface DebouncedFunction<T extends Array<unknown>> {
* for await (const event of Deno.watchFs("./")) {
* log(event);
* }
* // wait 200ms ...
* // output: Function debounced after 200ms with baz
* ```
*
* @param fn The function to debounce.

View File

@ -13,15 +13,17 @@ export interface Deferred<T> extends Promise<T> {
reject(reason?: any): void;
}
/** Creates a Promise with the `reject` and `resolve` functions
* placed as methods on the promise object itself. It allows you to do:
/**
* Creates a Promise with the `reject` and `resolve` functions placed as methods
* on the promise object itself.
*
* ```ts
* import { deferred } from "https://deno.land/std@$STD_VERSION/async/deferred.ts";
* @example
* ```typescript
* import { deferred } from "https://deno.land/std@$STD_VERSION/async/deferred.ts";
*
* const p = deferred<number>();
* // ...
* p.resolve(42);
* const p = deferred<number>();
* // ...
* p.resolve(42);
* ```
*/
export function deferred<T>(): Deferred<T> {

View File

@ -2,12 +2,40 @@
// This module is browser compatible.
export interface DelayOptions {
/** Signal used to abort the delay. */
signal?: AbortSignal;
/** Indicates whether the process should continue to run as long as the timer exists. This is `true` by default. */
/** Indicates whether the process should continue to run as long as the timer exists.
*
* @default {true}
*/
persistent?: boolean;
}
/* Resolves after the given number of milliseconds. */
/**
* Resolve a Promise after a given amount of milliseconds.
*
* @example
*
* ```typescript
* import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
*
* // ...
* const delayedPromise = delay(100);
* const result = await delayedPromise;
* // ...
* ```
*
* To allow the process to continue to run as long as the timer exists. Requires
* `--unstable` flag.
*
* ```typescript
* import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
*
* // ...
* await delay(100, { persistent: false });
* // ...
* ```
*/
export function delay(ms: number, options: DelayOptions = {}): Promise<void> {
const { signal, persistent } = options;
if (signal?.aborted) {

View File

@ -8,10 +8,36 @@ interface TaggedYieldedValue<T> {
value: T;
}
/** The MuxAsyncIterator class multiplexes multiple async iterators into a
* single stream. It currently makes an assumption:
* - The final result (the value returned and not yielded from the iterator)
* does not matter; if there is any, it is discarded.
/**
* The MuxAsyncIterator class multiplexes multiple async iterators into a single
* stream. It currently makes an assumption that the final result (the value
* returned and not yielded from the iterator) does not matter; if there is any
* result, it is discarded.
*
* @example
* ```typescript
* import { MuxAsyncIterator } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
* async function* gen123(): AsyncIterableIterator<number> {
* yield 1;
* yield 2;
* yield 3;
* }
*
* async function* gen456(): AsyncIterableIterator<number> {
* yield 4;
* yield 5;
* yield 6;
* }
*
* const mux = new MuxAsyncIterator<number>();
* mux.add(gen123());
* mux.add(gen456());
* for await (const value of mux) {
* // ...
* }
* // ..
* ```
*/
export class MuxAsyncIterator<T> implements AsyncIterable<T> {
#iteratorCount = 0;

View File

@ -12,6 +12,21 @@ export const ERROR_WHILE_MAPPING_MESSAGE = "Threw while mapping.";
* yielded on success. After that, the rejections among them are gathered and
* thrown by the iterator in an `AggregateError`.
*
* @example
* ```typescript
* import { pooledMap } from "https://deno.land/std@$STD_VERSION/async/pool.ts";
*
* const results = pooledMap(
* 2,
* [1, 2, 3],
* (i) => new Promise((r) => setTimeout(() => r(i), 1000)),
* );
*
* for await (const value of results) {
* // ...
* }
* ```
*
* @param poolLimit The maximum count of items being processed concurrently.
* @param array The input array for mapping.
* @param iteratorFn The function to call for every item of the array.

View File

@ -49,26 +49,25 @@ class Queue<T> {
/**
* Branches the given async iterable into the n branches.
*
* Example:
*
* @example
* ```ts
* import { tee } from "https://deno.land/std@$STD_VERSION/async/tee.ts";
* import { tee } from "https://deno.land/std@$STD_VERSION/async/tee.ts";
*
* const gen = async function* gen() {
* yield 1;
* yield 2;
* yield 3;
* }
* const gen = async function* gen() {
* yield 1;
* yield 2;
* yield 3;
* };
*
* const [branch1, branch2] = tee(gen());
* const [branch1, branch2] = tee(gen());
*
* for await (const n of branch1) {
* console.log(n); // => 1, 2, 3
* }
* for await (const n of branch1) {
* console.log(n); // => 1, 2, 3
* }
*
* for await (const n of branch2) {
* console.log(n); // => 1, 2, 3
* }
* for await (const n of branch2) {
* console.log(n); // => 1, 2, 3
* }
* ```
*/
export function tee<T, N extends number = 2>(

View File

@ -1,8 +0,0 @@
# Bytes
The bytes module provides helper functions to manipulate `Uint8Array` byte
slices that are not included on the `Uint8Array` prototype.
View the
[documentation](https://doc.deno.land/https://deno.land/std@$STD_VERSION/bytes/mod.ts)
for details information.

File diff suppressed because it is too large Load Diff

View File

@ -4,29 +4,33 @@
import { mapEntries } from "./map_entries.ts";
/**
* Applies the given aggregator to each group in the given Grouping, returning the results together with the respective group keys
* Applies the given aggregator to each group in the given grouping, returning the
* results together with the respective group keys
*
* @example
* ```ts
* import { aggregateGroups } from "https://deno.land/std@$STD_VERSION/collections/aggregate_groups.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const foodProperties = {
* 'Curry': [ 'spicy', 'vegan' ],
* 'Omelette': [ 'creamy', 'vegetarian' ],
* }
* const descriptions = aggregateGroups(foodProperties,
* (current, key, first, acc) => {
* if (first)
* return `${key} is ${current}`
* "Curry": ["spicy", "vegan"],
* "Omelette": ["creamy", "vegetarian"],
* };
* const descriptions = aggregateGroups(
* foodProperties,
* (current, key, first, acc) => {
* if (first) {
* return `${key} is ${current}`;
* }
*
* return `${acc} and ${current}`
* },
* )
* return `${acc} and ${current}`;
* },
* );
*
* assertEquals(descriptions, {
* 'Curry': 'Curry is spicy and vegan',
* 'Omelette': 'Omelette is creamy and vegetarian',
* })
* "Curry": "Curry is spicy and vegan",
* "Omelette": "Omelette is creamy and vegetarian",
* });
* ```
*/
export function aggregateGroups<T, A>(

View File

@ -2,28 +2,27 @@
// This module is browser compatible.
/**
* Transforms the given array into a Record, extracting the key of each element using the given selector.
* If the selector produces the same key for multiple elements, the latest one will be used (overriding the
* ones before it).
*
* Example:
* Transforms the given array into a Record, extracting the key of each element
* using the given selector. If the selector produces the same key for multiple
* elements, the latest one will be used (overriding the ones before it).
*
* @example
* ```ts
* import { associateBy } from "https://deno.land/std@$STD_VERSION/collections/associate_by.ts"
* import { associateBy } from "https://deno.land/std@$STD_VERSION/collections/associate_by.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const users = [
* { id: 'a2e', userName: 'Anna' },
* { id: '5f8', userName: 'Arnold' },
* { id: 'd2c', userName: 'Kim' },
* ]
* const usersById = associateBy(users, it => it.id)
* { id: "a2e", userName: "Anna" },
* { id: "5f8", userName: "Arnold" },
* { id: "d2c", userName: "Kim" },
* ];
* const usersById = associateBy(users, (it) => it.id);
*
* assertEquals(usersById, {
* 'a2e': { id: 'a2e', userName: 'Anna' },
* '5f8': { id: '5f8', userName: 'Arnold' },
* 'd2c': { id: 'd2c', userName: 'Kim' },
* })
* "a2e": { id: "a2e", userName: "Anna" },
* "5f8": { id: "5f8", userName: "Arnold" },
* "d2c": { id: "d2c", userName: "Kim" },
* });
* ```
*/
export function associateBy<T>(

View File

@ -2,24 +2,23 @@
// This module is browser compatible.
/**
* Builds a new Record using the given array as keys and choosing a value for each
* key using the given selector. If any of two pairs would have the same value
* the latest on will be used (overriding the ones before it).
*
* Example:
* Builds a new Record using the given array as keys and choosing a value for
* each key using the given selector. If any of two pairs would have the same
* value the latest on will be used (overriding the ones before it).
*
* @example
* ```ts
* import { associateWith } from "https://deno.land/std@$STD_VERSION/collections/associate_with.ts"
* import { associateWith } from "https://deno.land/std@$STD_VERSION/collections/associate_with.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const names = [ 'Kim', 'Lara', 'Jonathan' ]
* const namesToLength = associateWith(names, it => it.length)
* const names = ["Kim", "Lara", "Jonathan"];
* const namesToLength = associateWith(names, (it) => it.length);
*
* assertEquals(namesToLength, {
* 'Kim': 3,
* 'Lara': 4,
* 'Jonathan': 8,
* })
* "Kim": 3,
* "Lara": 4,
* "Jonathan": 8,
* });
* ```
*/
export function associateWith<T>(

View File

@ -17,8 +17,46 @@ function getParentIndex(index: number) {
}
/**
* A priority queue implemented with a binary heap. The heap is in decending order by default,
* using JavaScript's built in comparison operators to sort the values.
* A priority queue implemented with a binary heap. The heap is in descending
* order by default, using JavaScript's built-in comparison operators to sort
* the values.
*
* | Method | Average Case | Worst Case |
* | ----------- | ------------ | ---------- |
* | peek() | O(1) | O(1) |
* | pop() | O(log n) | O(log n) |
* | push(value) | O(1) | O(log n) |
*
* @example
* ```ts
* import {
* ascend,
* BinaryHeap,
* descend,
* } from "https://deno.land/std@$STD_VERSION/collections/binary_heap.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const maxHeap = new BinaryHeap<number>();
* maxHeap.push(4, 1, 3, 5, 2);
* assertEquals(maxHeap.peek(), 5);
* assertEquals(maxHeap.pop(), 5);
* assertEquals([...maxHeap], [4, 3, 2, 1]);
* assertEquals([...maxHeap], []);
*
* const minHeap = new BinaryHeap<number>(ascend);
* minHeap.push(4, 1, 3, 5, 2);
* assertEquals(minHeap.peek(), 1);
* assertEquals(minHeap.pop(), 1);
* assertEquals([...minHeap], [2, 3, 4, 5]);
* assertEquals([...minHeap], []);
*
* const words = new BinaryHeap<string>((a, b) => descend(a.length, b.length));
* words.push("truck", "car", "helicopter", "tank");
* assertEquals(words.peek(), "helicopter");
* assertEquals(words.pop(), "helicopter");
* assertEquals([...words], ["truck", "tank", "car"]);
* assertEquals([...words], []);
* ```
*/
export class BinaryHeap<T> implements Iterable<T> {
#data: T[] = [];

View File

@ -7,7 +7,84 @@ export * from "./_comparators.ts";
/**
* An unbalanced binary search tree. The values are in ascending order by default,
* using JavaScript's built in comparison operators to sort the values.
* using JavaScript's built-in comparison operators to sort the values.
*
* For performance, it's recommended that you use a self-balancing binary search
* tree instead of this one unless you are extending this to create a
* self-balancing tree. See RedBlackTree for an example of how BinarySearchTree
* can be extended to create a self-balancing binary search tree.
*
* | Method | Average Case | Worst Case |
* | ------------- | ------------ | ---------- |
* | find(value) | O(log n) | O(n) |
* | insert(value) | O(log n) | O(n) |
* | remove(value) | O(log n) | O(n) |
* | min() | O(log n) | O(n) |
* | max() | O(log n) | O(n) |
*
* @example
* ```ts
* import {
* ascend,
* BinarySearchTree,
* descend,
* } from "https://deno.land/std@$STD_VERSION/collections/binary_search_tree.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const values = [3, 10, 13, 4, 6, 7, 1, 14];
* const tree = new BinarySearchTree<number>();
* values.forEach((value) => tree.insert(value));
* assertEquals([...tree], [1, 3, 4, 6, 7, 10, 13, 14]);
* assertEquals(tree.min(), 1);
* assertEquals(tree.max(), 14);
* assertEquals(tree.find(42), null);
* assertEquals(tree.find(7), 7);
* assertEquals(tree.remove(42), false);
* assertEquals(tree.remove(7), true);
* assertEquals([...tree], [1, 3, 4, 6, 10, 13, 14]);
*
* const invertedTree = new BinarySearchTree<number>(descend);
* values.forEach((value) => invertedTree.insert(value));
* assertEquals([...invertedTree], [14, 13, 10, 7, 6, 4, 3, 1]);
* assertEquals(invertedTree.min(), 14);
* assertEquals(invertedTree.max(), 1);
* assertEquals(invertedTree.find(42), null);
* assertEquals(invertedTree.find(7), 7);
* assertEquals(invertedTree.remove(42), false);
* assertEquals(invertedTree.remove(7), true);
* assertEquals([...invertedTree], [14, 13, 10, 6, 4, 3, 1]);
*
* const words = new BinarySearchTree<string>((a, b) =>
* ascend(a.length, b.length) || ascend(a, b)
* );
* ["truck", "car", "helicopter", "tank", "train", "suv", "semi", "van"]
* .forEach((value) => words.insert(value));
* assertEquals([...words], [
* "car",
* "suv",
* "van",
* "semi",
* "tank",
* "train",
* "truck",
* "helicopter",
* ]);
* assertEquals(words.min(), "car");
* assertEquals(words.max(), "helicopter");
* assertEquals(words.find("scooter"), null);
* assertEquals(words.find("tank"), "tank");
* assertEquals(words.remove("scooter"), false);
* assertEquals(words.remove("tank"), true);
* assertEquals([...words], [
* "car",
* "suv",
* "van",
* "semi",
* "train",
* "truck",
* "helicopter",
* ]);
* ```
*/
export class BinarySearchTree<T> implements Iterable<T> {
protected root: BinarySearchNode<T> | null = null;

View File

@ -2,22 +2,32 @@
// This module is browser compatible.
/**
* Splits the given array into chunks of the given size and returns them
*
* Example:
* Splits the given array into chunks of the given size and returns them.
*
* @example
* ```ts
* import { chunk } from "https://deno.land/std@$STD_VERSION/collections/chunk.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const words = [ 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consetetur', 'sadipscing' ]
* const chunks = chunk(words, 3)
* const words = [
* "lorem",
* "ipsum",
* "dolor",
* "sit",
* "amet",
* "consetetur",
* "sadipscing",
* ];
* const chunks = chunk(words, 3);
*
* assertEquals(chunks, [
* [ 'lorem', 'ipsum', 'dolor' ],
* [ 'sit', 'amet', 'consetetur' ],
* [ 'sadipscing' ],
* ])
* assertEquals(
* chunks,
* [
* ["lorem", "ipsum", "dolor"],
* ["sit", "amet", "consetetur"],
* ["sadipscing"],
* ],
* );
* ```
*/
export function chunk<T>(array: readonly T[], size: number): T[][] {

View File

@ -8,23 +8,22 @@ import { filterInPlace } from "./_utils.ts";
const { hasOwn } = Object;
/**
* Merges the two given Records, recursively merging any nested Records with
* the second collection overriding the first in case of conflict
* Merges the two given Records, recursively merging any nested Records with the
* second collection overriding the first in case of conflict
*
* For arrays, maps and sets, a merging strategy can be specified to either
* "replace" values, or "merge" them instead.
* Use "includeNonEnumerable" option to include non enumerable properties too.
*
* Example:
* `replace` values, or `merge` them instead. Use `includeNonEnumerable` option
* to include non-enumerable properties too.
*
* @example
* ```ts
* import { deepMerge } from "https://deno.land/std@$STD_VERSION/collections/deep_merge.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const a = {foo: true}
* const b = {foo: {bar: true}}
* const a = { foo: true };
* const b = { foo: { bar: true } };
*
* assertEquals(deepMerge(a, b), {foo: {bar: true}});
* assertEquals(deepMerge(a, b), { foo: { bar: true } });
* ```
*/
export function deepMerge<

View File

@ -2,18 +2,18 @@
// This module is browser compatible.
/**
* Returns all distinct elements in the given array, preserving order by first occurrence
*
* Example:
* Returns all distinct elements in the given array, preserving order by first
* occurrence.
*
* @example
* ```ts
* import { distinct } from "https://deno.land/std@$STD_VERSION/collections/distinct.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const numbers = [ 3, 2, 5, 2, 5 ]
* const distinctNumbers = distinct(numbers)
* const numbers = [3, 2, 5, 2, 5];
* const distinctNumbers = distinct(numbers);
*
* assertEquals(distinctNumbers, [ 3, 2, 5 ])
* assertEquals(distinctNumbers, [3, 2, 5]);
* ```
*/
export function distinct<T>(array: readonly T[]): T[] {

View File

@ -2,18 +2,18 @@
// This module is browser compatible.
/**
* Returns all elements in the given array that produce a distinct value using the given selector, preserving order by first occurrence
*
* Example:
* Returns all elements in the given array that produce a distinct value using
* the given selector, preserving order by first occurrence.
*
* @example
* ```ts
* import { distinctBy } from "https://deno.land/std@$STD_VERSION/collections/distinct_by.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const names = [ 'Anna', 'Kim', 'Arnold', 'Kate' ]
* const exampleNamesByFirstLetter = distinctBy(names, it => it.charAt(0))
* const names = ["Anna", "Kim", "Arnold", "Kate"];
* const exampleNamesByFirstLetter = distinctBy(names, (it) => it.charAt(0));
*
* assertEquals(exampleNamesByFirstLetter, [ 'Anna', 'Kim' ])
* assertEquals(exampleNamesByFirstLetter, ["Anna", "Kim"]);
* ```
*/
export function distinctBy<T, D>(

View File

@ -5,18 +5,18 @@
* Returns a new array that drops all elements in the given collection until the
* last element that does not match the given predicate
*
* Example:
* @example
* ```ts
* import { dropLastWhile } from "https://deno.land/std@$STD_VERSION/collections/drop_last_while.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const numbers = [22, 30, 44];
*
* const notFortyFour = dropLastWhile(numbers, i => i != 44);
* const notFortyFour = dropLastWhile(numbers, (i) => i != 44);
*
* assertEquals(
* notFortyFour,
* [22, 30]
* [22, 30],
* );
* ```
*/

View File

@ -3,18 +3,17 @@
/**
* Returns a new array that drops all elements in the given collection until the
* first element that does not match the given predicate
*
* Example:
* first element that does not match the given predicate.
*
* @example
* ```ts
* import { dropWhile } from "https://deno.land/std@$STD_VERSION/collections/drop_while.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const numbers = [ 3, 2, 5, 2, 5 ]
* const dropWhileNumbers = dropWhile(numbers, i => i !== 2)
* const numbers = [3, 2, 5, 2, 5];
* const dropWhileNumbers = dropWhile(numbers, (i) => i !== 2);
*
* assertEquals(dropWhileNumbers, [2, 5, 2, 5 ])
* assertEquals(dropWhileNumbers, [2, 5, 2, 5]);
* ```
*/
export function dropWhile<T>(

View File

@ -2,26 +2,30 @@
// This module is browser compatible.
/**
* Returns a new record with all entries of the given record except the ones that do not match the given predicate
*
* Example:
* Returns a new record with all entries of the given record except the ones
* that do not match the given predicate.
*
* @example
* ```ts
* import { filterEntries } from "https://deno.land/std@$STD_VERSION/collections/filter_entries.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const menu = {
* 'Salad': 11,
* 'Soup': 8,
* 'Pasta': 13,
* "Salad": 11,
* "Soup": 8,
* "Pasta": 13,
* } as const;
* const myOptions = filterEntries(menu,
* ([ item, price ]) => item !== 'Pasta' && price < 10,
* )
* const myOptions = filterEntries(
* menu,
* ([item, price]) => item !== "Pasta" && price < 10,
* );
*
* assertEquals(myOptions, {
* 'Soup': 8,
* })
* assertEquals(
* myOptions,
* {
* "Soup": 8,
* },
* );
* ```
*/
export function filterEntries<T>(

View File

@ -2,25 +2,28 @@
// This module is browser compatible.
/**
* Returns a new record with all entries of the given record except the ones that have a key that does not match the given predicate
*
* Example:
* Returns a new record with all entries of the given record except the ones that
* have a key that does not match the given predicate.
*
* @example
* ```ts
* import { filterKeys } from "https://deno.land/std@$STD_VERSION/collections/filter_keys.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const menu = {
* 'Salad': 11,
* 'Soup': 8,
* 'Pasta': 13,
* }
* const menuWithoutSalad = filterKeys(menu, it => it !== 'Salad')
* "Salad": 11,
* "Soup": 8,
* "Pasta": 13,
* };
* const menuWithoutSalad = filterKeys(menu, (it) => it !== "Salad");
*
* assertEquals(menuWithoutSalad, {
* 'Soup': 8,
* 'Pasta': 13,
* })
* assertEquals(
* menuWithoutSalad,
* {
* "Soup": 8,
* "Pasta": 13,
* },
* );
* ```
*/
export function filterKeys<T>(

View File

@ -2,27 +2,28 @@
// This module is browser compatible.
/**
* Returns a new record with all entries of the given record except the ones that have a value that does not match the given predicate
*
* Example:
* Returns a new record with all entries of the given record except the ones
* that have a value that does not match the given predicate.
*
* @example
* ```ts
* import { filterValues } from "https://deno.land/std@$STD_VERSION/collections/filter_values.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* type Person = { age: number };
*
* const people: Record<string, Person> = {
* 'Arnold': { age: 37 },
* 'Sarah': { age: 7 },
* 'Kim': { age: 23 },
* const people = {
* "Arnold": 37,
* "Sarah": 7,
* "Kim": 23,
* };
* const adults = filterValues(people, it => it.age >= 18)
* const adults = filterValues(people, (it) => it >= 18);
*
* assertEquals(adults, {
* 'Arnold': { age: 37 },
* 'Kim': { age: 23 },
* })
* assertEquals(
* adults,
* {
* "Arnold": 37,
* "Kim": 23,
* },
* );
* ```
*/
export function filterValues<T>(

View File

@ -2,18 +2,18 @@
// This module is browser compatible.
/**
* Returns an element if and only if that element is the only one matching the given condition. Returns `undefined` otherwise.
*
* Example:
* Returns an element if and only if that element is the only one matching the
* given condition. Returns `undefined` otherwise.
*
* @example
* ```ts
* import { findSingle } from "https://deno.land/std@$STD_VERSION/collections/find_single.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const bookings = [
* { month: 'January', active: false },
* { month: 'March', active: false },
* { month: 'June', active: true },
* { month: "January", active: false },
* { month: "March", active: false },
* { month: "June", active: true },
* ];
* const activeBooking = findSingle(bookings, (it) => it.active);
* const inactiveBooking = findSingle(bookings, (it) => !it.active);

View File

@ -2,23 +2,23 @@
// This module is browser compatible.
/**
* Applies the given selector to elements in the given array until a value is produced that is neither `null` nor `undefined` and returns that value
* Returns `undefined` if no such value is produced
*
* Example:
* Applies the given selector to elements in the given array until a value is
* produced that is neither `null` nor `undefined` and returns that value.
* Returns `undefined` if no such value is produced.
*
* @example
* ```ts
* import { firstNotNullishOf } from "https://deno.land/std@$STD_VERSION/collections/first_not_nullish_of.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const tables = [
* { number: 11, order: null },
* { number: 12, order: 'Soup' },
* { number: 13, order: 'Salad' },
* ]
* const nextOrder = firstNotNullishOf(tables, it => it.order)
* { number: 11, order: null },
* { number: 12, order: "Soup" },
* { number: 13, order: "Salad" },
* ];
* const nextOrder = firstNotNullishOf(tables, (it) => it.order);
*
* assertEquals(nextOrder, 'Soup')
* assertEquals(nextOrder, "Soup");
* ```
*/
export function firstNotNullishOf<T, O>(

View File

@ -2,30 +2,29 @@
// This module is browser compatible.
/**
* Applies the given selector to each element in the given array, returning a Record containing the results as keys
* and all values that produced that key as values.
*
* Example:
* Applies the given selector to each element in the given array, returning a
* Record containing the results as keys and all values that produced that key
* as values.
*
* @example
* ```ts
* import { groupBy } from "https://deno.land/std@$STD_VERSION/collections/group_by.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* type Person = {
* name: string;
* };
*
* const people: Person[] = [
* { name: 'Anna' },
* { name: 'Arnold' },
* { name: 'Kim' },
* const people = [
* { name: "Anna" },
* { name: "Arnold" },
* { name: "Kim" },
* ];
* const peopleByFirstLetter = groupBy(people, it => it.name.charAt(0))
* const peopleByFirstLetter = groupBy(people, (it) => it.name.charAt(0));
*
* assertEquals(peopleByFirstLetter, {
* 'A': [ { name: 'Anna' }, { name: 'Arnold' } ],
* 'K': [ { name: 'Kim' } ],
* })
* assertEquals(
* peopleByFirstLetter,
* {
* "A": [{ name: "Anna" }, { name: "Arnold" }],
* "K": [{ name: "Kim" }],
* },
* );
* ```
*/
export function groupBy<T, K extends string>(

View File

@ -3,10 +3,10 @@
/**
* If the given value is part of the given object it returns true, otherwise it
* returns false.
* Doesn't work with non-primitive values: includesValue({x: {}}, {}) returns false.
* returns false. Doesn't work with non-primitive values: includesValue({x: {}},
* {}) returns false.
*
* Example:
* @example
* ```ts
* import { includesValue } from "https://deno.land/std@$STD_VERSION/collections/includes_value.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
@ -19,7 +19,6 @@
* assertEquals(includesValue(input, 34), true);
* ```
*/
export function includesValue<T>(
record: Readonly<Record<string, T>>,
value: T,

View File

@ -4,19 +4,19 @@
import { filterInPlace } from "./_utils.ts";
/**
* Returns all distinct elements that appear at least once in each of the given arrays
*
* Example:
* Returns all distinct elements that appear at least once in each of the given
* arrays.
*
* @example
* ```ts
* import { intersect } from "https://deno.land/std@$STD_VERSION/collections/intersect.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const lisaInterests = [ 'Cooking', 'Music', 'Hiking' ]
* const kimInterests = [ 'Music', 'Tennis', 'Cooking' ]
* const commonInterests = intersect(lisaInterests, kimInterests)
* const lisaInterests = ["Cooking", "Music", "Hiking"];
* const kimInterests = ["Music", "Tennis", "Cooking"];
* const commonInterests = intersect(lisaInterests, kimInterests);
*
* assertEquals(commonInterests, [ 'Cooking', 'Music' ])
* assertEquals(commonInterests, ["Cooking", "Music"]);
* ```
*/
export function intersect<T>(...arrays: (readonly T[])[]): T[] {

View File

@ -13,13 +13,14 @@ export type JoinToStringOptions = {
};
/**
* Transforms the elements in the given array to strings using the given selector.
* Joins the produced strings into one using the given `separator` and applying the given `prefix` and `suffix` to the whole string afterwards.
* If the array could be huge, you can specify a non-negative value of `limit`, in which case only the first `limit` elements will be appended, followed by the `truncated` string.
* Returns the resulting string.
*
* Example:
* Transforms the elements in the given array to strings using the given
* selector. Joins the produced strings into one using the given `separator`
* and applying the given `prefix` and `suffix` to the whole string afterwards.
* If the array could be huge, you can specify a non-negative value of `limit`,
* in which case only the first `limit` elements will be appended, followed by
* the `truncated` string. Returns the resulting string.
*
* @example
* ```ts
* import { joinToString } from "https://deno.land/std@$STD_VERSION/collections/join_to_string.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
@ -30,7 +31,7 @@ export type JoinToStringOptions = {
* { name: "Tim" },
* ];
*
* const message = joinToString(users, (it) => it.name, {
* const message = joinToString(users, (it) => it.name, {
* suffix: " are winners",
* prefix: "result: ",
* separator: " and ",

View File

@ -2,29 +2,29 @@
// This module is browser compatible.
/**
* Applies the given transformer to all entries in the given record and returns a new record containing the results
*
* Example:
* Applies the given transformer to all entries in the given record and returns
* a new record containing the results.
*
* @example
* ```ts
* import { mapEntries } from "https://deno.land/std@$STD_VERSION/collections/map_entries.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const usersById = {
* 'a2e': { name: 'Kim', age: 22 },
* 'dfe': { name: 'Anna', age: 31 },
* '34b': { name: 'Tim', age: 58 },
* "a2e": { name: "Kim", age: 22 },
* "dfe": { name: "Anna", age: 31 },
* "34b": { name: "Tim", age: 58 },
* } as const;
* const agesByNames = mapEntries(usersById, ([id, { name, age }]) => [name, age]);
*
* const agesByNames = mapEntries(usersById,
* ([ id, { name, age } ]) => [ name, age ],
* )
*
* assertEquals(agesByNames, {
* 'Kim': 22,
* 'Anna': 31,
* 'Tim': 58,
* })
* assertEquals(
* agesByNames,
* {
* "Kim": 22,
* "Anna": 31,
* "Tim": 58,
* },
* );
* ```
*/
export function mapEntries<T, O>(

View File

@ -2,24 +2,27 @@
// This module is browser compatible.
/**
* Applies the given transformer to all keys in the given record's entries and returns a new record containing the
* transformed entries.
* Applies the given transformer to all keys in the given record's entries and
* returns a new record containing the transformed entries.
*
* If the transformed entries contain the same key multiple times, only the last one will appear in the returned record.
*
* Example:
* If the transformed entries contain the same key multiple times, only the last
* one will appear in the returned record.
*
* @example
* ```ts
* import { mapKeys } from "https://deno.land/std@$STD_VERSION/collections/map_keys.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const counts = { a: 5, b: 3, c: 8 }
* const counts = { a: 5, b: 3, c: 8 };
*
* assertEquals(mapKeys(counts, it => it.toUpperCase()), {
* assertEquals(
* mapKeys(counts, (it) => it.toUpperCase()),
* {
* A: 5,
* B: 3,
* C: 8,
* })
* },
* );
* ```
*/
export function mapKeys<T>(

View File

@ -2,24 +2,24 @@
// This module is browser compatible.
/**
* Returns a new array, containing all elements in the given array transformed using the given transformer, except the ones
* that were transformed to `null` or `undefined`
*
* Example:
* Returns a new array, containing all elements in the given array transformed
* using the given transformer, except the ones that were transformed to `null`
* or `undefined`.
*
* @example
* ```ts
* import { mapNotNullish } from "https://deno.land/std@$STD_VERSION/collections/map_not_nullish.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const people = [
* { middleName: null },
* { middleName: 'William' },
* { middleName: undefined },
* { middleName: 'Martha' },
* ]
* const foundMiddleNames = mapNotNullish(people, it => it.middleName)
* { middleName: null },
* { middleName: "William" },
* { middleName: undefined },
* { middleName: "Martha" },
* ];
* const foundMiddleNames = mapNotNullish(people, (it) => it.middleName);
*
* assertEquals(foundMiddleNames, [ 'William', 'Martha' ])
* assertEquals(foundMiddleNames, ["William", "Martha"]);
* ```
*/
export function mapNotNullish<T, O>(

View File

@ -2,25 +2,28 @@
// This module is browser compatible.
/**
* Applies the given transformer to all values in the given record and returns a new record containing the resulting keys
* associated to the last value that produced them.
*
* Example:
* Applies the given transformer to all values in the given record and returns a
* new record containing the resulting keys associated to the last value that
* produced them.
*
* @example
* ```ts
* import { mapValues } from "https://deno.land/std@$STD_VERSION/collections/map_values.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const usersById = {
* 'a5ec': { name: 'Mischa' },
* 'de4f': { name: 'Kim' },
* }
* const namesById = mapValues(usersById, it => it.name)
* "a5ec": { name: "Mischa" },
* "de4f": { name: "Kim" },
* };
* const namesById = mapValues(usersById, (it) => it.name);
*
* assertEquals(namesById, {
* 'a5ec': 'Mischa',
* 'de4f': 'Kim',
* });
* assertEquals(
* namesById,
* {
* "a5ec": "Mischa",
* "de4f": "Kim",
* },
* );
* ```
*/
export function mapValues<T, O>(

View File

@ -2,23 +2,23 @@
// This module is browser compatible.
/**
* Returns the first element that is the largest value of the given function or undefined if there are no elements.
*
* Example:
* Returns the first element that is the largest value of the given function or
* undefined if there are no elements.
*
* @example
* ```ts
* import { maxBy } from "https://deno.land/std@$STD_VERSION/collections/max_by.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const people = [
* { name: 'Anna', age: 34 },
* { name: 'Kim', age: 42 },
* { name: 'John', age: 23 },
* { name: "Anna", age: 34 },
* { name: "Kim", age: 42 },
* { name: "John", age: 23 },
* ];
*
* const personWithMaxAge = maxBy(people, i => i.age);
* const personWithMaxAge = maxBy(people, (i) => i.age);
*
* assertEquals(personWithMaxAge, { name: 'Kim', age: 42 });
* assertEquals(personWithMaxAge, { name: "Kim", age: 42 });
* ```
*/
export function maxBy<T>(

View File

@ -2,21 +2,21 @@
// This module is browser compatible.
/**
* Applies the given selector to all elements of the given collection and
* Applies the given selector to all elements of the provided collection and
* returns the max value of all elements. If an empty array is provided the
* function will return undefined
*
* Example:
*
* @example
* ```ts
* import { maxOf } from "https://deno.land/std@$STD_VERSION/collections/max_of.ts"
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"
* import { maxOf } from "https://deno.land/std@$STD_VERSION/collections/max_of.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const inventory = [
* { name: "mustard", count: 2 },
* { name: "soy", count: 4 },
* { name: "tomato", count: 32 },
* { name: "mustard", count: 2 },
* { name: "soy", count: 4 },
* { name: "tomato", count: 32 },
* ];
*
* const maxCount = maxOf(inventory, (i) => i.count);
*
* assertEquals(maxCount, 32);

View File

@ -5,12 +5,11 @@
* Returns the first element having the largest value according to the provided
* comparator or undefined if there are no elements.
*
* The comparator is expected to work exactly like one passed to `Array.sort`, which means
* that `comparator(a, b)` should return a negative number if `a < b`, a positive number if `a > b`
* and `0` if `a == b`.
*
* Example:
* The comparator is expected to work exactly like one passed to `Array.sort`,
* which means that `comparator(a, b)` should return a negative number if `a < b`,
* a positive number if `a > b` and `0` if `a == b`.
*
* @example
* ```ts
* import { maxWith } from "https://deno.land/std@$STD_VERSION/collections/max_with.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";

View File

@ -2,23 +2,23 @@
// This module is browser compatible.
/**
* Returns the first element that is the smallest value of the given function or undefined if there are no elements.
*
* Example:
* Returns the first element that is the smallest value of the given function or
* undefined if there are no elements
*
* @example
* ```ts
* import { minBy } from "https://deno.land/std@$STD_VERSION/collections/min_by.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const people = [
* { name: 'Anna', age: 34 },
* { name: 'Kim', age: 42 },
* { name: 'John', age: 23 },
* { name: "Anna", age: 34 },
* { name: "Kim", age: 42 },
* { name: "John", age: 23 },
* ];
*
* const personWithMinAge = minBy(people, i => i.age);
* const personWithMinAge = minBy(people, (i) => i.age);
*
* assertEquals(personWithMinAge, { name: 'John', age: 23 });
* assertEquals(personWithMinAge, { name: "John", age: 23 });
* ```
*/
export function minBy<T>(

View File

@ -4,18 +4,17 @@
/**
* Applies the given selector to all elements of the given collection and
* returns the min value of all elements. If an empty array is provided the
* function will return undefined
*
* Example:
* function will return undefined.
*
* @example
* ```ts
* import { minOf } from "https://deno.land/std@$STD_VERSION/collections/min_of.ts"
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"
* import { minOf } from "https://deno.land/std@$STD_VERSION/collections/min_of.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const inventory = [
* { name: "mustard", count: 2 },
* { name: "soy", count: 4 },
* { name: "tomato", count: 32 },
* { name: "mustard", count: 2 },
* { name: "soy", count: 4 },
* { name: "tomato", count: 32 },
* ];
* const minCount = minOf(inventory, (i) => i.count);
*

View File

@ -2,10 +2,10 @@
// This module is browser compatible.
/**
* Returns the first element having the smallest value according to the provided comparator or undefined if there are no elements
*
* Example:
* Returns the first element having the smallest value according to the provided
* comparator or undefined if there are no elements
*
* @example
* ```ts
* import { minWith } from "https://deno.land/std@$STD_VERSION/collections/min_with.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";

View File

@ -1,12 +1,17 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
/** Functions for specific common tasks around collection types like `Array` and
* `Record`.
* `Record`. This module is heavily inspired by `kotlin`s stdlib.
*
* - All provided functions are **pure**, which also means that they do **not
* mutate** your inputs, **returning a new value** instead.
* - All functions are importable on their own by referencing their snake_case
* named file (e.g. `collections/sort_by.ts`)
*
* This module re-exports several modules, and importing this module directly
* will likely include a lot of code that you might not use.
*
* Consider importing the function directly. For example to import
* Consider importing the function directly. For example to import
* {@linkcode groupBy} import the module using the snake cased version of the
* module:
*

View File

@ -2,20 +2,20 @@
// This module is browser compatible.
/**
* Returns a tuple of two arrays with the first one containing all elements in the given array that match the given predicate
* and the second one containing all that do not
*
* Example:
* Returns a tuple of two arrays with the first one containing all elements in
* the given array that match the given predicate and the second one containing
* all that do not.
*
* @example
* ```ts
* import { partition } from "https://deno.land/std@$STD_VERSION/collections/partition.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const numbers = [ 5, 6, 7, 8, 9 ]
* const [ even, odd ] = partition(numbers, it => it % 2 == 0)
* const numbers = [5, 6, 7, 8, 9];
* const [even, odd] = partition(numbers, (it) => it % 2 == 0);
*
* assertEquals(even, [ 6, 8 ])
* assertEquals(odd, [ 5, 7, 9 ])
* assertEquals(even, [6, 8]);
* assertEquals(odd, [5, 7, 9]);
* ```
*/
export function partition<T, U extends T>(

View File

@ -6,19 +6,18 @@
* Ignores equality of elements, meaning this will always return the same
* number of permutations for a given length of input.
*
* Example:
*
* @example
* ```ts
* import { permutations } from "https://deno.land/std@$STD_VERSION/collections/permutations.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const numbers = [ 1, 2 ]
* const windows = permutations(numbers)
* const numbers = [ 1, 2 ];
* const windows = permutations(numbers);
*
* assertEquals(windows, [
* [ 1, 2 ],
* [ 2, 1 ],
* ])
* [ 1, 2 ],
* [ 2, 1 ],
* ]);
* ```
*/
export function permutations<T>(inputArray: readonly T[]): T[][] {

View File

@ -6,9 +6,86 @@ import { Direction, RedBlackNode } from "./red_black_node.ts";
export * from "./_comparators.ts";
/**
* A red-black tree. This is a kind of self-balancing binary search tree.
* The values are in ascending order by default,
* using JavaScript's built in comparison operators to sort the values.
* A red-black tree. This is a kind of self-balancing binary search tree. The
* values are in ascending order by default, using JavaScript's built-in
* comparison operators to sort the values.
*
* Red-Black Trees require fewer rotations than AVL Trees, so they can provide
* faster insertions and removal operations. If you need faster lookups, you
* should use an AVL Tree instead. AVL Trees are more strictly balanced than
* Red-Black Trees, so they can provide faster lookups.
*
* | Method | Average Case | Worst Case |
* | ------------- | ------------ | ---------- |
* | find(value) | O(log n) | O(log n) |
* | insert(value) | O(log n) | O(log n) |
* | remove(value) | O(log n) | O(log n) |
* | min() | O(log n) | O(log n) |
* | max() | O(log n) | O(log n) |
*
* @example
* ```ts
* import {
* ascend,
* descend,
* RedBlackTree,
* } from "https://deno.land/std@$STD_VERSION/collections/red_black_tree.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const values = [3, 10, 13, 4, 6, 7, 1, 14];
* const tree = new RedBlackTree<number>();
* values.forEach((value) => tree.insert(value));
* assertEquals([...tree], [1, 3, 4, 6, 7, 10, 13, 14]);
* assertEquals(tree.min(), 1);
* assertEquals(tree.max(), 14);
* assertEquals(tree.find(42), null);
* assertEquals(tree.find(7), 7);
* assertEquals(tree.remove(42), false);
* assertEquals(tree.remove(7), true);
* assertEquals([...tree], [1, 3, 4, 6, 10, 13, 14]);
*
* const invertedTree = new RedBlackTree<number>(descend);
* values.forEach((value) => invertedTree.insert(value));
* assertEquals([...invertedTree], [14, 13, 10, 7, 6, 4, 3, 1]);
* assertEquals(invertedTree.min(), 14);
* assertEquals(invertedTree.max(), 1);
* assertEquals(invertedTree.find(42), null);
* assertEquals(invertedTree.find(7), 7);
* assertEquals(invertedTree.remove(42), false);
* assertEquals(invertedTree.remove(7), true);
* assertEquals([...invertedTree], [14, 13, 10, 6, 4, 3, 1]);
*
* const words = new RedBlackTree<string>((a, b) =>
* ascend(a.length, b.length) || ascend(a, b)
* );
* ["truck", "car", "helicopter", "tank", "train", "suv", "semi", "van"]
* .forEach((value) => words.insert(value));
* assertEquals([...words], [
* "car",
* "suv",
* "van",
* "semi",
* "tank",
* "train",
* "truck",
* "helicopter",
* ]);
* assertEquals(words.min(), "car");
* assertEquals(words.max(), "helicopter");
* assertEquals(words.find("scooter"), null);
* assertEquals(words.find("tank"), "tank");
* assertEquals(words.remove("scooter"), false);
* assertEquals(words.remove("tank"), true);
* assertEquals([...words], [
* "car",
* "suv",
* "van",
* "semi",
* "train",
* "truck",
* "helicopter",
* ]);
* ```
*/
export class RedBlackTree<T> extends BinarySearchTree<T> {
declare protected root: RedBlackNode<T> | null;

View File

@ -4,22 +4,25 @@
import { mapValues } from "./map_values.ts";
/**
* Applies the given reducer to each group in the given Grouping, returning the results together with the respective group keys
* Applies the given reducer to each group in the given Grouping, returning the
* results together with the respective group keys.
*
* @example
* ```ts
* import { reduceGroups } from "https://deno.land/std@$STD_VERSION/collections/reduce_groups.ts"
* import { reduceGroups } from "https://deno.land/std@$STD_VERSION/collections/reduce_groups.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const votes = {
* 'Woody': [ 2, 3, 1, 4 ],
* 'Buzz': [ 5, 9 ],
* }
* const totalVotes = reduceGroups(votes, (sum, it) => sum + it, 0)
* "Woody": [2, 3, 1, 4],
* "Buzz": [5, 9],
* };
*
* const totalVotes = reduceGroups(votes, (sum, it) => sum + it, 0);
*
* assertEquals(totalVotes, {
* 'Woody': 10,
* 'Buzz': 14,
* })
* "Woody": 10,
* "Buzz": 14,
* });
* ```
*/
export function reduceGroups<T, A>(

View File

@ -2,12 +2,11 @@
// This module is browser compatible.
/**
* Calls the given reducer on each element of the given collection, passing it's
* result as the accumulator to the next respective call, starting with the given
* initialValue. Returns all intermediate accumulator results.
*
* Example:
* Calls the given reducer on each element of the given collection, passing its
* result as the accumulator to the next respective call, starting with the
* given initialValue. Returns all intermediate accumulator results.
*
* @example
* ```ts
* import { runningReduce } from "https://deno.land/std@$STD_VERSION/collections/running_reduce.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";

View File

@ -4,12 +4,11 @@
import { randomInteger } from "./_utils.ts";
/**
* Returns a random element from the given array.
*
* Example:
* Returns a random element from the given array
*
* @example
* ```ts
* import { sample } from "https://deno.land/std@$STD_VERSION/collections/sample.ts"
* import { sample } from "https://deno.land/std@$STD_VERSION/collections/sample.ts";
* import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const numbers = [1, 2, 3, 4];

View File

@ -2,18 +2,16 @@
// This module is browser compatible.
/**
* Generates sliding views of the given array of the given size and returns a new
* array containing all of them.
* Generates sliding views of the given array of the given size and returns a
* new array containing all of them.
*
* If step is set, each window will start that many elements after the last
* window's start. (Default: 1)
*
* If partial is set, windows will be generated for the last elements of the
* collection, resulting in some undefined values if size is greater than 1.
* (Default: false)
*
* Example:
*
* @example
* ```ts
* import { slidingWindows } from "https://deno.land/std@$STD_VERSION/collections/sliding_windows.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
@ -48,13 +46,16 @@ export function slidingWindows<T>(
{ step = 1, partial = false }: {
/**
* If step is set, each window will start that many elements after the last
* window's start. (Default: 1)
* window's start.
*
* @default {1}
*/
step?: number;
/**
* If partial is set, windows will be generated for the last elements of the
* collection, resulting in some undefined values if size is greater than 1.
* (Default: false)
*
* @default {false}
*/
partial?: boolean;
} = {},

View File

@ -2,26 +2,27 @@
// This module is browser compatible.
/**
* Returns all elements in the given collection, sorted stably by their result using the given selector. The selector function is called only once for each element.
*
* Example:
* Returns all elements in the given collection, sorted by their result using
* the given selector. The selector function is called only once for each
* element.
*
* @example
* ```ts
* import { sortBy } from "https://deno.land/std@$STD_VERSION/collections/sort_by.ts"
* import { sortBy } from "https://deno.land/std@$STD_VERSION/collections/sort_by.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const people = [
* { name: 'Anna', age: 34 },
* { name: 'Kim', age: 42 },
* { name: 'John', age: 23 },
* ]
* const sortedByAge = sortBy(people, it => it.age)
* { name: "Anna", age: 34 },
* { name: "Kim", age: 42 },
* { name: "John", age: 23 },
* ];
* const sortedByAge = sortBy(people, (it) => it.age);
*
* assertEquals(sortedByAge, [
* { name: 'John', age: 23 },
* { name: 'Anna', age: 34 },
* { name: 'Kim', age: 42 },
* ])
* { name: "John", age: 23 },
* { name: "Anna", age: 34 },
* { name: "Kim", age: 42 },
* ]);
* ```
*/
export function sortBy<T>(

View File

@ -2,22 +2,22 @@
// This module is browser compatible.
/**
* Applies the given selector to all elements in the given collection and calculates the sum of the results
*
* Example:
* Applies the given selector to all elements in the given collection and
* calculates the sum of the results.
*
* @example
* ```ts
* import { sumOf } from "https://deno.land/std@$STD_VERSION/collections/sum_of.ts"
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"
* import { sumOf } from "https://deno.land/std@$STD_VERSION/collections/sum_of.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const people = [
* { name: 'Anna', age: 34 },
* { name: 'Kim', age: 42 },
* { name: 'John', age: 23 },
* ]
* const totalAge = sumOf(people, i => i.age)
* { name: "Anna", age: 34 },
* { name: "Kim", age: 42 },
* { name: "John", age: 23 },
* ];
* const totalAge = sumOf(people, (i) => i.age);
*
* assertEquals(totalAge, 99)
* assertEquals(totalAge, 99);
* ```
*/
export function sumOf<T>(

View File

@ -5,7 +5,7 @@
* Returns all elements in the given array after the last element that does not
* match the given predicate.
*
* Example:
* @example
* ```ts
* import { takeLastWhile } from "https://deno.land/std@$STD_VERSION/collections/take_last_while.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";

View File

@ -2,9 +2,10 @@
// This module is browser compatible.
/**
* Returns all elements in the given collection until the first element that does not match the given predicate.
* Returns all elements in the given collection until the first element that
* does not match the given predicate.
*
* Example:
* @example
* ```ts
* import { takeWhile } from "https://deno.land/std@$STD_VERSION/collections/take_while.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";

View File

@ -4,17 +4,16 @@
/**
* Returns all distinct elements that appear in any of the given arrays
*
* Example:
*
* @example
* ```ts
* import { union } from "https://deno.land/std@$STD_VERSION/collections/union.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const soupIngredients = [ 'Pepper', 'Carrots', 'Leek' ]
* const saladIngredients = [ 'Carrots', 'Radicchio', 'Pepper' ]
* const shoppingList = union(soupIngredients, saladIngredients)
* const soupIngredients = ["Pepper", "Carrots", "Leek"];
* const saladIngredients = ["Carrots", "Radicchio", "Pepper"];
* const shoppingList = union(soupIngredients, saladIngredients);
*
* assertEquals(shoppingList, [ 'Pepper', 'Carrots', 'Leek', 'Radicchio' ])
* assertEquals(shoppingList, ["Pepper", "Carrots", "Leek", "Radicchio"]);
* ```
*/
export function union<T>(...arrays: (readonly T[])[]): T[] {

View File

@ -2,25 +2,24 @@
// This module is browser compatible.
/**
* Builds two separate arrays from the given array of 2-tuples, with the first returned array holding all first
* tuple elements and the second one holding all the second elements
*
* Example:
* Builds two separate arrays from the given array of 2-tuples, with the first
* returned array holding all first tuple elements and the second one holding
* all the second elements.
*
* ```ts
* import { unzip } from "https://deno.land/std@$STD_VERSION/collections/unzip.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const parents = [
* [ 'Maria', 'Jeff' ],
* [ 'Anna', 'Kim' ],
* [ 'John', 'Leroy' ],
* ["Maria", "Jeff"],
* ["Anna", "Kim"],
* ["John", "Leroy"],
* ] as [string, string][];
*
* const [ moms, dads ] = unzip(parents);
* const [moms, dads] = unzip(parents);
*
* assertEquals(moms, [ 'Maria', 'Anna', 'John' ]);
* assertEquals(dads, [ 'Jeff', 'Kim', 'Leroy' ]);
* assertEquals(moms, ["Maria", "Anna", "John"]);
* assertEquals(dads, ["Jeff", "Kim", "Leroy"]);
* ```
*/
export function unzip<T, U>(pairs: readonly [T, U][]): [T[], U[]] {

View File

@ -4,8 +4,7 @@
/**
* Returns an array excluding all given values.
*
* Example:
*
* @example
* ```ts
* import { withoutAll } from "https://deno.land/std@$STD_VERSION/collections/without_all.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";

View File

@ -2,23 +2,27 @@
// This module is browser compatible.
/**
* Builds N-tuples of elements from the given N arrays with matching indices, stopping when the smallest array's end is reached
* Example:
* Builds N-tuples of elements from the given N arrays with matching indices,
* stopping when the smallest array's end is reached.
*
* @example
* ```ts
* import { zip } from "https://deno.land/std@$STD_VERSION/collections/zip.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const numbers = [ 1, 2, 3, 4 ];
* const letters = [ 'a', 'b', 'c', 'd' ];
* const numbers = [1, 2, 3, 4];
* const letters = ["a", "b", "c", "d"];
* const pairs = zip(numbers, letters);
*
* assertEquals(pairs, [
* [ 1, 'a' ],
* [ 2, 'b' ],
* [ 3, 'c' ],
* [ 4, 'd' ],
* ]);
* assertEquals(
* pairs,
* [
* [1, "a"],
* [2, "b"],
* [3, "c"],
* [4, "d"],
* ],
* );
* ```
*/

View File

@ -1,178 +0,0 @@
# crypto
Extensions to the WebCrypto interface, which provides additional encryption
algorithms that are not part of the web standard, as well as a
`subtle.digest()`, `subtle.digestSync()`, and `subtle.timingSafeEqual()` methods
which provide additional functionality not covered by web crypto.
It also includes some utilities for key management.
## `crypto` usage
The `crypto` export provides an enhanced version of the built-in
[Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
providing additional cryptographic algorithms using the same interface as the
Web Crypto API, but also delegating to the built in APIs when possible.
```ts
import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
// This will delegate to the runtime's WebCrypto implementation.
console.log(
new Uint8Array(
await crypto.subtle.digest(
"SHA-384",
new TextEncoder().encode("hello world"),
),
),
);
// This will use a bundled Wasm/Rust implementation.
console.log(
new Uint8Array(
await crypto.subtle.digest(
"BLAKE3",
new TextEncoder().encode("hello world"),
),
),
);
```
### Supported algorithms
Here is a list of supported algorithms. If the algorithm name in WebCrypto and
Wasm/Rust is the same, this library prefers to use algorithms that are supported
by WebCrypto.
WebCrypto
```ts
// https://deno.land/std/crypto/mod.ts
const webCryptoDigestAlgorithms = [
"SHA-384",
"SHA-256",
"SHA-512",
// insecure (length-extendable and collidable):
"SHA-1",
] as const;
```
Wasm/Rust
```ts
// https://deno.land/std/_wasm_crypto/mod.ts
export const digestAlgorithms = [
"BLAKE2B-256",
"BLAKE2B-384",
"BLAKE2B",
"BLAKE2S",
"BLAKE3",
"KECCAK-224",
"KECCAK-256",
"KECCAK-384",
"KECCAK-512",
"SHA-384",
"SHA3-224",
"SHA3-256",
"SHA3-384",
"SHA3-512",
"SHAKE128",
"SHAKE256",
"TIGER",
// insecure (length-extendable):
"RIPEMD-160",
"SHA-224",
"SHA-256",
"SHA-512",
// insecure (collidable and length-extendable):
"MD5",
"SHA-1",
] as const;
```
## Timing safe comparison
When checking the values of cryptographic hashes are equal, default comparisons
can be susceptible to timing based attacks, where attacker is able to find out
information about the host system by repeatedly checking response times to to
equality comparisons of values.
It is likely some form of timing safe equality will make its way to the
WebCrypto standard (see:
[w3c/webcrypto#270](https://github.com/w3c/webcrypto/issues/270)), but until
that time, `timingSafeEqual()` is provided:
```ts
import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
const a = await crypto.subtle.digest(
"SHA-384",
new TextEncoder().encode("hello world"),
);
const b = await crypto.subtle.digest(
"SHA-384",
new TextEncoder().encode("hello world"),
);
const c = await crypto.subtle.digest(
"SHA-384",
new TextEncoder().encode("hello deno"),
);
assert(crypto.subtle.timingSafeEqual(a, b));
assert(!crypto.subtle.timingSafeEqual(a, c));
```
In addition to the method being part of the `crypto.subtle` interface, it is
also loadable directly:
```ts
import { timingSafeEqual } from "https://deno.land/std@$STD_VERSION/crypto/timing_safe_equal.ts";
import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
const a = await crypto.subtle.digest(
"SHA-384",
new TextEncoder().encode("hello world"),
);
const b = await crypto.subtle.digest(
"SHA-384",
new TextEncoder().encode("hello world"),
);
assert(timingSafeEqual(a, b));
```
## `KeyStack` usage
The `KeyStack` export implements the `KeyRing` interface for managing rotatable
keys for signing data to prevent tampering, like with HTTP cookies.
```ts
import { KeyStack } from "https://deno.land/std@$STD_VERSION/crypto/keystack.ts";
const keyStack = new KeyStack(["hello", "world"]);
const digest = await keyStack.sign("some data");
const rotatedStack = new KeyStack(["deno", "says", "hello", "world"]);
await rotatedStack.verify("some data", digest); // true
```
## Convert hash to a string
```ts
import {
crypto,
toHashString,
} from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
const hash = await crypto.subtle.digest(
"SHA-384",
new TextEncoder().encode("You hear that Mr. Anderson?"),
);
// Hex encoding by default
console.log(toHashString(hash));
// Or with base64 encoding
console.log(toHashString(hash, "base64"));
```

View File

@ -72,8 +72,7 @@ async function compare(a: Data, b: Data): Promise<boolean> {
*
* This was inspired by [keygrip](https://github.com/crypto-utils/keygrip/).
*
* ### Example
*
* @example
* ```ts
* import { KeyStack } from "https://deno.land/std@$STD_VERSION/crypto/keystack.ts";
*

View File

@ -3,11 +3,12 @@
/**
* Extensions to the
* [Web Crypto](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
* supporting additional encryption APIs.
* supporting additional encryption APIs, but also delegating to the built-in
* APIs when possible.
*
* Provides additional digest algorithms that are not part of the WebCrypto
* standard as well as a `subtle.digest` and `subtle.digestSync` methods. It
* also provide a `subtle.timingSafeEqual()` method to compare array buffers
* also provides a `subtle.timingSafeEqual()` method to compare array buffers
* or data views in a way that isn't prone to timing based attacks.
*
* The "polyfill" delegates to `WebCrypto` where possible.
@ -16,6 +17,155 @@
* for managing rotatable keys for signing data to prevent tampering, like with
* HTTP cookies.
*
* ## Supported algorithms
*
* Here is a list of supported algorithms. If the algorithm name in WebCrypto
* and Wasm/Rust is the same, this library prefers to use algorithms that are
* supported by WebCrypto.
*
* WebCrypto
*
* ```ts
* // https://deno.land/std/crypto/mod.ts
* const webCryptoDigestAlgorithms = [
* "SHA-384",
* "SHA-256",
* "SHA-512",
* // insecure (length-extendable and collidable):
* "SHA-1",
* ] as const;
* ```
*
* Wasm/Rust
*
* ```ts
* // https://deno.land/std/_wasm_crypto/mod.ts
* export const digestAlgorithms = [
* "BLAKE2B-256",
* "BLAKE2B-384",
* "BLAKE2B",
* "BLAKE2S",
* "BLAKE3",
* "KECCAK-224",
* "KECCAK-256",
* "KECCAK-384",
* "KECCAK-512",
* "SHA-384",
* "SHA3-224",
* "SHA3-256",
* "SHA3-384",
* "SHA3-512",
* "SHAKE128",
* "SHAKE256",
* "TIGER",
* // insecure (length-extendable):
* "RIPEMD-160",
* "SHA-224",
* "SHA-256",
* "SHA-512",
* // insecure (collidable and length-extendable):
* "MD5",
* "SHA-1",
* ] as const;
* ```
*
* ## Timing safe comparison
*
* When checking the values of cryptographic hashes are equal, default
* comparisons can be susceptible to timing based attacks, where attacker is
* able to find out information about the host system by repeatedly checking
* response times to equality comparisons of values.
*
* It is likely some form of timing safe equality will make its way to the
* WebCrypto standard (see:
* [w3c/webcrypto#270](https://github.com/w3c/webcrypto/issues/270)), but until
* that time, `timingSafeEqual()` is provided:
*
* ```ts
* import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
* import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const a = await crypto.subtle.digest(
* "SHA-384",
* new TextEncoder().encode("hello world"),
* );
* const b = await crypto.subtle.digest(
* "SHA-384",
* new TextEncoder().encode("hello world"),
* );
* const c = await crypto.subtle.digest(
* "SHA-384",
* new TextEncoder().encode("hello deno"),
* );
*
* assert(crypto.subtle.timingSafeEqual(a, b));
* assert(!crypto.subtle.timingSafeEqual(a, c));
* ```
*
* In addition to the method being part of the `crypto.subtle` interface, it is
* also loadable directly:
*
* ```ts
* import { timingSafeEqual } from "https://deno.land/std@$STD_VERSION/crypto/timing_safe_equal.ts";
* import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const a = await crypto.subtle.digest(
* "SHA-384",
* new TextEncoder().encode("hello world"),
* );
* const b = await crypto.subtle.digest(
* "SHA-384",
* new TextEncoder().encode("hello world"),
* );
*
* assert(timingSafeEqual(a, b));
* ```
*
* @example
* ```ts
* import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
*
* // This will delegate to the runtime's WebCrypto implementation.
* console.log(
* new Uint8Array(
* await crypto.subtle.digest(
* "SHA-384",
* new TextEncoder().encode("hello world"),
* ),
* ),
* );
*
* // This will use a bundled Wasm/Rust implementation.
* console.log(
* new Uint8Array(
* await crypto.subtle.digest(
* "BLAKE3",
* new TextEncoder().encode("hello world"),
* ),
* ),
* );
* ```
*
* @example Convert hash to a string
*
* ```ts
* import {
* crypto,
* toHashString,
* } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
*
* const hash = await crypto.subtle.digest(
* "SHA-384",
* new TextEncoder().encode("You hear that Mr. Anderson?"),
* );
*
* // Hex encoding by default
* console.log(toHashString(hash));
*
* // Or with base64 encoding
* console.log(toHashString(hash, "base64"));
* ```
*
* @module
*/

View File

@ -1,187 +0,0 @@
# datetime
Simple helper to help parse date strings into `Date`, with additional functions.
## Usage
The following symbols from
[unicode LDML](http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table)
are supported:
- `yyyy` - numeric year.
- `yy` - 2-digit year.
- `M` - numeric month.
- `MM` - 2-digit month.
- `d` - numeric day.
- `dd` - 2-digit day.
- `H` - numeric hour (0-23 hours).
- `HH` - 2-digit hour (00-23 hours).
- `h` - numeric hour (1-12 hours).
- `hh` - 2-digit hour (01-12 hours).
- `m` - numeric minute.
- `mm` - 2-digit minute.
- `s` - numeric second.
- `ss` - 2-digit second.
- `S` - 1-digit fractionalSecond.
- `SS` - 2-digit fractionalSecond.
- `SSS` - 3-digit fractionalSecond.
- `a` - dayPeriod, either `AM` or `PM`.
- `'foo'` - quoted literal.
- `./-` - unquoted literal.
## Methods
### parse
Takes an input `string` and a `formatString` to parse to a `date`.
```ts
import { parse } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
parse("20-01-2019", "dd-MM-yyyy"); // output : new Date(2019, 0, 20)
parse("2019-01-20", "yyyy-MM-dd"); // output : new Date(2019, 0, 20)
parse("20.01.2019", "dd.MM.yyyy"); // output : new Date(2019, 0, 20)
parse("01-20-2019 16:34", "MM-dd-yyyy HH:mm"); // output : new Date(2019, 0, 20, 16, 34)
parse("01-20-2019 04:34 PM", "MM-dd-yyyy hh:mm a"); // output : new Date(2019, 0, 20, 16, 34)
parse("16:34 01-20-2019", "HH:mm MM-dd-yyyy"); // output : new Date(2019, 0, 20, 16, 34)
parse("01-20-2019 16:34:23.123", "MM-dd-yyyy HH:mm:ss.SSS"); // output : new Date(2019, 0, 20, 16, 34, 23, 123)
```
### format
Takes an input `date` and a `formatString` to format to a `string`.
```ts
import { format } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
format(new Date(2019, 0, 20), "dd-MM-yyyy"); // output : "20-01-2019"
format(new Date(2019, 0, 20), "yyyy-MM-dd"); // output : "2019-01-20"
format(new Date(2019, 0, 20), "dd.MM.yyyy"); // output : "20.01.2019"
format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy HH:mm"); // output : "01-20-2019 16:34"
format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy hh:mm a"); // output : "01-20-2019 04:34 PM"
format(new Date(2019, 0, 20, 16, 34), "HH:mm MM-dd-yyyy"); // output : "16:34 01-20-2019"
format(new Date(2019, 0, 20, 16, 34, 23, 123), "MM-dd-yyyy HH:mm:ss.SSS"); // output : "01-20-2019 16:34:23.123"
format(new Date(2019, 0, 20), "'today:' yyyy-MM-dd"); // output : "today: 2019-01-20"
```
### dayOfYear
Returns the number of the day in the year.
```ts
import { dayOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
dayOfYear(new Date("2019-03-11T03:24:00")); // output: 70
```
### weekOfYear
Returns the ISO week number of the provided date (1-53).
```ts
import { weekOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
weekOfYear(new Date("2020-12-28T03:24:00")); // Returns 53
```
### toIMF
Formats the given date to IMF date time format. (Reference:
https://tools.ietf.org/html/rfc7231#section-7.1.1.1 )
```ts
import { toIMF } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
toIMF(new Date(0)); // => returns "Thu, 01 Jan 1970 00:00:00 GMT"
```
### isLeap
Returns true if the given date or year (in number) is a leap year. Returns false
otherwise.
```ts
import { isLeap } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
isLeap(new Date("1970-01-01")); // => returns false
isLeap(new Date("1972-01-01")); // => returns true
isLeap(new Date("2000-01-01")); // => returns true
isLeap(new Date("2100-01-01")); // => returns false
isLeap(1972); // => returns true
```
### difference
Returns the difference of the 2 given dates in the given units. If the units are
omitted, it returns the difference in the all available units.
Available units: "milliseconds", "seconds", "minutes", "hours", "days", "weeks",
"months", "quarters", "years"
```ts
import { difference } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
const date0 = new Date("2018-05-14");
const date1 = new Date("2020-05-13");
difference(date0, date1, { units: ["days", "months", "years"] });
// => returns { days: 730, months: 23, years: 1 }
difference(date0, date1);
// => returns {
// milliseconds: 63072000000,
// seconds: 63072000,
// minutes: 1051200,
// hours: 17520,
// days: 730,
// weeks: 104,
// months: 23,
// quarters: 5,
// years: 1
// }
```
## Constants
### SECOND
```ts
import { SECOND } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
console.log(SECOND); // => 1000
```
### MINUTE
```ts
import { MINUTE } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
console.log(MINUTE); // => 60000 (60 * 1000)
```
### HOUR
```ts
import { HOUR } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
console.log(HOUR); // => 3600000 (60 * 60 * 1000)
```
### DAY
```ts
import { DAY } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
console.log(DAY); // => 86400000 (24 * 60 * 60 * 1000)
```
### WEEK
```ts
import { WEEK } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
console.log(WEEK); // => 604800000 (7 * 24 * 60 * 60 * 1000)
```

View File

@ -3,6 +3,34 @@
/**
* Utilities for dealing with {@linkcode Date} objects.
*
* The following symbols from
* [unicode LDML](http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table)
* are supported:
*
* - `yyyy` - numeric year.
* - `yy` - 2-digit year.
* - `M` - numeric month.
* - `MM` - 2-digit month.
* - `d` - numeric day.
* - `dd` - 2-digit day.
*
* - `H` - numeric hour (0-23 hours).
* - `HH` - 2-digit hour (00-23 hours).
* - `h` - numeric hour (1-12 hours).
* - `hh` - 2-digit hour (01-12 hours).
* - `m` - numeric minute.
* - `mm` - 2-digit minute.
* - `s` - numeric second.
* - `ss` - 2-digit second.
* - `S` - 1-digit fractionalSecond.
* - `SS` - 2-digit fractionalSecond.
* - `SSS` - 3-digit fractionalSecond.
*
* - `a` - dayPeriod, either `AM` or `PM`.
*
* - `'foo'` - quoted literal.
* - `./-` - unquoted literal.
*
* This module is browser compatible.
*
* @module
@ -10,10 +38,60 @@
import { DateTimeFormatter } from "./formatter.ts";
/**
* The number of milliseconds in a second.
*
* @example
* ```ts
* import { SECOND } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* console.log(SECOND); // => 1000
* ```
*/
export const SECOND = 1e3;
/**
* The number of milliseconds in a minute.
*
* @example
* ```ts
* import { MINUTE } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* console.log(MINUTE); // => 60000 (60 * 1000)
* ```
*/
export const MINUTE = SECOND * 60;
/**
* The number of milliseconds in an hour.
*
* @example
* ```ts
* import { HOUR } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* console.log(HOUR); // => 3600000 (60 * 60 * 1000)
* ```
*/
export const HOUR = MINUTE * 60;
/**
* The number of milliseconds in a day.
*
* @example
* ```ts
* import { DAY } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* console.log(DAY); // => 86400000 (24 * 60 * 60 * 1000)
* ```
*/
export const DAY = HOUR * 24;
/**
* The number of milliseconds in a week.
*
* @example
* ```ts
* import { WEEK } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* console.log(WEEK); // => 604800000 (7 * 24 * 60 * 60 * 1000)
* ```
*/
export const WEEK = DAY * 7;
const DAYS_PER_WEEK = 7;
@ -28,9 +106,23 @@ enum Day {
}
/**
* Parse date from string using format string
* Takes an input `string` and a `formatString` to parse to a `date`.
*
* @example
* ```ts
* import { parse } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* parse("20-01-2019", "dd-MM-yyyy"); // output : new Date(2019, 0, 20)
* parse("2019-01-20", "yyyy-MM-dd"); // output : new Date(2019, 0, 20)
* parse("20.01.2019", "dd.MM.yyyy"); // output : new Date(2019, 0, 20)
* parse("01-20-2019 16:34", "MM-dd-yyyy HH:mm"); // output : new Date(2019, 0, 20, 16, 34)
* parse("01-20-2019 04:34 PM", "MM-dd-yyyy hh:mm a"); // output : new Date(2019, 0, 20, 16, 34)
* parse("16:34 01-20-2019", "HH:mm MM-dd-yyyy"); // output : new Date(2019, 0, 20, 16, 34)
* parse("01-20-2019 16:34:23.123", "MM-dd-yyyy HH:mm:ss.SSS"); // output : new Date(2019, 0, 20, 16, 34, 23, 123)
* ```
*
* @param dateString Date string
* @param format Format string
* @param formatString Format string
* @return Parsed date
*/
export function parse(dateString: string, formatString: string): Date {
@ -41,9 +133,24 @@ export function parse(dateString: string, formatString: string): Date {
}
/**
* Format date using format string
* Takes an input `date` and a `formatString` to format to a `string`.
*
* @example
* ```ts
* import { format } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* format(new Date(2019, 0, 20), "dd-MM-yyyy"); // output : "20-01-2019"
* format(new Date(2019, 0, 20), "yyyy-MM-dd"); // output : "2019-01-20"
* format(new Date(2019, 0, 20), "dd.MM.yyyy"); // output : "20.01.2019"
* format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy HH:mm"); // output : "01-20-2019 16:34"
* format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy hh:mm a"); // output : "01-20-2019 04:34 PM"
* format(new Date(2019, 0, 20, 16, 34), "HH:mm MM-dd-yyyy"); // output : "16:34 01-20-2019"
* format(new Date(2019, 0, 20, 16, 34, 23, 123), "MM-dd-yyyy HH:mm:ss.SSS"); // output : "01-20-2019 16:34:23.123"
* format(new Date(2019, 0, 20), "'today:' yyyy-MM-dd"); // output : "today: 2019-01-20"
* ```
*
* @param date Date
* @param format Format string
* @param formatString Format string
* @return formatted date string
*/
export function format(date: Date, formatString: string): string {
@ -52,7 +159,15 @@ export function format(date: Date, formatString: string): string {
}
/**
* Get number of the day in the year
* Returns the number of the day in the year.
*
* @example
* ```ts
* import { dayOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* dayOfYear(new Date("2019-03-11T03:24:00")); // output: 70
* ```
*
* @return Number of the day in year
*/
export function dayOfYear(date: Date): number {
@ -68,7 +183,15 @@ export function dayOfYear(date: Date): number {
return Math.floor(diff / DAY);
}
/**
* Get number of the week in the year (ISO-8601)
* Returns the ISO week number of the provided date (1-53).
*
* @example
* ```ts
* import { weekOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* weekOfYear(new Date("2020-12-28T03:24:00")); // Returns 53
* ```
*
* @return Number of the week in year
*/
export function weekOfYear(date: Date): number {
@ -92,11 +215,18 @@ export function weekOfYear(date: Date): number {
}
/**
* Parse a date to return a IMF formatted string date
* RFC: https://tools.ietf.org/html/rfc7231#section-7.1.1.1
* Formats the given date to IMF date time format. (Reference:
* https://tools.ietf.org/html/rfc7231#section-7.1.1.1).
* IMF is the time format to use when generating times in HTTP
* headers. The time being formatted must be in UTC for Format to
* generate the correct format.
*
* @example
* ```ts
* import { toIMF } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* toIMF(new Date(0)); // => returns "Thu, 01 Jan 1970 00:00:00 GMT"
* ```
* @param date Date to parse
* @return IMF date formatted string
*/
@ -130,8 +260,20 @@ export function toIMF(date: Date): string {
}
/**
* Check given year is a leap year or not.
* based on : https://docs.microsoft.com/en-us/office/troubleshoot/excel/determine-a-leap-year
* Returns whether the given date or year (in number) is a leap year or not.
* based on: https://docs.microsoft.com/en-us/office/troubleshoot/excel/determine-a-leap-year
*
* @example
* ```ts
* import { isLeap } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* isLeap(new Date("1970-01-01")); // => returns false
* isLeap(new Date("1972-01-01")); // => returns true
* isLeap(new Date("2000-01-01")); // => returns true
* isLeap(new Date("2100-01-01")); // => returns false
* isLeap(1972); // => returns true
* ```
*
* @param year year in number or Date format
*/
export function isLeap(year: Date | number): boolean {
@ -159,18 +301,36 @@ export type DifferenceOptions = {
};
/**
* Calculate difference between two dates.
* Returns the difference of the 2 given dates in the given units. If the units
* are omitted, it returns the difference in the all available units.
*
* @example
* ```ts
* import { difference } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* const date0 = new Date("2018-05-14");
* const date1 = new Date("2020-05-13");
*
* difference(date0, date1, { units: ["days", "months", "years"] });
* // => returns { days: 730, months: 23, years: 1 }
*
* difference(date0, date1);
* // => returns {
* // milliseconds: 63072000000,
* // seconds: 63072000,
* // minutes: 1051200,
* // hours: 17520,
* // days: 730,
* // weeks: 104,
* // months: 23,
* // quarters: 5,
* // years: 1
* // }
* ```
*
* @param from Year to calculate difference
* @param to Year to calculate difference with
* @param options Options for determining how to respond
*
* example :
*
* ```typescript
* import * as datetime from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
*
* datetime.difference(new Date("2020/1/1"),new Date("2020/2/2"),{ units : ["days","months"] })
* ```
*/
export function difference(
from: Date,

View File

@ -1,166 +0,0 @@
# Dotenv handling for deno.
## Usage
Setup a `.env` file in the root of your project.
```sh
# .env
GREETING=hello world
```
Then import the configuration using the `config` function.
```ts
// app.ts
import { config } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
console.log(await config());
```
Then run your app.
```
> deno run --allow-env --allow-read app.ts
{ GREETING: "hello world" }
```
### Options
- `path?: string`: Optional path to `.env` file. Defaults to `./.env`.
- `export?: boolean`: Set to `true` to export all `.env` variables to the
current processes environment. Variables are then accessable via
`Deno.env.get(<key>)`. Defaults to `false`.
- `safe?: boolean`: Set to `true` to ensure that all necessary environment
variables are defined after reading from `.env`. It will read `.env.example`
to get the list of needed variables.
- `example?: string`: Optional path to `.env.example` file. Defaults to
`./.env.example`.
- `allowEmptyValues?: boolean`: Set to `true` to allow required env variables to
be empty. Otherwise it will throw an error if any variable is empty. Defaults
to `false`.
- `defaults?: string`: Optional path to `.env.defaults` file which defaults to
`./.env.defaults`.
- `restrictEnvAccessTo?: Array<string>`: Optional list of Env variables to read
from process. Alternatively the complete Env is looked up. This allows to
permit access to only specific Env variables with `--allow-env=ENV_VAR_NAME`.
### Auto loading
`load.ts` automatically loads the local `.env` file on import and exports it to
the process environment:
```sh
# .env
GREETING=hello world
```
```ts
// app.ts
import "https://deno.land/std@$STD_VERSION/dotenv/load.ts";
console.log(Deno.env.get("GREETING"));
```
```
> deno run --allow-env --allow-read app.ts
hello world
```
### Safe Mode
To enable safe mode, create a `.env.example` file in the root of the project.
```sh
# .env.example
GREETING=
```
Then import the configuration with `safe` option set to `true`.
```ts
// app.ts
import { config } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
console.log(await config({ safe: true }));
```
If any of the defined variables is not in `.env`, an error will occur. This
method is preferred because it prevents runtime errors in a production
application due to improper configuration.
Another way to supply required variables is externally, like so:
```sh
GREETING="hello world" deno run --allow-env app.ts
```
## Default Values
Default values can be easily added via creating a `.env.defaults` file and using
the same format as an`.env` file.
```sh
# .env.defaults
# Will not be set if GREETING is set in base .env file
GREETING="a secret to everybody"
```
## Parsing Rules
The parsing engine currently supports the following rules:
- Variables that already exist in the environment are not overridden with
`export: true`
- `BASIC=basic` becomes `{ BASIC: "basic" }`
- empty lines are skipped
- lines beginning with `#` are treated as comments
- empty values become empty strings (`EMPTY=` becomes `{ EMPTY: "" }`)
- single and double quoted values are escaped (`SINGLE_QUOTE='quoted'` becomes
`{ SINGLE_QUOTE: "quoted" }`)
- new lines are expanded in double quoted values (`MULTILINE="new\nline"`
becomes
```
{ MULTILINE: "new
line" }
```
- inner quotes are maintained (think JSON) (`JSON={"foo": "bar"}` becomes
`{ JSON: "{\"foo\": \"bar\"}" }`)
- whitespace is removed from both ends of unquoted values (see more on
[`trim`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim))
(`FOO= some value` becomes `{ FOO: "some value" }`)
- whitespace is preserved on both ends of quoted values (`FOO=" some value "`
becomes `{ FOO: " some value " }`)
- dollar sign with an environment key in or without curly braces in unquoted
values will expand the environment key (`KEY=$KEY` or `KEY=${KEY}` becomes
`{ KEY: "<KEY_VALUE_FROM_ENV>" }`)
- escaped dollar sign with an environment key in unquoted values will escape the
environment key rather than expand (`KEY=\$KEY` becomes `{ KEY: "\\$KEY" }`)
- colon and a minus sign with a default value(which can also be another expand
value) in expanding construction in unquoted values will first attempt to
expand the environment key. If its not found, then it will return the default
value (`KEY=${KEY:-default}` If KEY exists it becomes
`{ KEY: "<KEY_VALUE_FROM_ENV>" }` If not, then it becomes
`{ KEY: "default" }`. Also there is possible to do this case
`KEY=${NO_SUCH_KEY:-${EXISTING_KEY:-default}}` which becomes
`{ KEY: "<EXISTING_KEY_VALUE_FROM_ENV>" }`)
## Stringify
```ts
import { stringify } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
const string = stringify({ GREETING: "hello world" });
console.log(string);
/*
GREETING='hello world'
*/
```
## Credit
- Inspired by the node module [`dotenv`](https://github.com/motdotla/dotenv)and
[`dotenv-expand`](https://github.com/motdotla/dotenv-expand).

View File

@ -1,6 +1,91 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
/**
* Load environment variables from `.env` files.
* Inspired by the node module [`dotenv`](https://github.com/motdotla/dotenv) and
* [`dotenv-expand`](https://github.com/motdotla/dotenv-expand).
*
* ```sh
* # .env
* GREETING=hello world
* ```
*
* Then import the configuration using the `config` function.
*
* ```ts
* // app.ts
* import { config } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
*
* console.log(await config());
* ```
*
* Then run your app.
*
* ```sh
* > deno run --allow-env --allow-read app.ts
* { GREETING: "hello world" }
* ```
*
* ## Auto loading
*
* `load.ts` automatically loads the local `.env` file on import and exports it to
* the process environment:
*
* ```sh
* # .env
* GREETING=hello world
* ```
*
* ```ts
* // app.ts
* import "https://deno.land/std@$STD_VERSION/dotenv/load.ts";
*
* console.log(Deno.env.get("GREETING"));
* ```
*
* ```sh
* > deno run --allow-env --allow-read app.ts
* hello world
* ```
*
* ## Parsing Rules
*
* The parsing engine currently supports the following rules:
*
* - Variables that already exist in the environment are not overridden with
* `export: true`
* - `BASIC=basic` becomes `{ BASIC: "basic" }`
* - empty lines are skipped
* - lines beginning with `#` are treated as comments
* - empty values become empty strings (`EMPTY=` becomes `{ EMPTY: "" }`)
* - single and double quoted values are escaped (`SINGLE_QUOTE='quoted'` becomes
* `{ SINGLE_QUOTE: "quoted" }`)
* - new lines are expanded in double quoted values (`MULTILINE="new\nline"`
* becomes
*
* ```
* { MULTILINE: "new\nline" }
* ```
*
* - inner quotes are maintained (think JSON) (`JSON={"foo": "bar"}` becomes
* `{ JSON: "{\"foo\": \"bar\"}" }`)
* - whitespace is removed from both ends of unquoted values (see more on
* [`trim`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim))
* (`FOO= some value` becomes `{ FOO: "some value" }`)
* - whitespace is preserved on both ends of quoted values (`FOO=" some value "`
* becomes `{ FOO: " some value " }`)
* - dollar sign with an environment key in or without curly braces in unquoted
* values will expand the environment key (`KEY=$KEY` or `KEY=${KEY}` becomes
* `{ KEY: "<KEY_VALUE_FROM_ENV>" }`)
* - escaped dollar sign with an environment key in unquoted values will escape the
* environment key rather than expand (`KEY=\$KEY` becomes `{ KEY: "\\$KEY" }`)
* - colon and a minus sign with a default value(which can also be another expand
* value) in expanding construction in unquoted values will first attempt to
* expand the environment key. If its not found, then it will return the default
* value (`KEY=${KEY:-default}` If KEY exists it becomes
* `{ KEY: "<KEY_VALUE_FROM_ENV>" }` If not, then it becomes
* `{ KEY: "default" }`. Also there is possible to do this case
* `KEY=${NO_SUCH_KEY:-${EXISTING_KEY:-default}}` which becomes
* `{ KEY: "<EXISTING_KEY_VALUE_FROM_ENV>" }`)
*
* @module
*/
@ -14,12 +99,62 @@ export interface DotenvConfig {
type StringList = Array<string> | undefined;
export interface ConfigOptions {
/** Optional path to `.env` file.
*
* @default {"./.env"}
*/
path?: string;
/**
* Set to `true` to export all `.env` variables to the current processes
* environment. Variables are then accessable via `Deno.env.get(<key>)`.
*
* @default {false}
*/
export?: boolean;
/**
* Set to `true` to ensure that all necessary environment variables are
* defined after reading from `.env`. It will read {@linkcode example} to get the
* list of needed variables.
*
* If any of the defined variables is not in `.env`, an error will occur. This
* method is preferred because it prevents runtime errors in a production
* application due to improper configuration.
* Another way to supply required variables is externally, like so:
*
* ```sh
* GREETING="hello world" deno run --allow-env app.ts
* ```
*/
safe?: boolean;
/** Optional path to `.env.example` file.
*
* @default {"./.env.example"}
*/
example?: string;
/**
* Set to `true` to allow required env variables to be empty. Otherwise, it
* will throw an error if any variable is empty.
*
* @default {false}
*/
allowEmptyValues?: boolean;
/**
* Path to `.env.defaults` file which is used to define default values.
*
* ```sh
* # .env.defaults
* # Will not be set if GREETING is set in base .env file
* GREETING="a secret to everybody"
* ```
*
* @default {"./.env.defaults"}
*/
defaults?: string;
/**
* List of Env variables to read from process. By default, the complete Env is
* looked up. This allows to permit access to only specific Env variables with
* `--allow-env=ENV_VAR_NAME`.
*/
restrictEnvAccessTo?: StringList;
}
@ -279,14 +414,16 @@ function expand(str: string, variablesMap: { [key: string]: string }): string {
}
/**
* @param object object to be stringified
* @returns string of object
* @example
* ```ts
* import { stringify } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
*
* const object = { GREETING: "hello world" };
* const string = stringify(object);
* const string = stringify(object); // GREETING='hello world'
* ```
*
* @param object object to be stringified
* @returns string of object
*/
export function stringify(object: DotenvConfig) {
const lines: string[] = [];

View File

@ -1,952 +0,0 @@
# encoding
Helper module for dealing with external data structures.
- [`ascii85`](#ascii85)
- [`base32`](#base32)
- [`base64`](#base64)
- [`base64url`](#base64url)
- [`binary`](#binary)
- [`csv`](#csv)
- [`front matter`](#front-matter)
- [`JSON streaming`](#json-streaming)
- [`jsonc`](#jsonc)
- [`toml`](#toml)
- [`yaml`](#yaml)
## Binary
Implements equivalent methods to Go's `encoding/binary` package.
Available Functions:
- `sizeof(dataType: DataTypes): number`
- `getNBytes(r: Deno.Reader, n: number): Promise<Uint8Array>`
- `varnum(b: Uint8Array, o: VarnumOptions = {}): number | null`
- `varbig(b: Uint8Array, o: VarbigOptions = {}): bigint | null`
- `putVarnum(b: Uint8Array, x: number, o: VarnumOptions = {}): number`
- `putVarbig(b: Uint8Array, x: bigint, o: VarbigOptions = {}): number`
- `readVarnum(r: Deno.Reader, o: VarnumOptions = {}): Promise<number>`
- `readVarbig(r: Deno.Reader, o: VarbigOptions = {}): Promise<bigint>`
- `writeVarnum(w: Deno.Writer, x: number, o: VarnumOptions = {}): Promise<number>`
- `writeVarbig(w: Deno.Writer, x: bigint, o: VarbigOptions = {}): Promise<number>`
## CSV
### API
#### `readMatrix`
Parse the CSV from the `reader` with the options provided and return
`string[][]`.
#### `parse`
Parse the CSV string/buffer with the options provided. The result of this
function is as follows:
- If you don't provide `opt.skipFirstRow` and `opt.columns`, it returns
`string[][]`.
- If you provide `opt.skipFirstRow` or `opt.columns` it returns
`Record<string, unknown>[]`.
##### `ParseOptions`
- **`skipFirstRow: boolean;`**: If you provide `skipFirstRow: true` and
`columns`, the first line will be skipped. If you provide `skipFirstRow: true`
but not `columns`, the first line will be skipped and used as header
definitions.
- **`columns: string[] | ColumnOptions[];`**: If you provide `string[]` or
`ColumnOptions[]`, those names will be used for header definition.
##### `ColumnOptions`
- **`name: string;`**: Name of the header to be used as property.
##### `ReadOptions`
- **`comma?: string;`**: Character which separates values. Default: `","`.
- **`comment?: string;`**: Character to start a comment. Default: `"#"`.
- **`trimLeadingSpace?: boolean;`**: Flag to trim the leading space of the
value. Default: `false`.
- **`lazyQuotes?: boolean;`**: Allow unquoted quote in a quoted field or non
double quoted quotes in quoted field. Default: `false`.
- **`fieldsPerRecord?`**: Enabling the check of fields for each row. If == 0,
first row is used as referral for the number of fields.
#### `stringify`
- **`data`** is the source data to stringify. It's an array of items which are
plain objects or arrays.
`DataItem: Record<string, unknown> | unknown[]`
```ts
const data = [
{
name: "Deno",
repo: { org: "denoland", name: "deno" },
runsOn: ["Rust", "TypeScript"],
},
];
```
- **`columns`** is a list of instructions for how to target and transform the
data for each column of output. This is also where you can provide an explicit
header name for the column.
`Column`:
- The most essential aspect of a column is accessing the property holding the
data for that column on each object in the data array. If that member is at
the top level, `Column` can simply be a property accessor, which is either a
`string` (if it's a plain object) or a `number` (if it's an array).
```ts
const columns = [
"name",
];
```
Each property accessor will be used as the header for the column:
| name |
| :--: |
| Deno |
- If the required data is not at the top level (it's nested in other
objects/arrays), then a simple property accessor won't work, so an array of
them will be required.
```ts
const columns = [
["repo", "name"],
["repo", "org"],
];
```
When using arrays of property accessors, the header names inherit the value
of the last accessor in each array:
| name | org |
| :--: | :------: |
| deno | denoland |
- If a different column header is desired, then a `ColumnDetails` object type
can be used for each column:
- **`header?: string`** is the optional value to use for the column header
name
- **`prop: PropertyAccessor | PropertyAccessor[]`** is the property accessor
(`string` or `number`) or array of property accessors used to access the
data on each object
```ts
const columns = [
"name",
{
prop: ["runsOn", 0],
header: "language 1",
},
{
prop: ["runsOn", 1],
header: "language 2",
},
];
```
| name | language 1 | language 2 |
| :--: | :--------: | :--------: |
| Deno | Rust | TypeScript |
- **`options`** are options for the delimiter-separated output.
- **`headers?: boolean`**: Whether or not to include the row of headers.
Default: `true`
- **`separator?: string`**: Delimiter used to separate values. Examples:
- `","` _comma_ (Default)
- `"\t"` _tab_
- `"|"` _pipe_
- etc.
### Basic Usage
```ts
import { parse } from "https://deno.land/std@$STD_VERSION/encoding/csv.ts";
const string = "a,b,c\nd,e,f";
console.log(
parse(string, {
skipFirstRow: false,
}),
);
// output:
// [["a", "b", "c"], ["d", "e", "f"]]
```
```ts
import {
Column,
stringify,
} from "https://deno.land/std@$STD_VERSION/encoding/csv.ts";
type Character = {
age: number;
name: {
first: string;
last: string;
};
};
const data: Character[] = [
{
age: 70,
name: {
first: "Rick",
last: "Sanchez",
},
},
{
age: 14,
name: {
first: "Morty",
last: "Smith",
},
},
];
let columns: Column[] = [
["name", "first"],
"age",
];
console.log(stringify(data, { columns }));
// first,age
// Rick,70
// Morty,14
```
## TOML
This module parse TOML files. It follows as much as possible the
[TOML specs](https://toml.io/en/latest). Be sure to read the supported types as
not every specs is supported at the moment and the handling in TypeScript side
is a bit different.
### Supported types and handling
- :heavy_check_mark: [Keys](https://toml.io/en/latest#keys)
- :exclamation: [String](https://toml.io/en/latest#string)
- :heavy_check_mark: [Multiline String](https://toml.io/en/latest#string)
- :heavy_check_mark: [Literal String](https://toml.io/en/latest#string)
- :exclamation: [Integer](https://toml.io/en/latest#integer)
- :heavy_check_mark: [Float](https://toml.io/en/latest#float)
- :heavy_check_mark: [Boolean](https://toml.io/en/latest#boolean)
- :heavy_check_mark:
[Offset Date-time](https://toml.io/en/latest#offset-date-time)
- :heavy_check_mark:
[Local Date-time](https://toml.io/en/latest#local-date-time)
- :heavy_check_mark: [Local Date](https://toml.io/en/latest#local-date)
- :exclamation: [Local Time](https://toml.io/en/latest#local-time)
- :heavy_check_mark: [Table](https://toml.io/en/latest#table)
- :heavy_check_mark: [Inline Table](https://toml.io/en/latest#inline-table)
- :exclamation: [Array of Tables](https://toml.io/en/latest#array-of-tables)
:exclamation: _Supported with warnings see [Warning](#Warning)._
#### :warning: Warning
##### String
- Regex : Due to the spec, there is no flag to detect regex properly in a TOML
declaration. So the regex is stored as string.
##### Integer
For **Binary** / **Octal** / **Hexadecimal** numbers, they are stored as string
to be not interpreted as Decimal.
##### Local Time
Because local time does not exist in JavaScript, the local time is stored as a
string.
##### Inline Table
Inline tables are supported. See below:
```toml
animal = { type = { name = "pug" } }
## Output { animal: { type: { name: "pug" } } }
animal = { type.name = "pug" }
## Output { animal: { type : { name : "pug" } }
animal.as.leaders = "tosin"
## Output { animal: { as: { leaders: "tosin" } } }
"tosin.abasi" = "guitarist"
## Output { tosin.abasi: "guitarist" }
```
##### Array of Tables
At the moment only simple declarations like below are supported:
```toml
[[bin]]
name = "deno"
path = "cli/main.rs"
[[bin]]
name = "deno_core"
path = "src/foo.rs"
[[nib]]
name = "node"
path = "not_found"
```
will output:
```json
{
"bin": [
{ "name": "deno", "path": "cli/main.rs" },
{ "name": "deno_core", "path": "src/foo.rs" }
],
"nib": [{ "name": "node", "path": "not_found" }]
}
```
### Basic usage
```ts
import {
parse,
stringify,
} from "https://deno.land/std@$STD_VERSION/encoding/toml.ts";
const obj = {
bin: [
{ name: "deno", path: "cli/main.rs" },
{ name: "deno_core", path: "src/foo.rs" },
],
nib: [{ name: "node", path: "not_found" }],
};
const tomlString = stringify(obj);
console.log(tomlString);
// =>
// [[bin]]
// name = "deno"
// path = "cli/main.rs"
// [[bin]]
// name = "deno_core"
// path = "src/foo.rs"
// [[nib]]
// name = "node"
// path = "not_found"
const tomlObject = parse(tomlString);
console.log(tomlObject);
// =>
// {
// bin: [
// { name: "deno", path: "cli/main.rs" },
// { name: "deno_core", path: "src/foo.rs" }
// ],
// nib: [ { name: "node", path: "not_found" } ]
// }
```
## YAML
YAML parser / dumper for Deno.
Heavily inspired from [`js-yaml`](https://github.com/nodeca/js-yaml).
### Basic usage
`parse` parses the yaml string, and `stringify` dumps the given object to YAML
string.
```ts
import {
parse,
stringify,
} from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
const data = parse(`
foo: bar
baz:
- qux
- quux
`);
console.log(data);
// => { foo: "bar", baz: [ "qux", "quux" ] }
const yaml = stringify({ foo: "bar", baz: ["qux", "quux"] });
console.log(yaml);
// =>
// foo: bar
// baz:
// - qux
// - quux
```
If your YAML contains multiple documents in it, you can use `parseAll` for
handling it.
```ts
import { parseAll } from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
const data = parseAll(`
---
id: 1
name: Alice
---
id: 2
name: Bob
---
id: 3
name: Eve
`);
console.log(data);
// => [ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, { id: 3, name: "Eve" } ]
```
To handle `regexp`, and `undefined` types, use the `EXTENDED_SCHEMA`. Note that
functions are no longer supported for security reasons
```ts
import {
EXTENDED_SCHEMA,
parse,
} from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
const data = parse(
`
regexp:
simple: !!js/regexp foobar
modifiers: !!js/regexp /foobar/mi
undefined: !!js/undefined ~
# Disabled, see: https://github.com/denoland/deno_std/pull/1275
# function: !!js/function >
# function foobar() {
# return 'hello world!';
# }
`,
{ schema: EXTENDED_SCHEMA },
);
```
You can also use custom types by extending schemas.
```ts
import {
DEFAULT_SCHEMA,
parse,
Type,
} from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
const yaml = "...";
const MyYamlType = new Type("!myYamlType", {
kind: "sequence",
/* other type options here*/
});
const MY_SCHEMA = DEFAULT_SCHEMA.extend({ explicit: [MyYamlType] });
parse(yaml, { schema: MY_SCHEMA });
```
### API
#### `parse(str: string, opts?: ParserOption): unknown`
Parses the YAML string with a single document.
#### `parseAll(str: string, iterator?: Function, opts?: ParserOption): unknown`
Parses the YAML string with multiple documents. If the iterator is given, it's
applied to every document instead of returning the array of parsed objects.
#### `stringify(obj: object, opts?: DumpOption): string`
Serializes `object` as a YAML document.
### :warning: Limitations
- `binary` type is currently not stable.
### More example
See: https://github.com/nodeca/js-yaml/tree/master/examples
## JSON streaming
Streams JSON concatenated with line breaks or special characters. This module
supports the following formats:
- [JSON lines](https://jsonlines.org/)
- [NDJSON](http://ndjson.org/)
- [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464)
- [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON)
- JSON concatenated with any delimiter
### Basic usage
If you want to parse JSON separated by a delimiter, use `TextLineStream` (or
`TextDelimiterStream`) and `JsonParseStream`. `JsonParseStream` ignores chunks
consisting of spaces, tab characters, or newline characters .
```ts
// parse JSON lines or NDJSON
import { TextLineStream } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
import { JsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
const url =
"https://deno.land/std@$STD_VERSION/encoding/testdata/json/test.jsonl";
const { body } = await fetch(url);
const readable = body!
.pipeThrough(new TextDecoderStream()) // convert Uint8Array to string
.pipeThrough(new TextLineStream()) // transform into a stream where each chunk is divided by a newline
.pipeThrough(new JsonParseStream()); // parse each chunk as JSON
for await (const data of readable) {
console.log(data);
}
```
```ts
// parse JSON Text Sequences
import { TextDelimiterStream } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
import { JsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
const url =
"https://deno.land/std@$STD_VERSION/encoding/testdata/json/test.json-seq";
const { body } = await fetch(url);
const delimiter = "\x1E";
const readable = body!
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextDelimiterStream(delimiter)) // transform into a stream where each chunk is divided by a delimiter
.pipeThrough(new JsonParseStream());
for await (const data of readable) {
console.log(data);
}
```
If you want to parse
[Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON),
use `ConcatenatedJsonParseStream`.
```ts
import { ConcatenatedJsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
const url =
"https://deno.land/std@$STD_VERSION/encoding/testdata/json/test.concatenated-json";
const { body } = await fetch(url);
const readable = body!
.pipeThrough(new TextDecoderStream()) // convert Uint8Array to string
.pipeThrough(new ConcatenatedJsonParseStream()); // parse Concatenated JSON
for await (const data of readable) {
console.log(data);
}
```
Use `JsonStringifyStream` to transform streaming data to
[JSON lines](https://jsonlines.org/), [NDJSON](http://ndjson.org/),
[NDJSON](http://ndjson.org/) or
[Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON).
By default, `JsonStringifyStream` adds "\n" as a suffix after each chunk.
```ts
import { readableStreamFromIterable } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
const file = await Deno.open("./tmp.jsonl", { create: true, write: true });
readableStreamFromIterable([{ foo: "bar" }, { baz: 100 }])
.pipeThrough(new JsonStringifyStream()) // convert to JSON lines (ndjson)
.pipeThrough(new TextEncoderStream()) // convert a string to a Uint8Array
.pipeTo(file.writable)
.then(() => console.log("write success"));
```
If you want to use an arbitrary delimiter, specify prefix and suffix as options.
These are added before and after chunk after stringify. To convert to
[JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464), set the
prefix to the delimiter "\x1E" as options.
```ts
import { readableStreamFromIterable } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
const file = await Deno.open("./tmp.jsonl", { create: true, write: true });
readableStreamFromIterable([{ foo: "bar" }, { baz: 100 }])
.pipeThrough(new JsonStringifyStream({ prefix: "\x1E", suffix: "\n" })) // convert to JSON Text Sequences
.pipeThrough(new TextEncoderStream())
.pipeTo(file.writable)
.then(() => console.log("write success"));
```
If you want to stream [JSON lines](https://jsonlines.org/) from the server:
```ts
import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts";
import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
// A server that streams one line of JSON every second
serve(() => {
let intervalId: number | undefined;
const readable = new ReadableStream({
start(controller) {
// enqueue data once per second
intervalId = setInterval(() => {
controller.enqueue({ now: new Date() });
}, 1000);
},
cancel() {
clearInterval(intervalId);
},
});
const body = readable
.pipeThrough(new JsonStringifyStream()) // convert data to JSON lines
.pipeThrough(new TextEncoderStream()); // convert a string to a Uint8Array
return new Response(body);
});
```
## JSONC
JSONC (JSON with Comments) parser for Deno.
### API
#### `parse(text: string, options: { allowTrailingComma?: boolean; })`
Parses the JSONC string. Setting allowTrailingComma to false rejects trailing
commas in objects and arrays. If parsing fails, throw a SyntaxError.
### Basic usage
```ts
import * as JSONC from "https://deno.land/std@$STD_VERSION/encoding/jsonc.ts";
console.log(JSONC.parse('{"foo": "bar", } // comment')); //=> { foo: "bar" }
console.log(JSONC.parse('{"foo": "bar", } /* comment */')); //=> { foo: "bar" }
console.log(JSONC.parse('{"foo": "bar" } // comment', {
allowTrailingComma: false,
})); //=> { foo: "bar" }
```
## base32
[RFC4648 base32](https://tools.ietf.org/html/rfc4648#section-6) encoder/decoder
for Deno.
### Basic usage
`encode` encodes a `Uint8Array` to RFC4648 base32 representation, and `decode`
decodes the given RFC4648 base32 representation to a `Uint8Array`.
```ts
import {
decode,
encode,
} from "https://deno.land/std@$STD_VERSION/encoding/base32.ts";
const b32Repr = "RC2E6GA=";
const binaryData = decode(b32Repr);
console.log(binaryData);
// => Uint8Array [ 136, 180, 79, 24 ]
console.log(encode(binaryData));
// => RC2E6GA=
```
## base64
[RFC4648 base64](https://tools.ietf.org/html/rfc4648#section-4) encoder/decoder
for Deno.
### Basic usage
`encode` encodes a `Uint8Array` to RFC4648 base64 representation, and `decode`
decodes the given RFC4648 base64 representation to a `Uint8Array`.
```ts
import {
decode,
encode,
} from "https://deno.land/std@$STD_VERSION/encoding/base64.ts";
const b64Repr = "Zm9vYg==";
const binaryData = decode(b64Repr);
console.log(binaryData);
// => Uint8Array [ 102, 111, 111, 98 ]
console.log(encode(binaryData));
// => Zm9vYg==
```
## base64url
[RFC4648 base64url](https://datatracker.ietf.org/doc/html/rfc4648#section-5)
encoder/decoder for Deno.
### Basic usage
`encode` encodes a `Uint8Array` to RFC4648 base64url representation, and
`decode` decodes the given RFC4648 base64url representation to a `Uint8Array`.
```ts
import {
decode,
encode,
} from "https://deno.land/std@$STD_VERSION/encoding/base64url.ts";
const binary = new TextEncoder().encode("foobar");
const encoded = encode(binary);
console.log(encoded);
// => "Zm9vYmFy"
console.log(decode(encoded));
// => Uint8Array(6) [ 102, 111, 111, 98, 97, 114 ]
```
## ascii85
Ascii85/base85 encoder and decoder with support for multiple standards.
### Basic usage
`encode` encodes a `Uint8Array` to a ascii85 representation, and `decode`
decodes the given ascii85 representation to a `Uint8Array`.
```ts
import {
decode,
encode,
} from "https://deno.land/std@$STD_VERSION/encoding/ascii85.ts";
const a85Repr = "LpTqp";
const binaryData = decode(a85Repr);
console.log(binaryData);
// => Uint8Array [ 136, 180, 79, 24 ]
console.log(encode(binaryData));
// => LpTqp
```
### Specifying a standard and delimiter
By default all functions are using the most popular Adobe version of ascii85 and
not adding any delimiter. However, there are three more standards supported -
btoa (different delimiter and additional compression of 4 bytes equal to 32),
[Z85](https://rfc.zeromq.org/spec/32/) and
[RFC 1924](https://tools.ietf.org/html/rfc1924). It's possible to use a
different encoding by specifying it in `options` object as a second parameter.
Similarly, it's possible to make `encode` add a delimiter (`<~` and `~>` for
Adobe, `xbtoa Begin` and `xbtoa End` with newlines between the delimiters and
encoded data for btoa. Checksums for btoa are not supported. Delimiters are not
supported by other encodings.)
encoding examples:
```ts
import {
decode,
encode,
} from "https://deno.land/std@$STD_VERSION/encoding/ascii85.ts";
const binaryData = new Uint8Array([136, 180, 79, 24]);
console.log(encode(binaryData));
// => LpTqp
console.log(encode(binaryData, { standard: "Adobe", delimiter: true }));
// => <~LpTqp~>
console.log(encode(binaryData, { standard: "btoa", delimiter: true }));
/* => xbtoa Begin
LpTqp
xbtoa End */
console.log(encode(binaryData, { standard: "RFC 1924" }));
// => h_p`_
console.log(encode(binaryData, { standard: "Z85" }));
// => H{P}{
```
## hex
hexadecimal encoder/decoder for Deno.
### Basic usage
`encode` encodes a `Uint8Array` to hexadecimal `Uint8Array` with 2 * length, and
`decode` decodes the given hexadecimal `Uint8Array` to a `Uint8Array`.
```ts
import {
decode,
encode,
} from "https://deno.land/std@$STD_VERSION/encoding/hex.ts";
const binary = new TextEncoder().encode("abc");
const encoded = encode(binary);
console.log(encoded);
// => Uint8Array(6) [ 54, 49, 54, 50, 54, 51 ]
console.log(decode(encoded));
// => Uint8Array(3) [ 97, 98, 99 ]
```
## Front Matter
Extracts
[front matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/)
from strings.
Supported formats:
- [`YAML`](./front_matter/yaml.ts)
- [`TOML`](./front_matter/toml.ts)
- [`JSON`](./front_matter/json.ts)
### Basic usage
example.md
```
---
module: front_matter
tags:
- yaml
- toml
- json
---
deno is awesome
```
example.ts
```ts
import {
extract,
test,
} from "https://deno.land/std@$STD_VERSION/encoding/front_matter/any.ts";
const str = await Deno.readTextFile("./example.md");
if (test(str)) {
console.log(extract(str));
} else {
console.log("document doesn't contain front matter");
}
```
```
$ deno run ./example.ts
{
frontMatter: "module: front_matter\ntags:\n - yaml\n - toml\n - json",
body: "deno is awesome",
attrs: { module: "front_matter", tags: [ "yaml", "toml", "json" ] }
}
```
The above example recognizes any of the supported formats, extracts metadata and
parses accordingly. Please note that in this case both the [YAML](#yaml) and
[TOML](#toml) parsers will be imported as dependencies.
If you need only one specific format then you can import the file named
respectively from [here](./front_matter).
### Advanced usage
```ts
import {
createExtractor,
Format,
Parser,
test as _test,
} from "https://deno.land/std@$STD_VERSION/encoding/front_matter/mod.ts";
import { parse } from "https://deno.land/std@$STD_VERSION/encoding/toml.ts";
const extract = createExtractor({
[Format.TOML]: parse as Parser,
[Format.JSON]: JSON.parse as Parser,
});
export function test(str: string): boolean {
return _test(str, [Format.TOML, Format.JSON]);
}
```
In this setup `extract()` and `test()` will work with TOML and JSON and only.
This way the YAML parser is not loaded if not needed. You can cherry-pick which
combination of formats are you supporting based on your needs.
### Delimiters
#### YAML
```
---
these: are
---
```
```
---yaml
all: recognized
---
```
```
= yaml =
as: yaml
= yaml =
```
#### TOML
```
---toml
this = 'is'
---
```
```
= toml =
parsed = 'as'
toml = 'data'
= toml =
```
#### JSON
```
---json
{
"and": "this"
}
---
```
```
{
"is": "JSON"
}
```

View File

@ -21,6 +21,25 @@ export function parse(content: string, options?: ParseOptions): unknown {
/**
* Same as `parse()`, but understands multi-document sources.
* Applies iterator to each document if specified, or returns array of documents.
*
* @example
* ```ts
* import { parseAll } from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
*
* const data = parseAll(`
* ---
* id: 1
* name: Alice
* ---
* id: 2
* name: Bob
* ---
* id: 3
* name: Eve
* `);
* console.log(data);
* // => [ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, { id: 3, name: "Eve" } ]
* ```
*/
export function parseAll(
content: string,

View File

@ -4,8 +4,34 @@ import { Schema } from "../schema.ts";
import { regexp, undefinedType } from "../type/mod.ts";
import { def } from "./default.ts";
// Extends JS-YAML default schema with additional JavaScript types
// It is not described in the YAML specification.
/***
* Extends JS-YAML default schema with additional JavaScript types
* It is not described in the YAML specification.
* Functions are no longer supported for security reasons.
*
* @example
* ```ts
* import {
* EXTENDED_SCHEMA,
* parse,
* } from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
*
* const data = parse(
* `
* regexp:
* simple: !!js/regexp foobar
* modifiers: !!js/regexp /foobar/mi
* undefined: !!js/undefined ~
* # Disabled, see: https://github.com/denoland/deno_std/pull/1275
* # function: !!js/function >
* # function foobar() {
* # return 'hello world!';
* # }
* `,
* { schema: EXTENDED_SCHEMA },
* );
* ```
*/
export const extended = new Schema({
explicit: [regexp, undefinedType],
include: [def],

View File

@ -6,18 +6,50 @@
*
* This module is browser compatible.
*
* ## Specifying a standard and delimiter
*
* By default, all functions are using the most popular Adobe version of ascii85
* and not adding any delimiter. However, there are three more standards
* supported - btoa (different delimiter and additional compression of 4 bytes
* equal to 32), [Z85](https://rfc.zeromq.org/spec/32/) and
* [RFC 1924](https://tools.ietf.org/html/rfc1924). It's possible to use a
* different encoding by specifying it in `options` object as a second parameter.
*
* Similarly, it's possible to make `encode` add a delimiter (`<~` and `~>` for
* Adobe, `xbtoa Begin` and `xbtoa End` with newlines between the delimiters and
* encoded data for btoa. Checksums for btoa are not supported. Delimiters are not
* supported by other encodings.)
*
* @example
* ```ts
* import {
* decode,
* encode,
* } from "https://deno.land/std@$STD_VERSION/encoding/ascii85.ts";
*
* const a85Repr = "LpTqp";
*
* const binaryData = decode(a85Repr);
* console.log(binaryData);
* // => Uint8Array [ 136, 180, 79, 24 ]
*
* console.log(encode(binaryData));
* // => LpTqp
* ```
*
* @module
*/
export type Ascii85Standard = "Adobe" | "btoa" | "RFC 1924" | "Z85";
/**
* encoding/decoding options
* @property standard - characterset and delimiter (if supported and used). Defaults to Adobe
* @property delimiter - whether to use a delimiter (if supported) - "<~" and "~>" by default
*/
/** encoding/decoding options */
export interface Ascii85Options {
/** characterset and delimiter (if supported and used).
*
* @default {"Adobe"}
*/
standard?: Ascii85Standard;
/** whether to use a delimiter (if supported) - "<~" and "~>" by default */
delimiter?: boolean;
}
const rfc1924 =

View File

@ -9,6 +9,23 @@
*
* This module is browser compatible.
*
* @example
* ```ts
* import {
* decode,
* encode,
* } from "https://deno.land/std@$STD_VERSION/encoding/base32.ts";
*
* const b32Repr = "RC2E6GA=";
*
* const binaryData = decode(b32Repr);
* console.log(binaryData);
* // => Uint8Array [ 136, 180, 79, 24 ]
*
* console.log(encode(binaryData));
* // => RC2E6GA=
* ```
*
* @module
*/

View File

@ -6,6 +6,23 @@
*
* This module is browser compatible.
*
* @example
* ```ts
* import {
* decode,
* encode,
* } from "https://deno.land/std@$STD_VERSION/encoding/base64.ts";
*
* const b64Repr = "Zm9vYg==";
*
* const binaryData = decode(b64Repr);
* console.log(binaryData);
* // => Uint8Array [ 102, 111, 111, 98 ]
*
* console.log(encode(binaryData));
* // => Zm9vYg==
* ```
*
* @module
*/

View File

@ -6,6 +6,22 @@
*
* This module is browser compatible.
*
* @example
* ```ts
* import {
* decode,
* encode,
* } from "https://deno.land/std@$STD_VERSION/encoding/base64url.ts";
*
* const binary = new TextEncoder().encode("foobar");
* const encoded = encode(binary);
* console.log(encoded);
* // => "Zm9vYmFy"
*
* console.log(decode(encoded));
* // => Uint8Array(6) [ 102, 111, 111, 98, 97, 114 ]
* ```
*
* @module
*/

View File

@ -60,6 +60,70 @@ export type ColumnDetails = {
prop: PropertyAccessor | PropertyAccessor[];
};
/**
* The most essential aspect of a column is accessing the property holding the
* data for that column on each object in the data array. If that member is at
* the top level, `Column` can simply be a property accessor, which is either a
* `string` (if it's a plain object) or a `number` (if it's an array).
*
* ```ts
* const columns = [
* "name",
* ];
* ```
*
* Each property accessor will be used as the header for the column:
*
* | name |
* | :--: |
* | Deno |
*
* - If the required data is not at the top level (it's nested in other
* objects/arrays), then a simple property accessor won't work, so an array of
* them will be required.
*
* ```ts
* const columns = [
* ["repo", "name"],
* ["repo", "org"],
* ];
* ```
*
* When using arrays of property accessors, the header names inherit the value
* of the last accessor in each array:
*
* | name | org |
* | :--: | :------: |
* | deno | denoland |
*
* - If a different column header is desired, then a `ColumnDetails` object type
* can be used for each column:
*
* - **`header?: string`** is the optional value to use for the column header
* name
*
* - **`prop: PropertyAccessor | PropertyAccessor[]`** is the property accessor
* (`string` or `number`) or array of property accessors used to access the
* data on each object
*
* ```ts
* const columns = [
* "name",
* {
* prop: ["runsOn", 0],
* header: "language 1",
* },
* {
* prop: ["runsOn", 1],
* header: "language 2",
* },
* ];
* ```
*
* | name | language 1 | language 2 |
* | :--: | :--------: | :--------: |
* | Deno | Rust | TypeScript |
*/
export type Column = ColumnDetails | PropertyAccessor | PropertyAccessor[];
type NormalizedColumn = Omit<ColumnDetails, "header" | "prop"> & {
@ -138,24 +202,89 @@ function getValuesFromItem(
return values;
}
/**
* @param headers Whether or not to include the row of headers.
* Default: `true`
*
* @param separator Delimiter used to separate values. Examples:
* - `","` _comma_ (Default)
* - `"\t"` _tab_
* - `"|"` _pipe_
* - etc.
*/
export type StringifyOptions = {
/** Whether to include the row of headers or not.
*
* @default {true}
*/
headers?: boolean;
/**
* Delimiter used to separate values. Examples:
* - `","` _comma_
* - `"\t"` _tab_
* - `"|"` _pipe_
* - etc.
*
* @default {","}
*/
separator?: string;
/**
* a list of instructions for how to target and transform the data for each
* column of output. This is also where you can provide an explicit header
* name for the column.
*/
columns?: Column[];
};
/**
* @param data The array of objects to encode
* @param data The source data to stringify. It's an array of items which are
* plain objects or arrays.
*
* `DataItem: Record<string, unknown> | unknown[]`
*
* ```ts
* const data = [
* {
* name: "Deno",
* repo: { org: "denoland", name: "deno" },
* runsOn: ["Rust", "TypeScript"],
* },
* ];
* ```
*
* @example
* ```ts
* import {
* Column,
* stringify,
* } from "https://deno.land/std@$STD_VERSION/encoding/csv.ts";
*
* type Character = {
* age: number;
* name: {
* first: string;
* last: string;
* };
* };
*
* const data: Character[] = [
* {
* age: 70,
* name: {
* first: "Rick",
* last: "Sanchez",
* },
* },
* {
* age: 14,
* name: {
* first: "Morty",
* last: "Smith",
* },
* },
* ];
*
* let columns: Column[] = [
* ["name", "first"],
* "age",
* ];
*
* console.log(stringify(data, { columns }));
* // first,age
* // Rick,70
* // Morty,14
* ```
*
* @param options Output formatting options
*/
export function stringify(
@ -194,20 +323,35 @@ export function stringify(
export interface ParseOptions extends ReadOptions {
/**
* If you provide `skipFirstRow: true` and `columns`, the first line will be skipped.
* If you provide `skipFirstRow: true` but not `columns`, the first line will be skipped and used as header definitions.
* If you provide `skipFirstRow: true` and `columns`, the first line will be
* skipped.
* If you provide `skipFirstRow: true` but not `columns`, the first line will
* be skipped and used as header definitions.
*/
skipFirstRow?: boolean;
/**
* If you provide `string[]` or `ColumnOptions[]`, those names will be used for header definition.
*/
/** List of names used for header definition. */
columns?: string[];
}
/**
* Csv parse helper to manipulate data.
* Provides an auto/custom mapper for columns.
*
* @example
* ```ts
* import { parse } from "https://deno.land/std@$STD_VERSION/encoding/csv.ts";
* const string = "a,b,c\nd,e,f";
*
* console.log(
* await parse(string, {
* skipFirstRow: false,
* }),
* );
* // output:
* // [["a", "b", "c"], ["d", "e", "f"]]
* ```
*
* @param input Input to parse.
* @param opt options of the parser.
* @returns If you don't provide `opt.skipFirstRow` and `opt.columns`, it returns `string[][]`.

View File

@ -5,21 +5,33 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { assert } from "../../_util/asserts.ts";
/**
* @property separator - Character which separates values. Default: ','
* @property comment - Character to start a comment. Default: '#'
* @property trimLeadingSpace - Flag to trim the leading space of the value.
* Default: 'false'
* @property lazyQuotes - Allow unquoted quote in a quoted field or non double
* quoted quotes in quoted field. Default: 'false'
* @property fieldsPerRecord - Enabling the check of fields for each row.
* If == 0, first row is used as referral for the number of fields.
*/
export interface ReadOptions {
/** Character which separates values.
*
* @default {","}
*/
separator?: string;
/** Character to start a comment.
*
* @default {"#"}
*/
comment?: string;
/** Flag to trim the leading space of the value.
*
* @default {false}
*/
trimLeadingSpace?: boolean;
/**
* Allow unquoted quote in a quoted field or non-double-quoted quotes in
* quoted field.
*
* @default {false}
*/
lazyQuotes?: boolean;
/**
* Enabling the check of fields for each row. If == 0, first row is used as
* referral for the number of fields.
*/
fieldsPerRecord?: number;
}

View File

@ -2,12 +2,149 @@
// Copyright (c) Jason Campbell. MIT license
/**
* Extracts
* [front matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/)
* from strings.
*
* {@linkcode createExtractor}, {@linkcode recognize} and {@linkcode test} functions
* to handle many forms of front matter.
*
* Adapted from
* [jxson/front-matter](https://github.com/jxson/front-matter/blob/36f139ef797bd9e5196a9ede03ef481d7fbca18e/index.js).
*
* Supported formats:
*
* - [`YAML`](./front_matter/yaml.ts)
* - [`TOML`](./front_matter/toml.ts)
* - [`JSON`](./front_matter/json.ts)
*
* ### Basic usage
*
* example.md
*
* ```ignore
* ---
* module: front_matter
* tags:
* - yaml
* - toml
* - json
* ---
*
* deno is awesome
* ```
*
* example.ts
*
* ```ts
* import {
* extract,
* test,
* } from "https://deno.land/std@$STD_VERSION/encoding/front_matter/any.ts";
*
* const str = await Deno.readTextFile("./example.md");
*
* if (test(str)) {
* console.log(extract(str));
* } else {
* console.log("document doesn't contain front matter");
* }
* ```
*
* ```ignore
* $ deno run ./example.ts
* {
* frontMatter: "module: front_matter\ntags:\n - yaml\n - toml\n - json",
* body: "deno is awesome",
* attrs: { module: "front_matter", tags: [ "yaml", "toml", "json" ] }
* }
* ```
*
* The above example recognizes any of the supported formats, extracts metadata and
* parses accordingly. Please note that in this case both the [YAML](#yaml) and
* [TOML](#toml) parsers will be imported as dependencies.
*
* If you need only one specific format then you can import the file named
* respectively from [here](./front_matter).
*
* ### Advanced usage
*
* ```ts
* import {
* createExtractor,
* Format,
* Parser,
* test as _test,
* } from "https://deno.land/std@$STD_VERSION/encoding/front_matter/mod.ts";
* import { parse } from "https://deno.land/std@$STD_VERSION/encoding/toml.ts";
*
* const extract = createExtractor({
* [Format.TOML]: parse as Parser,
* [Format.JSON]: JSON.parse as Parser,
* });
*
* export function test(str: string): boolean {
* return _test(str, [Format.TOML, Format.JSON]);
* }
* ```
*
* In this setup `extract()` and `test()` will work with TOML and JSON and only.
* This way the YAML parser is not loaded if not needed. You can cherry-pick which
* combination of formats are you supporting based on your needs.
*
* ### Delimiters
*
* #### YAML
*
* ```ignore
* ---
* these: are
* ---
* ```
*
* ```ignore
* ---yaml
* all: recognized
* ---
* ```
*
* ```ignore
* = yaml =
* as: yaml
* = yaml =
* ```
*
* #### TOML
*
* ```ignore
* ---toml
* this = 'is'
* ---
* ```
*
* ```ignore
* = toml =
* parsed = 'as'
* toml = 'data'
* = toml =
* ```
*
* #### JSON
*
* ```ignore
* ---json
* {
* "and": "this"
* }
* ---
* ```
*
* ```ignore
* {
* "is": "JSON"
* }
* ```
*
* @module
*/

View File

@ -8,6 +8,22 @@
*
* This module is browser compatible.
*
* @example
* ```ts
* import {
* decode,
* encode,
* } from "https://deno.land/std@$STD_VERSION/encoding/hex.ts";
*
* const binary = new TextEncoder().encode("abc");
* const encoded = encode(binary);
* console.log(encoded);
* // => Uint8Array(6) [ 54, 49, 54, 50, 54, 51 ]
*
* console.log(decode(encoded));
* // => Uint8Array(3) [ 97, 98, 99 ]
* ```
*
* @module
*/

View File

@ -25,6 +25,8 @@ export interface ParseStreamOptions {
* This can be used to parse [JSON lines](https://jsonlines.org/), [NDJSON](http://ndjson.org/) and [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464).
* Chunks consisting of spaces, tab characters, or newline characters will be ignored.
*
* @example
* parse JSON lines or NDJSON
* ```ts
* import { TextLineStream } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
* import { JsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
@ -33,8 +35,29 @@ export interface ParseStreamOptions {
* const { body } = await fetch(url);
*
* const readable = body!
* .pipeThrough(new TextDecoderStream()) // convert Uint8Array to string
* .pipeThrough(new TextLineStream()) // transform into a stream where each chunk is divided by a newline
* .pipeThrough(new JsonParseStream()); // parse each chunk as JSON
*
* for await (const data of readable) {
* console.log(data);
* }
* ```
*
* @example
* parse JSON Text Sequences
* ```ts
* import { TextDelimiterStream } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
* import { JsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
*
* const url =
* "https://deno.land/std@$STD_VERSION/encoding/testdata/json/test.json-seq";
* const { body } = await fetch(url);
*
* const delimiter = "\x1E";
* const readable = body!
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new TextLineStream()) // or `new TextDelimiterStream(delimiter)`
* .pipeThrough(new TextDelimiterStream(delimiter)) // transform into a stream where each chunk is divided by a delimiter
* .pipeThrough(new JsonParseStream());
*
* for await (const data of readable) {
@ -71,6 +94,7 @@ function isBrankString(str: string) {
/**
* stream to parse [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON).
*
* @example
* ```ts
* import { ConcatenatedJsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
*
@ -78,8 +102,8 @@ function isBrankString(str: string) {
* const { body } = await fetch(url);
*
* const readable = body!
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new ConcatenatedJsonParseStream());
* .pipeThrough(new TextDecoderStream()) // convert Uint8Array to string
* .pipeThrough(new ConcatenatedJsonParseStream()); // parse Concatenated JSON
*
* for await (const data of readable) {
* console.log(data);

View File

@ -2,9 +2,15 @@
/** Optional object interface for `JsonStringifyStream`. */
export interface StringifyStreamOptions {
/** Prefix to be added after stringify. The default is "". */
/** Prefix to be added after stringify.
*
* @default {""}
*/
readonly prefix?: string;
/** Suffix to be added after stringify. The default is "\n". */
/** Suffix to be added after stringify.
*
* @default {"\n"}
*/
readonly suffix?: string;
/** Controls the buffer of the TransformStream used internally. Check https://developer.mozilla.org/en-US/docs/Web/API/TransformStream/TransformStream. */
readonly writableStrategy?: QueuingStrategy<unknown>;
@ -18,6 +24,7 @@ export interface StringifyStreamOptions {
* This can be used to stringify [JSON lines](https://jsonlines.org/), [NDJSON](http://ndjson.org/), [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464), and [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON).
* You can optionally specify a prefix and suffix for each chunk. The default prefix is "" and the default suffix is "\n".
*
* @example
* ```ts
* import { readableStreamFromIterable } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
* import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
@ -25,20 +32,58 @@ export interface StringifyStreamOptions {
* const file = await Deno.open("./tmp.jsonl", { create: true, write: true });
*
* readableStreamFromIterable([{ foo: "bar" }, { baz: 100 }])
* .pipeThrough(new JsonStringifyStream())
* .pipeThrough(new JsonStringifyStream()) // convert to JSON lines (ndjson)
* .pipeThrough(new TextEncoderStream()) // convert a string to a Uint8Array
* .pipeTo(file.writable)
* .then(() => console.log("write success"));
* ```
*
* @example
* To convert to [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464), set the
* prefix to the delimiter "\x1E" as options.
* ```ts
* import { readableStreamFromIterable } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
* import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
*
* const file = await Deno.open("./tmp.jsonl", { create: true, write: true });
*
* readableStreamFromIterable([{ foo: "bar" }, { baz: 100 }])
* .pipeThrough(new JsonStringifyStream({ prefix: "\x1E", suffix: "\n" })) // convert to JSON Text Sequences
* .pipeThrough(new TextEncoderStream())
* .pipeTo(file.writable)
* .then(() => console.log("write success"));
* ```
*
* @example
* If you want to stream [JSON lines](https://jsonlines.org/) from the server:
* ```ts
* import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts";
* import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
*
* // A server that streams one line of JSON every second
* serve(() => {
* let intervalId: number | undefined;
* const readable = new ReadableStream({
* start(controller) {
* // enqueue data once per second
* intervalId = setInterval(() => {
* controller.enqueue({ now: new Date() });
* }, 1000);
* },
* cancel() {
* clearInterval(intervalId);
* },
* });
*
* const body = readable
* .pipeThrough(new JsonStringifyStream()) // convert data to JSON lines
* .pipeThrough(new TextEncoderStream()); // convert a string to a Uint8Array
*
* return new Response(body);
* });
* ```
*/
export class JsonStringifyStream extends TransformStream<unknown, string> {
/**
* @param options
* @param options.prefix Prefix to be added after stringify. The default is "".
* @param options.suffix Suffix to be added after stringify. The default is "\n".
* @param options.writableStrategy Controls the buffer of the TransformStream used internally. Check https://developer.mozilla.org/en-US/docs/Web/API/TransformStream/TransformStream.
* @param options.readableStrategy Controls the buffer of the TransformStream used internally. Check https://developer.mozilla.org/en-US/docs/Web/API/TransformStream/TransformStream.
*/
constructor({
prefix = "",
suffix = "\n",

View File

@ -1,4 +1,28 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
/***
* Streams JSON concatenated with line breaks or special characters. This module
* supports the following formats:
* - [JSON lines](https://jsonlines.org/)
* - [NDJSON](http://ndjson.org/)
* - [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464)
* - [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON)
* - JSON concatenated with any delimiter
*
* If you want to parse JSON separated by a delimiter, use {@linkcode TextLineStream}
* (or {@linkcode TextDelimiterStream}) and {@linkcode JsonParseStream}.
* {@linkcode JsonParseStream} ignores chunks consisting of spaces, tab
* characters, or newline characters.
*
* If you want to parse
* [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON),
* use {@linkcode ConcatenatedJsonParseStream}.
*
* Use {@linkcode JsonStringifyStream} to transform streaming data to
* [JSON lines](https://jsonlines.org/), [NDJSON](http://ndjson.org/),
* [NDJSON](http://ndjson.org/) or
* [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON).
*/
export * from "./_parse.ts";
export * from "./_stringify.ts";

View File

@ -2,7 +2,7 @@
/** {@linkcode parse} function for parsing
* [JSONC](https://code.visualstudio.com/docs/languages/json#_json-with-comments)
* strings.
* (JSON with Comments) strings.
*
* This module is browser compatible.
*
@ -12,7 +12,10 @@
import { assert } from "../_util/asserts.ts";
export interface ParseOptions {
/** Allow trailing commas at the end of arrays and objects. (default: `true`) */
/** Allow trailing commas at the end of arrays and objects.
*
* @default {true}
*/
allowTrailingComma?: boolean;
}
@ -20,16 +23,19 @@ export interface ParseOptions {
* Converts a JSON with Comments (JSONC) string into an object.
* If a syntax error is found, throw a SyntaxError.
*
* @param text A valid JSONC string.
* @param options
* @param options.allowTrailingComma Allow trailing commas at the end of arrays and objects. (default: `true`)
* @example
*
* ```ts
* import * as JSONC from "https://deno.land/std@$STD_VERSION/encoding/jsonc.ts";
*
* JSONC.parse('{"foo": "bar", } // comment'); //=> { foo: "bar" }
* JSONC.parse('{"foo": "bar" } // comment', { allowTrailingComma: false }); //=> { foo: "bar" }
* console.log(JSONC.parse('{"foo": "bar", } // comment')); //=> { foo: "bar" }
* console.log(JSONC.parse('{"foo": "bar", } /* comment *\/')); //=> { foo: "bar" }
* console.log(JSONC.parse('{"foo": "bar" } // comment', {
* allowTrailingComma: false,
* })); //=> { foo: "bar" }
* ```
*
* @param text A valid JSONC string.
*/
export function parse(
text: string,

View File

@ -1,10 +1,138 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
/** {@linkcode parse} and {@linkcode stringify} for handling
* [TOML](https://toml.io/en/) encoded data.
/**
* {@linkcode parse} and {@linkcode stringify} for handling
* [TOML](https://toml.io/en/latest) encoded data. Be sure to read the supported
* types as not every spec is supported at the moment and the handling in
* TypeScript side is a bit different.
*
* ## Supported types and handling
*
* - :heavy_check_mark: [Keys](https://toml.io/en/latest#keys)
* - :exclamation: [String](https://toml.io/en/latest#string)
* - :heavy_check_mark: [Multiline String](https://toml.io/en/latest#string)
* - :heavy_check_mark: [Literal String](https://toml.io/en/latest#string)
* - :exclamation: [Integer](https://toml.io/en/latest#integer)
* - :heavy_check_mark: [Float](https://toml.io/en/latest#float)
* - :heavy_check_mark: [Boolean](https://toml.io/en/latest#boolean)
* - :heavy_check_mark:
* [Offset Date-time](https://toml.io/en/latest#offset-date-time)
* - :heavy_check_mark:
* [Local Date-time](https://toml.io/en/latest#local-date-time)
* - :heavy_check_mark: [Local Date](https://toml.io/en/latest#local-date)
* - :exclamation: [Local Time](https://toml.io/en/latest#local-time)
* - :heavy_check_mark: [Table](https://toml.io/en/latest#table)
* - :heavy_check_mark: [Inline Table](https://toml.io/en/latest#inline-table)
* - :exclamation: [Array of Tables](https://toml.io/en/latest#array-of-tables)
*
* :exclamation: _Supported with warnings see [Warning](#Warning)._
*
* ### :warning: Warning
*
* #### String
*
* - Regex : Due to the spec, there is no flag to detect regex properly in a TOML
* declaration. So the regex is stored as string.
*
* #### Integer
*
* For **Binary** / **Octal** / **Hexadecimal** numbers, they are stored as string
* to be not interpreted as Decimal.
*
* #### Local Time
*
* Because local time does not exist in JavaScript, the local time is stored as a
* string.
*
* #### Inline Table
*
* Inline tables are supported. See below:
*
* ```toml
* animal = { type = { name = "pug" } }
* ## Output { animal: { type: { name: "pug" } } }
* animal = { type.name = "pug" }
* ## Output { animal: { type : { name : "pug" } }
* animal.as.leaders = "tosin"
* ## Output { animal: { as: { leaders: "tosin" } } }
* "tosin.abasi" = "guitarist"
* ## Output { tosin.abasi: "guitarist" }
* ```
*
* #### Array of Tables
*
* At the moment only simple declarations like below are supported:
*
* ```toml
* [[bin]]
* name = "deno"
* path = "cli/main.rs"
*
* [[bin]]
* name = "deno_core"
* path = "src/foo.rs"
*
* [[nib]]
* name = "node"
* path = "not_found"
* ```
*
* will output:
*
* ```json
* {
* "bin": [
* { "name": "deno", "path": "cli/main.rs" },
* { "name": "deno_core", "path": "src/foo.rs" }
* ],
* "nib": [{ "name": "node", "path": "not_found" }]
* }
* ```
*
* This module is browser compatible.
*
* @example
* ```ts
* import {
* parse,
* stringify,
* } from "https://deno.land/std@$STD_VERSION/encoding/toml.ts";
* const obj = {
* bin: [
* { name: "deno", path: "cli/main.rs" },
* { name: "deno_core", path: "src/foo.rs" },
* ],
* nib: [{ name: "node", path: "not_found" }],
* };
* const tomlString = stringify(obj);
* console.log(tomlString);
*
* // =>
* // [[bin]]
* // name = "deno"
* // path = "cli/main.rs"
*
* // [[bin]]
* // name = "deno_core"
* // path = "src/foo.rs"
*
* // [[nib]]
* // name = "node"
* // path = "not_found"
*
* const tomlObject = parse(tomlString);
* console.log(tomlObject);
*
* // =>
* // {
* // bin: [
* // { name: "deno", path: "cli/main.rs" },
* // { name: "deno_core", path: "src/foo.rs" }
* // ],
* // nib: [ { name: "node", path: "not_found" } ]
* // }
* ```
*
* @module
*/

View File

@ -1,12 +1,48 @@
// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
/** {@linkcode parse} and {@linkcode stringify} for handling
/**
* {@linkcode parse} and {@linkcode stringify} for handling
* [YAML](https://yaml.org/) encoded data.
*
* Ported from
* [js-yaml v3.13.1](https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da)
*
* If your YAML contains multiple documents in it, you can use {@linkcode parseAll} for
* handling it.
*
* To handle `regexp`, and `undefined` types, use {@linkcode EXTENDED_SCHEMA}.
* You can also use custom types by extending schemas.
*
* ## :warning: Limitations
* - `binary` type is currently not stable.
*
* For further examples see https://github.com/nodeca/js-yaml/tree/master/examples.
* @example
* ```ts
* import {
* parse,
* stringify,
* } from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
*
* const data = parse(`
* foo: bar
* baz:
* - qux
* - quux
* `);
* console.log(data);
* // => { foo: "bar", baz: [ "qux", "quux" ] }
*
* const yaml = stringify({ foo: "bar", baz: ["qux", "quux"] });
* console.log(yaml);
* // =>
* // foo: bar
* // baz:
* // - qux
* // - quux
* ```
*
* @module
*/

View File

@ -1,83 +0,0 @@
# flags
Command line arguments parser for Deno based on minimist.
# Example
```ts
import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
console.dir(parse(Deno.args));
```
```
$ deno run https://deno.land/std/examples/flags.ts -a beep -b boop
{ _: [], a: 'beep', b: 'boop' }
```
```
$ deno run https://deno.land/std/examples/flags.ts -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
{ _: [ 'foo', 'bar', 'baz' ],
x: 3,
y: 4,
n: 5,
a: true,
b: true,
c: true,
beep: 'boop' }
```
# API
## const parsedArgs = parse(args, options = {});
`parsedArgs._` contains all the arguments that didn't have an option associated
with them.
Numeric-looking arguments will be returned as numbers unless `options.string` or
`options.boolean` is set for that argument name.
Any arguments after `'--'` will not be parsed and will end up in `parsedArgs._`.
options can be:
- `options.string` - a string or array of strings argument names to always treat
as strings.
- `options.boolean` - a boolean, string or array of strings to always treat as
booleans. if `true` will treat all double hyphenated arguments without equal
signs as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`). All
`boolean` arguments will be set to `false` by default.
- `options.collect` - a string or array of strings argument names to always
treat as arrays. Collectable options can be used multiple times. All values
will be collected into an array. If a non collectable option is used multiple
times, the last value is used. All Collectable arguments will be set to `[]`
by default.
- `options.negatable` - a string or array of strings argument names which can be
negated by prefixing them with `--no-`, like `--no-config`.
- `options.alias` - an object mapping string names to strings or arrays of
string argument names to use as aliases.
- `options.default` - an object mapping string argument names to default values.
- `options.stopEarly` - when true, populate `parsedArgs._` with everything after
the first non-option.
- `options['--']` - when true, populate `parsedArgs._` with everything before
the `--` and `parsedArgs['--']` with everything after the `--`. Here's an
example:
```ts
// $ deno run example.ts -- a arg1
import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
console.dir(parse(Deno.args, { "--": false }));
// output: { _: [ "a", "arg1" ] }
console.dir(parse(Deno.args, { "--": true }));
// output: { _: [], --: [ "a", "arg1" ] }
```
- `options.unknown` - a function which is invoked with a command line parameter
not defined in the `options` configuration object. If the function returns
`false`, the unknown option is not added to `parsedArgs`.
By default, the flags module tries to determine the type of all arguments
automatically and the return type of the `parse` method will have an index
signature with `any` as value (`{ [x: string]: any }`).
If the `string`, `boolean` or `collect` option is set, the return value of the
`parse` method will be fully typed and the index signature of the return type
will change to `{ [x: string]: unknown }`.

View File

@ -5,6 +5,30 @@
*
* This module is browser compatible.
*
* @example
* ```ts
* import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
*
* console.dir(parse(Deno.args));
* ```
*
* ```sh
* $ deno run https://deno.land/std/examples/flags.ts -a beep -b boop
* { _: [], a: 'beep', b: 'boop' }
* ```
*
* ```sh
* $ deno run https://deno.land/std/examples/flags.ts -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
* { _: [ 'foo', 'bar', 'baz' ],
* x: 3,
* y: 4,
* n: 5,
* a: true,
* b: true,
* c: true,
* beep: 'boop' }
* ```
*
* @module
*/
import { assert } from "../_util/asserts.ts";
@ -229,9 +253,13 @@ export interface ParseOptions<
| undefined,
DD extends boolean | undefined = boolean | undefined,
> {
/** When `true`, populate the result `_` with everything before the `--` and
* the result `['--']` with everything after the `--`. Here's an example:
/**
* When `true`, populate the result `_` with everything before the `--` and
* the result `['--']` with everything after the `--`.
*
* @default {false}
*
* @example
* ```ts
* // $ deno run example.ts -- a arg1
* import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
@ -240,43 +268,55 @@ export interface ParseOptions<
* console.dir(parse(Deno.args, { "--": true }));
* // output: { _: [], --: [ "a", "arg1" ] }
* ```
*
* Defaults to `false`.
*/
"--"?: DD;
/** An object mapping string names to strings or arrays of string argument
* names to use as aliases. */
/**
* An object mapping string names to strings or arrays of string argument
* names to use as aliases.
*/
alias?: A;
/** A boolean, string or array of strings to always treat as booleans. If
/**
* A boolean, string or array of strings to always treat as booleans. If
* `true` will treat all double hyphenated arguments without equal signs as
* `boolean` (e.g. affects `--foo`, not `-f` or `--foo=bar`) */
* `boolean` (e.g. affects `--foo`, not `-f` or `--foo=bar`).
* All `boolean` arguments will be set to `false` by default.
*/
boolean?: B | ReadonlyArray<Extract<B, string>>;
/** An object mapping string argument names to default values. */
default?: D & Defaults<B, S>;
/** When `true`, populate the result `_` with everything after the first
* non-option. */
/**
* When `true`, populate the result `_` with everything after the first
* non-option.
*/
stopEarly?: boolean;
/** A string or array of strings argument names to always treat as strings. */
string?: S | ReadonlyArray<Extract<S, string>>;
/** A string or array of strings argument names to always treat as arrays.
/**
* A string or array of strings argument names to always treat as arrays.
* Collectable options can be used multiple times. All values will be
* collected into one array. If a non-collectable option is used multiple
* times, the last value is used. */
* times, the last value is used.
* All Collectable arguments will be set to `[]` by default.
*/
collect?: C | ReadonlyArray<Extract<C, string>>;
/** A string or array of strings argument names which can be negated
* by prefixing them with `--no-`, like `--no-config`. */
/**
* A string or array of strings argument names which can be negated
* by prefixing them with `--no-`, like `--no-config`.
*/
negatable?: N | ReadonlyArray<Extract<N, string>>;
/** A function which is invoked with a command line parameter not defined in
/**
* A function which is invoked with a command line parameter not defined in
* the `options` configuration object. If the function returns `false`, the
* unknown option is not added to `parsedArgs`. */
* unknown option is not added to `parsedArgs`.
*/
unknown?: (arg: string, key?: string, value?: unknown) => unknown;
}
@ -331,11 +371,26 @@ function hasKey(obj: NestedMapping, keys: string[]): boolean {
* considered a key-value pair. Any arguments which could not be parsed are
* available in the `_` property of the returned object.
*
* By default, the flags module tries to determine the type of all arguments
* automatically and the return type of the `parse` method will have an index
* signature with `any` as value (`{ [x: string]: any }`).
*
* If the `string`, `boolean` or `collect` option is set, the return value of
* the `parse` method will be fully typed and the index signature of the return
* type will change to `{ [x: string]: unknown }`.
*
* Any arguments after `'--'` will not be parsed and will end up in `parsedArgs._`.
*
* Numeric-looking arguments will be returned as numbers unless `options.string`
* or `options.boolean` is set for that argument name.
*
* @example
* ```ts
* import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
* const parsedArgs = parse(Deno.args);
* ```
*
* @example
* ```ts
* import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
* const parsedArgs = parse(["--foo", "--bar=baz", "./quux.txt"]);

View File

@ -3,20 +3,6 @@
This is very much a work-in-progress. I'm actively soliciting feedback. What
immediately follows are points for discussion.
If you are looking for the documentation proper, skip to:
"printf: prints formatted output"
and
"Colors"
below.
## Discussion
This is very much a work-in-progress. I'm actively soliciting feedback.
- What useful features are available in other languages apart from Golang and C?
- behaviour of `%v` verb. In Golang, this is a shortcut verb to "print the
@ -28,8 +14,9 @@ This is very much a work-in-progress. I'm actively soliciting feedback.
`inspect` output is not defined, however. This may be problematic if using
this code on other platforms (and expecting interoperability). To my
knowledge, no suitable specification of object representation aside from JSON
and `toString` exist. ( Aside: see "[Common object formats][3]" in the
"Console Living Standard" which basically says "do whatever" )
and `toString` exist. ( Aside: see
"[Common object formats](https://console.spec.whatwg.org/#object-formats)" in
the "Console Living Standard" which basically says "do whatever" )
- `%j` verb. This is an extension particular to this implementation. Currently
not very sophisticated, it just runs `JSON.stringify` on the argument.
@ -58,236 +45,3 @@ This is very much a work-in-progress. I'm actively soliciting feedback.
- some flags that are potentially applicable ( POSIX long and unsigned modifiers
are not likely useful) are missing, namely %q (print quoted), %U (unicode
format)
# printf: prints formatted output
sprintf converts and formats a variable number of arguments as is specified by a
`format string`. In it's basic form, a format string may just be a literal. In
case arguments are meant to be formatted, a `directive` is contained in the
format string, preceded by a '%' character:
%<verb>
E.g. the verb `s` indicates the directive should be replaced by the string
representation of the argument in the corresponding position of the argument
list. E.g.:
Hello %s!
applied to the arguments "World" yields "Hello World!".
The meaning of the format string is modelled after [POSIX][1] format strings as
well as well as [Golang format strings][2]. Both contain elements specific to
the respective programming language that don't apply to JavaScript, so they can
not be fully supported. Furthermore we implement some functionality that is
specific to JS.
## Verbs
The following verbs are supported:
| Verb | Meaning |
| ----- | -------------------------------------------------------------- |
| `%` | print a literal percent |
| `t` | evaluate arg as boolean, print `true` or `false` |
| `b` | eval as number, print binary |
| `c` | eval as number, print character corresponding to the codePoint |
| `o` | eval as number, print octal |
| `x X` | print as hex (ff FF), treat string as list of bytes |
| `e E` | print number in scientific/exponent format 1.123123e+01 |
| `f F` | print number as float with decimal point and no exponent |
| `g G` | use %e %E or %f %F depending on size of argument |
| `s` | interpolate string |
| `T` | type of arg, as returned by `typeof` |
| `v` | value of argument in 'default' format (see below) |
| `j` | argument as formatted by `JSON.stringify` |
## Width and Precision
Verbs may be modified by providing them with width and precision, either or both
may be omitted:
%9f width 9, default precision
%.9f default width, precision 9
%8.9f width 8, precision 9
%8.f width 9, precision 0
In general, 'width' describes the minimum length of the output, while
'precision' limits the output.
| verb | precision |
| --------- | --------------------------------------------------------------- |
| `t` | n/a |
| `b c o` | n/a |
| `x X` | n/a for number, strings are truncated to p bytes(!) |
| `e E f F` | number of places after decimal, default 6 |
| `g G` | set maximum number of digits |
| `s` | truncate input |
| `T` | truncate |
| `v` | truncate, or depth if used with # see "'default' format", below |
| `j` | n/a |
Numerical values for width and precision can be substituted for the `*` char, in
which case the values are obtained from the next args, e.g.:
sprintf("%*.*f", 9, 8, 456.0)
is equivalent to:
sprintf("%9.8f", 456.0)
## Flags
The effects of the verb may be further influenced by using flags to modify the
directive:
| Flag | Verb | Meaning |
| ----- | --------- | -------------------------------------------------------------------------- |
| `+` | numeric | always print sign |
| `-` | all | pad to the right (left justify) |
| `#` | | alternate format |
| `#` | `b o x X` | prefix with `0b 0 0x` |
| `#` | `g G` | don't remove trailing zeros |
| `#` | `v` | ues output of `inspect` instead of `toString` |
| `' '` | | space character |
| `' '` | `x X` | leave spaces between bytes when printing string |
| `' '` | `d` | insert space for missing `+` sign character |
| `0` | all | pad with zero, `-` takes precedence, sign is appended in front of padding |
| `<` | all | format elements of the passed array according to the directive (extension) |
## 'default' format
The default format used by `%v` is the result of calling `toString()` on the
relevant argument. If the `#` flags is used, the result of calling `inspect()`
is interpolated. In this case, the precision, if set is passed to `inspect()` as
the 'depth' config parameter.
## Positional arguments
Arguments do not need to be consumed in the order they are provided and may be
consumed more than once. E.g.:
sprintf("%[2]s %[1]s", "World", "Hello")
returns "Hello World". The presence of a positional indicator resets the arg
counter allowing args to be reused:
sprintf("dec[%d]=%d hex[%[1]d]=%x oct[%[1]d]=%#o %s", 1, 255, "Third")
returns `dec[1]=255 hex[1]=0xff oct[1]=0377 Third`
Width and precision my also use positionals:
"%[2]*.[1]*d", 1, 2
This follows the golang conventions and not POSIX.
## Errors
The following errors are handled:
Incorrect verb:
S("%h", "") %!(BAD VERB 'h')
Too few arguments:
S("%d") %!(MISSING 'd')"
# Colors
Adds functions used for displaying colored text.
## Usage
```typescript
import {
bgBlue,
bgRgb24,
bgRgb8,
bold,
italic,
red,
rgb24,
rgb8,
} from "https://deno.land/std@$STD_VERSION/fmt/colors.ts";
console.log(bgBlue(italic(red(bold("Hello, World!")))));
// also supports 8bit colors
console.log(rgb8("Hello, World!", 42));
console.log(bgRgb8("Hello, World!", 42));
// and 24bit rgb
console.log(rgb24("Hello, World!", {
r: 41,
g: 42,
b: 43,
}));
console.log(bgRgb24("Hello, World!", {
r: 41,
g: 42,
b: 43,
}));
```
# Pretty Bytes
> Convert bytes to a human readable string: 1337 → 1.34 kB
A utility for displaying file sizes for humans.
Note: This module was ported from
[pretty-bytes](https://github.com/sindresorhus/pretty-bytes).
## Usage
```ts
import { format } from "https://deno.land/std@$STD_VERSION/fmt/bytes.ts";
format(1337);
//=> '1.34 kB'
format(100);
//=> '100 B'
// Display with units of bits
format(1337, { bits: true });
//=> '1.34 kbit'
// Display file size differences
format(42, { signed: true });
//=> '+42 B'
// Localized output using German locale
format(1337, { locale: "de" });
//=> '1,34 kB'
```
# Pretty Duration
Format milliseconds to time duration.
```ts
import { format } from "https://deno.land/std@$STD_VERSION/fmt/duration.ts";
// "00:00:01:39:674:000:000"
format(99674, { style: "digital" });
// "0d 0h 1m 39s 674ms 0µs 0ns"
format(99674);
// "1m 39s 674ms"
format(99674, { ignoreZero: true });
// "1 minutes, 39 seconds, 674 milliseconds"
format(99674, { style: "full", ignoreZero: true });
```
[1]: https://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
[2]: https://golang.org/pkg/fmt/
[3]: https://console.spec.whatwg.org/#object-formats

View File

@ -5,9 +5,33 @@
/** Pretty print bytes.
*
* Based on [pretty-bytes](https://github.com/sindresorhus/pretty-bytes).
* A utility for displaying file sizes for humans.
*
* This module is browser compatible.
*
* @example
* ```ts
* import { format } from "https://deno.land/std@$STD_VERSION/fmt/bytes.ts";
*
* format(1337);
* //=> '1.34 kB'
*
* format(100);
* //=> '100 B'
*
* // Display with units of bits
* format(1337, { bits: true });
* //=> '1.34 kbit'
*
* // Display file size differences
* format(42, { signed: true });
* //=> '+42 B'
*
* // Localized output using German locale
* format(1337, { locale: "de" });
* //=> '1,34 kB'
* ```
*
* @module
*/
@ -20,9 +44,15 @@ type LocaleOptions = {
* @deprecated (will be removed after 0.170.0) use `FormatOptions` instead
*/
export interface PrettyBytesOptions {
/** Uses bits representation. Default is false. */
/** Uses bits representation.
*
* @default {false}
*/
bits?: boolean;
/** Uses binary bytes (e.g. kibibyte). Default is false. */
/** Uses binary bytes (e.g. kibibyte).
*
* @default {false}
*/
binary?: boolean;
/** Include plus sign for positive numbers. */
signed?: boolean;
@ -59,7 +89,7 @@ export function prettyBytes(num: number, options: FormatOptions = {}) {
}
/**
* Convert bytes to a human readable string: 1337 1.34 kB
* Convert bytes to a human-readable string: 1337 1.34 kB
*
* @param num The number to format
* @param options The options

View File

@ -7,14 +7,45 @@
*
* This module is browser compatible.
*
* ```ts
* import { bgBlue, red, bold } from "https://deno.land/std@$STD_VERSION/fmt/colors.ts";
* console.log(bgBlue(red(bold("Hello world!"))));
* ```
*
* This module supports `NO_COLOR` environmental variable disabling any coloring
* if `NO_COLOR` is set.
*
* @example
* ```typescript
* import {
* bgBlue,
* bgRgb24,
* bgRgb8,
* bold,
* italic,
* red,
* rgb24,
* rgb8,
* } from "https://deno.land/std@$STD_VERSION/fmt/colors.ts";
*
* console.log(bgBlue(italic(red(bold("Hello, World!")))));
*
* // also supports 8bit colors
*
* console.log(rgb8("Hello, World!", 42));
*
* console.log(bgRgb8("Hello, World!", 42));
*
* // and 24bit rgb
*
* console.log(rgb24("Hello, World!", {
* r: 41,
* g: 42,
* b: 43,
* }));
*
* console.log(bgRgb24("Hello, World!", {
* r: 41,
* g: 42,
* b: 43,
* }));
* ```
*
* @module
*/

View File

@ -1,5 +1,25 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
// A module to get formatted digital duration from milliseconds.
/**
* Format milliseconds to time duration.
*
* ```ts
* import { format } from "https://deno.land/std@$STD_VERSION/fmt/duration.ts";
*
* // "00:00:01:39:674:000:000"
* format(99674, { style: "digital" });
*
* // "0d 0h 1m 39s 674ms 0µs 0ns"
* format(99674);
*
* // "1m 39s 674ms"
* format(99674, { ignoreZero: true });
*
* // "1 minutes, 39 seconds, 674 milliseconds"
* format(99674, { style: "full", ignoreZero: true });
* ```
* @module
*/
const addZero = (num: number, digits: number) =>
String(num).padStart(digits, "0");

View File

@ -7,6 +7,142 @@
* This implementation is inspired by POSIX and Golang but does not port
* implementation code.
*
* sprintf converts and formats a variable number of arguments as is specified
* by a `format string`. In it's basic form, a format string may just be a
* literal. In case arguments are meant to be formatted, a `directive` is
* contained in the format string, preceded by a '%' character:
*
* %<verb>
*
* E.g. the verb `s` indicates the directive should be replaced by the string
* representation of the argument in the corresponding position of the argument
* list. E.g.:
*
* Hello %s!
*
* applied to the arguments "World" yields "Hello World!".
*
* The meaning of the format string is modelled after [POSIX][1] format strings
* as well as well as [Golang format strings][2]. Both contain elements specific
* to the respective programming language that don't apply to JavaScript, so
* they can not be fully supported. Furthermore we implement some functionality
* that is specific to JS.
*
* ## Verbs
*
* The following verbs are supported:
*
* | Verb | Meaning |
* | ----- | -------------------------------------------------------------- |
* | `%` | print a literal percent |
* | `t` | evaluate arg as boolean, print `true` or `false` |
* | `b` | eval as number, print binary |
* | `c` | eval as number, print character corresponding to the codePoint |
* | `o` | eval as number, print octal |
* | `x X` | print as hex (ff FF), treat string as list of bytes |
* | `e E` | print number in scientific/exponent format 1.123123e+01 |
* | `f F` | print number as float with decimal point and no exponent |
* | `g G` | use %e %E or %f %F depending on size of argument |
* | `s` | interpolate string |
* | `T` | type of arg, as returned by `typeof` |
* | `v` | value of argument in 'default' format (see below) |
* | `j` | argument as formatted by `JSON.stringify` |
*
* ## Width and Precision
*
* Verbs may be modified by providing them with width and precision, either or
* both may be omitted:
*
* %9f width 9, default precision
* %.9f default width, precision 9
* %8.9f width 8, precision 9
* %8.f width 9, precision 0
*
* In general, 'width' describes the minimum length of the output, while
* 'precision' limits the output.
*
* | verb | precision |
* | --------- | --------------------------------------------------------------- |
* | `t` | n/a |
* | `b c o` | n/a |
* | `x X` | n/a for number, strings are truncated to p bytes(!) |
* | `e E f F` | number of places after decimal, default 6 |
* | `g G` | set maximum number of digits |
* | `s` | truncate input |
* | `T` | truncate |
* | `v` | truncate, or depth if used with # see "'default' format", below |
* | `j` | n/a |
*
* Numerical values for width and precision can be substituted for the `*` char,
* in which case the values are obtained from the next args, e.g.:
*
* sprintf("%*.*f", 9, 8, 456.0)
*
* is equivalent to:
*
* sprintf("%9.8f", 456.0)
*
* ## Flags
*
* The effects of the verb may be further influenced by using flags to modify
* the directive:
*
* | Flag | Verb | Meaning |
* | ----- | --------- | -------------------------------------------------------------------------- |
* | `+` | numeric | always print sign |
* | `-` | all | pad to the right (left justify) |
* | `#` | | alternate format |
* | `#` | `b o x X` | prefix with `0b 0 0x` |
* | `#` | `g G` | don't remove trailing zeros |
* | `#` | `v` | ues output of `inspect` instead of `toString` |
* | `' '` | | space character |
* | `' '` | `x X` | leave spaces between bytes when printing string |
* | `' '` | `d` | insert space for missing `+` sign character |
* | `0` | all | pad with zero, `-` takes precedence, sign is appended in front of padding |
* | `<` | all | format elements of the passed array according to the directive (extension) |
*
* ## 'default' format
*
* The default format used by `%v` is the result of calling `toString()` on the
* relevant argument. If the `#` flags is used, the result of calling `inspect()`
* is interpolated. In this case, the precision, if set is passed to `inspect()`
* as the 'depth' config parameter.
*
* ## Positional arguments
*
* Arguments do not need to be consumed in the order they are provided and may
* be consumed more than once. E.g.:
*
* sprintf("%[2]s %[1]s", "World", "Hello")
*
* returns "Hello World". The presence of a positional indicator resets the arg
* counter allowing args to be reused:
*
* sprintf("dec[%d]=%d hex[%[1]d]=%x oct[%[1]d]=%#o %s", 1, 255, "Third")
*
* returns `dec[1]=255 hex[1]=0xff oct[1]=0377 Third`
*
* Width and precision my also use positionals:
*
* "%[2]*.[1]*d", 1, 2
*
* This follows the golang conventions and not POSIX.
*
* ## Errors
*
* The following errors are handled:
*
* Incorrect verb:
*
* S("%h", "") %!(BAD VERB 'h')
*
* Too few arguments:
*
* S("%d") %!(MISSING 'd')"
*
* [1]: https://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
* [2]: https://golang.org/pkg/fmt/
*
* @module
*/

View File

@ -1,228 +0,0 @@
# fs
fs module is made to provide helpers to manipulate the filesystem.
## Usage
Most of the following modules are exposed in `mod.ts`. This feature is currently
<b>unstable</b>. To enable it use `deno run --unstable`.
### emptyDir
Ensures that a directory is empty. Deletes directory contents if the directory
is not empty. If the directory does not exist, it is created. The directory
itself is not deleted.
```ts
import {
emptyDir,
emptyDirSync,
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
emptyDir("./foo"); // returns a promise
emptyDirSync("./foo"); // void
```
### ensureDir
Ensures that the directory exists. If the directory structure does not exist, it
is created. Like `mkdir -p`.
```ts
import {
ensureDir,
ensureDirSync,
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
ensureDir("./bar"); // returns a promise
ensureDirSync("./ensureDirSync"); // void
```
### ensureFile
Ensures that the file exists. If the file that is requested to be created is in
directories that do not exist, these directories are created. If the file
already exists, it is **NOT MODIFIED**.
```ts
import {
ensureFile,
ensureFileSync,
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
ensureFile("./folder/targetFile.dat"); // returns promise
ensureFileSync("./folder/targetFile.dat"); // void
```
### ensureSymlink
Ensures that the link exists. If the directory structure does not exist, it is
created.
```ts
import {
ensureSymlink,
ensureSymlinkSync,
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
ensureSymlink("./folder/targetFile.dat", "./folder/targetFile.link.dat"); // returns promise
ensureSymlinkSync("./folder/targetFile.dat", "./folder/targetFile.link.dat"); // void
```
### EOL
Detects and format the passed string for the targeted End Of Line character.
```ts
import {
detect,
EOL,
format,
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
const CRLFinput = "deno\r\nis not\r\nnode";
const Mixedinput = "deno\nis not\r\nnode";
const LFinput = "deno\nis not\nnode";
const NoNLinput = "deno is not node";
detect(LFinput); // output EOL.LF
detect(CRLFinput); // output EOL.CRLF
detect(Mixedinput); // output EOL.CRLF
detect(NoNLinput); // output null
format(CRLFinput, EOL.LF); // output "deno\nis not\nnode"
```
### exists
Test whether or not the given path exists by checking with the file system.
```ts
import {
exists,
existsSync,
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
exists("./foo.txt"); // resolves a boolean
existsSync("./foo.txt"); // returns a boolean
```
**Note: do not use this function if performing a check before another operation
on that file. Doing so causes a race condition. Instead, perform the actual file
operation directly.**
Bad:
```ts
import {
exists,
existsSync,
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
if (await exists("./foo.txt")) {
await Deno.remove("./foo.txt");
}
// OR
if (existsSync("./foo.txt")) {
Deno.removeSync("./foo.txt");
}
```
Good:
```ts
// Notice no use of exists or existsSync
try {
await Deno.remove("./foo.txt");
} catch (error) {
if (!(error instanceof Deno.errors.NotFound)) {
throw error;
}
// Do nothing...
}
// OR
try {
Deno.removeSync("./foo.txt");
} catch (error) {
if (!(error instanceof Deno.errors.NotFound)) {
throw error;
}
// Do nothing...
}
```
### move
Moves a file or directory. Overwrites it if option provided.
```ts
import { move, moveSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
move("./foo", "./bar"); // returns a promise
moveSync("./foo", "./bar"); // void
moveSync("./foo", "./existingFolder", { overwrite: true });
// Will overwrite existingFolder
```
### copy
copy a file or directory. Overwrites it if option provided.
```ts
import { copy, copySync } from "https://deno.land/std@$STD_VERSION/fs/copy.ts";
copy("./foo", "./bar"); // returns a promise
copySync("./foo", "./bar"); // void
copySync("./foo", "./existingFolder", { overwrite: true });
// Will overwrite existingFolder
```
### walk
Iterate all files in a directory recursively.
```ts
import { walk, walkSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
for (const entry of walkSync(".")) {
console.log(entry.path);
}
// Async
async function printFilesNames() {
for await (const entry of walk(".")) {
console.log(entry.path);
}
}
printFilesNames().then(() => console.log("Done!"));
```
### expandGlob
Expand the glob string from the specified `root` directory and yield each result
as a `WalkEntry` object.
```ts
import { expandGlob } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
for await (const file of expandGlob("**/*.ts")) {
console.log(file);
}
```
### expandGlobSync
Synchronous version of `expandGlob()`.
```ts
import { expandGlobSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
for (const file of expandGlobSync("**/*.ts")) {
console.log(file);
}
```

View File

@ -9,22 +9,22 @@ import { isWindows } from "../_util/os.ts";
export interface CopyOptions {
/**
* overwrite existing file or directory. Default is `false`
* overwrite existing file or directory.
* @default {false}
*/
overwrite?: boolean;
/**
* When `true`, will set last modification and access times to the ones of the
* original source files.
* When `false`, timestamp behavior is OS-dependent.
* Default is `false`.
*
* @default {false}
*/
preserveTimestamps?: boolean;
}
interface InternalCopyOptions extends CopyOptions {
/**
* default is `false`
*/
/** @default {false} */
isFolder?: boolean;
}
@ -243,6 +243,13 @@ function copyDirSync(
/**
* Copy a file or directory. The directory can have contents. Like `cp -r`.
* Requires the `--allow-read` and `--allow-write` flag.
*
* @example
* ```ts
* import { copy } from "https://deno.land/std@$STD_VERSION/fs/copy.ts";
* copy("./foo", "./bar"); // returns a promise
* ```
*
* @param src the file/directory path.
* Note that if `src` is a directory it will copy everything inside
* of this directory, not the entire directory itself
@ -282,6 +289,12 @@ export async function copy(
/**
* Copy a file or directory. The directory can have contents. Like `cp -r`.
* Requires the `--allow-read` and `--allow-write` flag.
*
* @example
* ```ts
* import { copySync } from "https://deno.land/std@$STD_VERSION/fs/copy.ts";
* copySync("./foo", "./bar"); // void
* ```
* @param src the file/directory path.
* Note that if `src` is a directory it will copy everything inside
* of this directory, not the entire directory itself

View File

@ -8,6 +8,13 @@ import { toPathString } from "./_util.ts";
* If the directory does not exist, it is created.
* The directory itself is not deleted.
* Requires the `--allow-read` and `--allow-write` flag.
*
* @example
* ```ts
* import { emptyDir } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* emptyDir("./foo"); // returns a promise
* ```
*/
export async function emptyDir(dir: string | URL) {
try {
@ -39,6 +46,13 @@ export async function emptyDir(dir: string | URL) {
* If the directory does not exist, it is created.
* The directory itself is not deleted.
* Requires the `--allow-read` and `--allow-write` flag.
*
* @example
* ```ts
* import { emptyDirSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* emptyDirSync("./foo"); // void
* ```
*/
export function emptyDirSync(dir: string | URL) {
try {

View File

@ -5,6 +5,13 @@ import { getFileInfoType } from "./_util.ts";
* Ensures that the directory exists.
* If the directory structure does not exist, it is created. Like mkdir -p.
* Requires the `--allow-read` and `--allow-write` flag.
*
* @example
* ```ts
* import { ensureDir } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* ensureDir("./bar"); // returns a promise
* ```
*/
export async function ensureDir(dir: string | URL) {
try {
@ -30,6 +37,13 @@ export async function ensureDir(dir: string | URL) {
* Ensures that the directory exists.
* If the directory structure does not exist, it is created. Like mkdir -p.
* Requires the `--allow-read` and `--allow-write` flag.
*
* @example
* ```ts
* import { ensureDirSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* ensureDirSync("./ensureDirSync"); // void
* ```
*/
export function ensureDirSync(dir: string | URL) {
try {

View File

@ -10,6 +10,13 @@ import { getFileInfoType, toPathString } from "./_util.ts";
* these directories are created. If the file already exists,
* it is NOTMODIFIED.
* Requires the `--allow-read` and `--allow-write` flag.
*
* @example
* ```ts
* import { ensureFile } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* ensureFile("./folder/targetFile.dat"); // returns promise
* ```
*/
export async function ensureFile(filePath: string | URL) {
try {
@ -41,6 +48,13 @@ export async function ensureFile(filePath: string | URL) {
* these directories are created. If the file already exists,
* it is NOT MODIFIED.
* Requires the `--allow-read` and `--allow-write` flag.
*
* @example
* ```ts
* import { ensureFileSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* ensureFileSync("./folder/targetFile.dat"); // void
* ```
*/
export function ensureFileSync(filePath: string | URL) {
try {

View File

@ -7,6 +7,13 @@ import { toPathString } from "./_util.ts";
* Ensures that the hard link exists.
* If the directory structure does not exist, it is created.
*
* @example
* ```ts
* import { ensureSymlink } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* ensureSymlink("./folder/targetFile.dat", "./folder/targetFile.link.dat"); // returns promise
* ```
*
* @param src the source file path. Directory hard links are not allowed.
* @param dest the destination link path
*/
@ -21,6 +28,13 @@ export async function ensureLink(src: string | URL, dest: string | URL) {
* Ensures that the hard link exists.
* If the directory structure does not exist, it is created.
*
* @example
* ```ts
* import { ensureSymlinkSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* ensureSymlinkSync("./folder/targetFile.dat", "./folder/targetFile.link.dat"); // void
* ```
*
* @param src the source file path. Directory hard links are not allowed.
* @param dest the destination link path
*/

View File

@ -13,7 +13,22 @@ const regDetect = /(?:\r?\n)/g;
/**
* Detect the EOL character for string input.
* returns null if no newline
* returns null if no newline.
*
* @example
* ```ts
* import { detect, EOL } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* const CRLFinput = "deno\r\nis not\r\nnode";
* const Mixedinput = "deno\nis not\r\nnode";
* const LFinput = "deno\nis not\nnode";
* const NoNLinput = "deno is not node";
*
* detect(LFinput); // output EOL.LF
* detect(CRLFinput); // output EOL.CRLF
* detect(Mixedinput); // output EOL.CRLF
* detect(NoNLinput); // output null
* ```
*/
export function detect(content: string): EOL | null {
const d = content.match(regDetect);
@ -25,7 +40,18 @@ export function detect(content: string): EOL | null {
return hasCRLF ? EOL.CRLF : EOL.LF;
}
/** Format the file to the targeted EOL */
/**
* Format the file to the targeted EOL.
*
* @example
* ```ts
* import { EOL, format } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* const CRLFinput = "deno\r\nis not\r\nnode";
*
* format(CRLFinput, EOL.LF); // output "deno\nis not\nnode"
* ```
*/
export function format(content: string, eol: EOL): string {
return content.replace(regDetect, eol);
}

View File

@ -58,18 +58,19 @@ function comparePath(a: WalkEntry, b: WalkEntry): number {
return 0;
}
/** Expand the glob string from the specified `root` directory and yield each
/**
* Expand the glob string from the specified `root` directory and yield each
* result as a `WalkEntry` object.
*
* See [`globToRegExp()`](../path/glob.ts#globToRegExp) for details on supported
* syntax.
*
* Example:
* @example
* ```ts
* import { expandGlob } from "https://deno.land/std@$STD_VERSION/fs/expand_glob.ts";
* for await (const file of expandGlob("**\/*.ts")) {
* console.log(file);
* }
* import { expandGlob } from "https://deno.land/std@$STD_VERSION/fs/expand_glob.ts";
* for await (const file of expandGlob("**\/*.ts")) {
* console.log(file);
* }
* ```
*/
export async function* expandGlob(
@ -180,15 +181,15 @@ export async function* expandGlob(
yield* currentMatches;
}
/** Synchronous version of `expandGlob()`.
*
* Example:
/**
* Synchronous version of `expandGlob()`.
*
* @example
* ```ts
* import { expandGlobSync } from "https://deno.land/std@$STD_VERSION/fs/expand_glob.ts";
* for (const file of expandGlobSync("**\/*.ts")) {
* console.log(file);
* }
* import { expandGlobSync } from "https://deno.land/std@$STD_VERSION/fs/expand_glob.ts";
* for (const file of expandGlobSync("**\/*.ts")) {
* console.log(file);
* }
* ```
*/
export function* expandGlobSync(

View File

@ -1,6 +1,7 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
/** Helpers for working with the filesystem.
/**
* Helpers for working with the filesystem.
*
* @module
*/

View File

@ -7,7 +7,16 @@ interface MoveOptions {
overwrite?: boolean;
}
/** Moves a file or directory */
/**
* Moves a file or directory.
*
* @example
* ```ts
* import { move } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* move("./foo", "./bar"); // returns a promise
* ```
*/
export async function move(
src: string | URL,
dest: string | URL,
@ -43,7 +52,15 @@ export async function move(
return;
}
/** Moves a file or directory synchronously */
/**
* Moves a file or directory synchronously.
* @example
* ```ts
* import { moveSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
*
* moveSync("./foo", "./bar"); // void
* ```
*/
export function moveSync(
src: string | URL,
dest: string | URL,

Some files were not shown because too many files have changed in this diff Show More