Skip to content

Instantly share code, notes, and snippets.

@maoxiaoke
Last active January 4, 2023 06:07
Show Gist options
  • Save maoxiaoke/684679484d8c7d3796846307cbb6bb11 to your computer and use it in GitHub Desktop.
Save maoxiaoke/684679484d8c7d3796846307cbb6bb11 to your computer and use it in GitHub Desktop.
__Snippets__
const LoadingSVG = () => {
return (
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 19 17"
className="fill-black dark:fill-white"
width="20"
height="20">
<circle className="loadingCircle" cx="2.2" cy="10" r="1.6" />
<circle className="loadingCircle" cx="9.5" cy="10" r="1.6" />
<circle className="loadingCircle" cx="16.8" cy="10" r="1.6" />
</svg>
</div>
);
};
/*
@keyframes loading-svg {
0% { cy: 10; }
25% { cy: 3; }
50% { cy: 10; }
}
.loadingCircle {
animation-duration: 1s;
animation-iteration-count: infinite;
animation-name: loading-svg;
}
.loadingCircle:nth-child(2) { animation-delay: .1s }
.loadingCircle:nth-child(3) { animation-delay: .2s }
*/
export function isDir(name) {
return fs.stat(name)
.then(stats => stats.isDirectory())
.catch(() => false)
}
export function isFile (name) {
return fs.stat(name)
.then(stats => stats.isFile())
.catch(() => false)
}
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const uniqueArr = [ ...new Set([1,2,3]) ]
// https://github.com/rxaviers/async-pool
const asyncPool = <T>(poolLimit: number, iterator: T[], iteratorFn: (iter: T) => any) => {
// Make iteratorFn an Promise
const makeIteratorFnPromise = (iter) => Promise.resolve().then(() => iteratorFn(iter));
// A sets to store the executing iterators
const executing = new Set();
// A list to store all promises, and a promise can be never resolved twice
// https://twitter.com/xiaokedada/status/1542809543524364288
const ret = [];
const clean = (p) => executing.delete(p);
// Use for...of to iterate over the iterators
for (const iter of iterator) {
const p = makeIteratorFnPromise(iter);
p.then(clean).catch(clean);
executing.add(p);
ret.push(p);
if (executing.size >= poolLimit) {
Promise.race(executing)
}
}
return Promise.all(ret)
}
export function debouncePromise<T extends unknown[]>(
fn: (...args: T) => Promise<void>,
delay: number,
onError: (err: unknown) => void,
) {
let timeout: ReturnType<typeof setTimeout> | undefined;
let promiseInFly: Promise<void> | undefined;
let callbackPending: (() => void) | undefined;
return function debounced(...args: Parameters<typeof fn>) {
if (promiseInFly) {
callbackPending = () => {
debounced(...args);
callbackPending = undefined;
};
} else {
if (timeout != null) clearTimeout(timeout);
timeout = setTimeout(() => {
timeout = undefined;
promiseInFly = fn(...args)
.catch(onError)
.finally(() => {
promiseInFly = undefined;
if (callbackPending) callbackPending();
});
}, delay);
}
};
}
import path from 'path';
export const formatPath = (pathStr: string): string => {
return process.platform === 'win32' ? pathStr.split(path.sep).join('/') : pathStr;
}
export const noop = () => {};
let r = (Math.random() + 1).toString(36).substring(7);
/**
* 获取对象某个属性值的类型
*/
type PropType<T, U extends keyof T> = T[U];

元素距离视口的距离

Element.getBoundingClientRect 提供其相对于视口 ViewPort 的距离:

  • top
  • left
  • right
  • bottom

目前该 api 的兼容性完全够用,可以放心使用

该 api 还提供:

  • width
  • height

这两个元素和 Element.offsetWidth、Element.offsetHeight 的区别是:正常情况下两个值是一样的,但是如果元素发生了 transform,则 getBoundingClientRect 返回实际页面渲染的高度和宽度。

例如:如果元素的宽 width:100px,变化 transform:scale(0.5),此时 getBoundingClientRect() 将返回宽 50,而 offsetWidth 将返回宽 100.

元素距离页面顶部的距离

结合 getBoundingClientRectwindow.scrollY 就可以计算出元素距离页面顶部的距离。

同理,还存在一个 window.scrollX 的属性,标记 x 轴方向的滚动距离

元素的宽高

内联元素为 0. 该宽度包含 padding,不包括 border 和 margin。

Element.clientHeight 同理。这两个元素属性标识 displayed content 的内容

  • [Element.offsetWidth]

该宽度包括宽度 + border + padding + vertical scrollbar。不包括 margin 和 伪元素的宽度。

和 Element.offsetHeight 一样,这两个属性标识元素占据了多少空间。

  • [Element.scrollWidth]

当元素设置了 visible: true 时元素的总宽度。

滚动

  • window.scroll

滚动到页面指定位置

  • window.scrollBy

按照指定的偏移量进行滚动

将一个元素滚动到视口可视区域。

scrollIntoView 在 IOS 下,兼容性非常差

参考

https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

// https://regexr.com/47jlq
const importRegex = /import\s+?(?:(?:(?:[\w*\s{},]*)\s+from\s+?)|)(?:(?:"(.*?)")|(?:'(.*?)'))[\s]*?(?:;|$|)/;
const matches = source.match(new RegExp(importRegex, 'g'));
if (matches) {
imports = matches.map((matchStr) => {
const [, singleQuoteImporter, doubleQuoteImporter] = matchStr.match(importRegex);
const importer = singleQuoteImporter || doubleQuoteImporter;
// compatible with `import xx from '.';`
return importer === '.' ? './index' : importer;
}).filter(Boolean);
}
/** others specific regex */
// match: import React from 'react'; import * as React from 'react';
const defaultImportRegex = /([\w\W]*)?(\n?import\s+(?:\*\s+as\s+)?React\s+from\s+['"]react['"];?\n?)([\w\W]*)/;
// match: import React, { useState } from 'react';
const namedImport = /([\w\W]*import\s+(?:[\w*\s{}]*)?\s?)(,?\s?React\s?,?\s?){1}((?:[\w*\s{}]*)?\s+from\s+['"]react['"];?[\w\W]*)/;
let list1 = [[0, 1], [2, 3], [4, 5]];
let list2 = [0, [1, [2, [3, [4, [5, [6]]]]]]];
const flatten = (arr) => {
return arr.reduce(
(acc, val) => {
return acc.concat(Array.isArray(val) ? flatten(val) : val)
}, []
);
};
flatten(list1);
// [0, 1, 2, 3, 4, 5]
flatten(list2);
// [ 0, 1, 2, 3, 4, 5, 6 ]
// 通过 node-fetch 下载
export const downloadFile = async (url: string, path: string) => {
const res = await fetch(url);
const fileStream = fs.createWriteStream(path);
return new Promise((resolve, reject) => {
res.body.pipe(fileStream);
res.body.on('error', reject);
fileStream.on('finish', resolve);
});
}
import crypto from 'crypto';
crypto.createHash('sha256').update('foo').digest('hex');
import { statSync, existsSync } from 'fs-extra';
/**
* check if path is dir
* @param name
* @returns Promise<Boolean>
*/
export const isDirectory = (name: string) => existsSync(name) && statSync(name).isDirectory();
export const isFile = (name: string) => existsSync(name) && statSync(name).isFile();

可以直接用 Node 的 crypto 模块生成 MD5 值,可以用于为固定的字符串生成唯一的,固定的值。

const hash = crypto.createHash('md5');
hash.update('some string');
const hashValue = hash.digest('hex'); // Generate Hex value
# curl + post + data + json
curl -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST http://localhost:3000/data
  1. 修改源
git remote set-url origin <新的远程仓库地址>
  1. 在某个 scope 下发布 NPM Package
$ npm publish --access=public
  1. 打 tags
$ git tag -a v2.0.2 -m "v2.0.2"
$ git push -u origin v2.0.2
  1. dist-tag 修改 latest 版本
$ npm dist-tag add xxx@version latest
  1. 添加其他贡献者
$ npm owner add xxxx

Unix 的一些操作指令

  1. 查看文件大小、读写等信息
$ ls -lh
  1. 统计文件个数(包含子目录)
$ ls -lR|grep "^-"|wc -l
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment