Skip to content

Commit

Permalink
update.
Browse files Browse the repository at this point in the history
  • Loading branch information
dojyorin committed Jan 28, 2024
1 parent 4913a0c commit 702b8d0
Show file tree
Hide file tree
Showing 24 changed files with 149 additions and 155 deletions.
2 changes: 1 addition & 1 deletion deps.pure_ext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ export {parse, stringify} from "https://deno.land/[email protected]/csv/mod.ts";
export {ZipReader, ZipWriter, Uint8ArrayReader, Uint8ArrayWriter} from "https://deno.land/x/[email protected]/index.js";

// @deno-types="https://cdn.sheetjs.com/xlsx-0.20.1/package/types/index.d.ts"
export {type WorkBook, type WorkSheet, type CellObject, set_cptable, read as xlsxRead, write as xlsxWrite, utils as xlsxUtil} from "https://cdn.sheetjs.com/xlsx-0.20.1/package/xlsx.mjs";
export {type WorkBook as RawWorkBook, type WorkSheet as RawWorkSheet, type CellObject as RawWorkCell, set_cptable, read as xlsxRead, write as xlsxWrite, utils as xlsxUtil} from "https://cdn.sheetjs.com/xlsx-0.20.1/package/xlsx.mjs";
export * as xlsxcp from "https://cdn.sheetjs.com/xlsx-0.20.1/package/dist/cpexcel.full.mjs";
8 changes: 4 additions & 4 deletions src/deno/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {type Opt} from "../pure/deep.ts";
* Read JSON file and convert to object.
* @example
* ```ts
* const json = await jsonRead("./resource.json");
* const json = await jsonRead("./data.json");
* ```
*/
export async function jsonRead<T extends Opt<T>>(path:string):Promise<T>{
Expand All @@ -15,7 +15,7 @@ export async function jsonRead<T extends Opt<T>>(path:string):Promise<T>{
* Convert from object to JSON and write to file.
* @example
* ```ts
* await jsonWrite("./resource.json", {
* await jsonWrite("./data.json", {
* foo: "bar"
* });
* ```
Expand All @@ -30,8 +30,8 @@ export async function jsonWrite<T extends Opt<T>>(path:string, data:T):Promise<v
* Argument default value also act as type definition.
* @example
* ```ts
* import dresource from "./resource.json" assert {type: "json"};
* const resource = await jsonLoad("./resource.json", dresource);
* import data from "./data.json" assert {type: "json"};
* const json = await jsonLoad("./data.json", data);
* ```
*/
export async function jsonLoad<T extends Opt<T>>(path:string, def:T):Promise<T>{
Expand Down
2 changes: 1 addition & 1 deletion src/deno/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function configPath():string{
}

/**
* System-wide home path for each OS.
* System-wide home directory path for each OS.
* `${HOME}` for UNIX and `%USERPROFILE%` for Windows.
* @example
* ```ts
Expand Down
67 changes: 28 additions & 39 deletions src/deno_ext/dom.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
import {type Element, DOMParser} from "../../deps.deno_ext.ts";
import {type FetchInit, fetchExtend} from "../pure/fetch.ts";
import {deepClone} from "../pure/deep.ts";
import {cleanText} from "../pure/text.ts";

function selectedElement(elements:Element[], attribute:"checked" | "selected"){
return elements.find(e => typeof e.getAttribute(attribute) === "string");
return elements.find(v => typeof v.getAttribute(attribute) === "string");
}

function getContent({textContent}:Element){
return cleanText(textContent);
function getValue(element?:Element){
return element?.getAttribute("value") ?? "";
}

function getValue(element?:Element){
return cleanText(element?.getAttribute("value") ?? "");
function getContent({textContent}:Element){
return textContent;
}

function extractValue(element?:Element){
if(!element){
return "";
}

switch(element.tagName){
switch(element?.tagName){
case "SELECT": return getValue(selectedElement(element.getElementsByTagName("option"), "selected"));
case "DATALIST": return getValue(selectedElement(element.getElementsByTagName("option"), "selected"));
case "OPTION": return getValue(element);
Expand All @@ -35,7 +30,7 @@ function extractValue(element?:Element){
* @see https://deno.land/x/deno_dom
* @example
* ```ts
* const element = await fetchDOM("https://www.google.com");
* const dom = await fetchDOM("https://www.google.com");
* ```
*/
export async function fetchDOM(path:string, option?:FetchInit):Promise<Element>{
Expand All @@ -47,8 +42,7 @@ export async function fetchDOM(path:string, option?:FetchInit):Promise<Element>{
* @see https://deno.land/x/deno_dom
* @example
* ```ts
* const html = "<div>foo</div>";
* const element = parseDOM(html);
* const dom = parseDOM("<div>foo</div>");
* ```
*/
export function parseDOM(html:string):Element{
Expand All @@ -65,28 +59,27 @@ export function parseDOM(html:string):Element{
* Find all `input` `textarea` elements with `id` attribute and convert them to key-value record.
* @example
* ```ts
* const html = "<input id='foo'><textarea id='bar'></textarea>";
* const element = parseHtml(html);
* const result = collectInputById(element);
* const dom = parseDOM("<input id='foo'><textarea id='bar'></textarea>");
* const result = collectInputById(dom);
* ```
*/
export function collectInputById(element:Element):Record<string, string>{
const records:Record<string, string> = {};

for(const e of element.getElementsByTagName("INPUT")){
if(!e.id){
for(const input of element.getElementsByTagName("INPUT")){
if(!input.id){
continue;
}

records[e.id] = getValue(e);
records[input.id] = getValue(input);
}

for(const e of element.getElementsByTagName("TEXTAREA")){
if(!e.id){
for(const textarea of element.getElementsByTagName("TEXTAREA")){
if(!textarea.id){
continue;
}

records[e.id] = getContent(e);
records[textarea.id] = getContent(textarea);
}

return deepClone(records);
Expand All @@ -96,23 +89,21 @@ export function collectInputById(element:Element):Record<string, string>{
* Find all elements with `name` attribute.
* @example
* ```ts
* const html = "<input name='foo'>";
* const element = parseHtml(html);
* const result = getElementsByName(element, "foo");
* const dom = parseDOM("<input name='foo'>");
* const result = getElementsByName(dom, "foo");
* ```
*/
export function getElementsByName(element:Element, name:string):Element[]{
return element.getElementsByTagName("*").filter(e => e.getAttribute("name") === name);
return element.getElementsByTagName("*").filter(v => v.getAttribute("name") === name);
}

/**
* Get value by `id` search.
* `.value` for `<input>`, `.textContent` for `<textarea>` and `.value` of `.selected` for `<select>` `<dataset>`.
* @example
* ```ts
* const html = "<input id='foo'>";
* const element = parseHtml(html);
* const result = getValueById(element, "foo");
* ```ts\
* const dom = parseDOM("<input id='foo'>");
* const result = getValueById(dom, "foo");
* ```
*/
export function getValueById(element:Element, id:string):string{
Expand All @@ -124,28 +115,26 @@ export function getValueById(element:Element, id:string):string{
* `.value` for `<input>`, `.textContent` for `<textarea>` and `.value` of `.selected` for `<select>` `<dataset>`.
* @example
* ```ts
* const html = "<input name='foo'>";
* const element = parseHtml(html);
* const result = getValuesByName(element, "foo");
* const dom = parseDOM("<input name='foo'>");
* const result = getValuesByName(dom, "foo");
* ```
*/
export function getValuesByName(element:Element, name:string):string[]{
return getElementsByName(element, name).map(e => extractValue(e));
return getElementsByName(element, name).map(v => extractValue(v));
}

/**
* Gets value of `.checked` in group of radio buttons.
* @example
* ```ts
* const html = "<input type='radio' name='foo' value='1' checked><input type='radio' name='foo' value='2'>";
* const element = parseHtml(html);
* const result = getValueByRadioActive(element, "foo");
* const dom = parseDOM("<input type='radio' name='foo' value='1' checked><input type='radio' name='foo' value='2'>");
* const result = getValueByRadioActive(dom, "foo");
* ```
*/
export function getValueByRadioActive(element:Element, name:string):string{
const elements = getElementsByName(element, name);

if(elements.some(e => e.tagName !== "INPUT" || e.getAttribute("type") !== "radio")){
if(elements.some(v => v.tagName !== "INPUT" || v.getAttribute("type") !== "radio")){
return "";
}

Expand Down
5 changes: 2 additions & 3 deletions src/deno_ext/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ function logRecord(date:Date, level:string, message:string){
}

/**
* Instantiate logger with general configuration.
* Output to console and also to file if `name` is defined.
* Log file default save path is `${Deno.mainModule}/${name}.log`.
* Start logging.
* Output to console for general and also write to file if `path` is defined.
* @see https://deno.land/std/log
* @example
* ```ts
Expand Down
12 changes: 6 additions & 6 deletions src/deno_ext/smtp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {type DataMap} from "../pure/minipack.ts";
*/
export interface MailMessage{
from: string;
to: string | string[];
cc?: string | string[];
bcc?: string | string[];
to: string[];
title: string;
body: string;
cc?: string[];
bcc?: string[];
files?: DataMap[];
}

Expand All @@ -19,9 +19,9 @@ export interface MailMessage{
* @see https://www.npmjs.com/package/nodemailer
* @example
* ```ts
* const ok = await smtpSend("smtp://smtp.example.com:25", {
* from: "mike@xxx.com",
* to: "john@xxx.com",
* await smtpSend("smtp://smtp.example.com:25", {
* from: "mike@example.com",
* to: ["john@example.com"],
* title: "test",
* body: "test mail."
* });
Expand Down
8 changes: 4 additions & 4 deletions src/pure/byte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ interface BlobType{
* Convert from blob to specified data type.
* @example
* ```ts
* const file = new File(["my-text"], "example.txt");
* const data = await blobConvert(file, "text");
* const blob = new Blob(["my-text"]);
* const data = await blobConvert(blob, "text");
* ```
*/
export async function blobConvert<T extends keyof BlobType>(blob:Blob, type:T):Promise<BlobType[T]>{
Expand All @@ -28,14 +28,14 @@ export async function blobConvert<T extends keyof BlobType>(blob:Blob, type:T):P
}

/**
* Concat multiple buffer sources into single Uint8Array.
* Concat multiple buffer sources into single binary.
* @example
* ```ts
* const byte = byteConcat(new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6]));
* ```
*/
export function byteConcat(...sources:BufferSource[]):Uint8Array{
const output = new Uint8Array(sources.reduce((n, {byteLength}) => n + byteLength , 0));
const output = new Uint8Array(sources.reduce((v, {byteLength}) => v + byteLength , 0));

let i = 0;
for(const source of sources){
Expand Down
32 changes: 16 additions & 16 deletions src/pure/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,17 @@ export async function pkGenerateECDSA():Promise<PortableCryptoKeyPair>{
* const bin = await Deno.readFile("./file");
* const k1 = await pkGenerateECDH();
* const k2 = await pkGenerateECDH();
* const cipher = await pkEncrypt({
* const cipher = await pkEncrypt(bin, {
* publicKey: k1.publicKey,
* privateKey: k2.privateKey
* }, bin);
* const decrypt = await pkDecrypt({
* });
* const decrypt = await pkDecrypt(cipher, {
* publicKey: k2.publicKey,
* privateKey: k1.privateKey
* }, cipher);
* });
* ```
*/
export async function pkEncrypt({publicKey, privateKey}:PortableCryptoKeyPair, data:Uint8Array):Promise<Uint8Array>{
export async function pkEncrypt(data:Uint8Array, {publicKey, privateKey}:PortableCryptoKeyPair):Promise<Uint8Array>{
const aes = {
name: AES_MODE,
iv: generateRandom(12)
Expand All @@ -132,17 +132,17 @@ export async function pkEncrypt({publicKey, privateKey}:PortableCryptoKeyPair, d
* const bin = await Deno.readFile("./file");
* const k1 = await pkGenerateECDH();
* const k2 = await pkGenerateECDH();
* const cipher = await pkEncrypt({
* const cipher = await pkEncrypt(bin, {
* publicKey: k1.publicKey,
* privateKey: k2.privateKey
* }, bin);
* const decrypt = await pkDecrypt({
* });
* const decrypt = await pkDecrypt(cipher, {
* publicKey: k2.publicKey,
* privateKey: k1.privateKey
* }, cipher);
* });
* ```
*/
export async function pkDecrypt({publicKey, privateKey}:PortableCryptoKeyPair, data:Uint8Array):Promise<Uint8Array>{
export async function pkDecrypt(data:Uint8Array, {publicKey, privateKey}:PortableCryptoKeyPair):Promise<Uint8Array>{
const aes = {
name: AES_MODE,
iv: data.subarray(0, 12)
Expand All @@ -157,11 +157,11 @@ export async function pkDecrypt({publicKey, privateKey}:PortableCryptoKeyPair, d
* ```ts
* const bin = await Deno.readFile("./file");
* const {publicKey, privateKey} = await pkGenerateECDSA();
* const sign = await pkSign(privateKey, bin);
* const verify = await pkVerify(publicKey, sign, bin);
* const sign = await pkSign(bin, privateKey);
* const verify = await pkVerify(bin, publicKey, sign);
* ```
*/
export async function pkSign(key:Uint8Array, data:Uint8Array):Promise<Uint8Array>{
export async function pkSign(data:Uint8Array, key:Uint8Array):Promise<Uint8Array>{
return new Uint8Array(await crypto.subtle.sign(MAC_ECDSA, await crypto.subtle.importKey(FORMAT_PRI, key, CURVE_ECDSA, false, ["sign"]), data));
}

Expand All @@ -171,10 +171,10 @@ export async function pkSign(key:Uint8Array, data:Uint8Array):Promise<Uint8Array
* ```ts
* const bin = await Deno.readFile("./file");
* const {publicKey, privateKey} = await pkGenerateECDSA();
* const sign = await pkSign(privateKey, bin);
* const verify = await pkVerify(publicKey, sign, bin);
* const sign = await pkSign(bin, privateKey);
* const verify = await pkVerify(bin, publicKey, sign);
* ```
*/
export async function pkVerify(key:Uint8Array, sign:Uint8Array, data:Uint8Array):Promise<boolean>{
export async function pkVerify(data:Uint8Array, key:Uint8Array, sign:Uint8Array):Promise<boolean>{
return await crypto.subtle.verify(MAC_ECDSA, await crypto.subtle.importKey(FORMAT_PUB, key, CURVE_ECDSA, false, ["verify"]), sign, data);
}
2 changes: 1 addition & 1 deletion src/pure/deep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ function hasObject(data:Record<string | number | symbol, unknown>, key:string){
}

/**
* `structuredClone()` with argument type added to return value.
* `structuredClone()` with argument type added.
* @example
* ```ts
* const clone = deepClone({
Expand Down
20 changes: 11 additions & 9 deletions src/pure/deflate.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import {streamEncode, streamDecode} from "./stream.ts";

const DEFLATE_CODEC = "deflate-raw";
type CompressCodec = "gzip" | "deflate" | "deflate-raw";

const COMPRESS_CODEC = "deflate-raw";

/**
* Compress binary with "deflate" format.
* Does not contain header such as "gzip" (RFC1952) or "zlib" (RFC1950).
* Compress binary with DEFLATE format.
* Default codec is DEFLATE with no header (RFC-1951) and name in WebAPI specification is `"deflate-raw"`.
* @example
* ```ts
* const bin = await Deno.readFile("./file");
* const encode = await deflateEncode(bin);
* const decode = await deflateDecode(encode);
* ```
*/
export async function deflateEncode(data:Uint8Array, codec?:string):Promise<Uint8Array>{
return await streamDecode(streamEncode(data).pipeThrough(new CompressionStream(codec ?? DEFLATE_CODEC)));
export async function deflateEncode(data:Uint8Array, codec?:CompressCodec):Promise<Uint8Array>{
return await streamDecode(streamEncode(data).pipeThrough(new CompressionStream(codec ?? COMPRESS_CODEC)));
}

/**
* Decompress "deflate" format binary.
* Cannot decompress such as "gzip" (RFC1952) or "zlib" (RFC1950) that contain header.
* Decompress DEFLATE format binary.
* Default codec is DEFLATE with no header (RFC-1951) and name in WebAPI specification is `"deflate-raw"`.
* @example
* ```ts
* const bin = await Deno.readFile("./file");
* const encode = await deflateEncode(bin);
* const decode = await deflateDecode(encode);
* ```
*/
export async function deflateDecode(data:Uint8Array, codec?:string):Promise<Uint8Array>{
return await streamDecode(streamEncode(data).pipeThrough(new DecompressionStream(codec ?? DEFLATE_CODEC)));
export async function deflateDecode(data:Uint8Array, codec?:CompressCodec):Promise<Uint8Array>{
return await streamDecode(streamEncode(data).pipeThrough(new DecompressionStream(codec ?? COMPRESS_CODEC)));
}
Loading

0 comments on commit 702b8d0

Please sign in to comment.