ph-utils 0.6.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
package/lib/dom.d.ts CHANGED
@@ -90,3 +90,12 @@ export declare function queryHideNodeSize(hideNode: string | HTMLElement, parent
90
90
  width: number;
91
91
  height: number;
92
92
  };
93
+ /**
94
+ * 判断元素是否在父元素的可视区域内。
95
+ *
96
+ * @param el 要检查的元素
97
+ * @param parent 元素的父元素,默认为document.body
98
+ * @param direction 检查的方向,默认为"horizontal"
99
+ * @returns 如果元素在父元素的可视区域内,则返回true;否则返回false。
100
+ */
101
+ export declare function isVisible(el: HTMLElement, parent?: HTMLElement, direction?: string): boolean;
package/lib/dom.js CHANGED
@@ -3,13 +3,13 @@
3
3
  * 现今不推荐在使用这种方式,现在开发前端的时候,推荐使用一些成熟的框架例如:React、Preact、Vue、Angular、Svelte、Ember、Knockout等
4
4
  * 在使用这些框架的时候额外的一些不可避免的 dom 操作时才使用这个工具;如果确实需要使用原生开发推荐使用 jquery 或者想要更精简的话可以使用 https://github.com/finom/bala 封装
5
5
  */
6
- const vendorPrefix = ['', '-webkit', '-moz-'];
6
+ const vendorPrefix = ["", "-webkit", "-moz-"];
7
7
  /**
8
8
  * 根据选择器获取节点
9
9
  * @param {string} selector 选择器
10
10
  */
11
11
  export function elem(selector, dom) {
12
- if (typeof selector === 'string') {
12
+ if (typeof selector === "string") {
13
13
  return (dom || document).querySelectorAll(selector);
14
14
  }
15
15
  else {
@@ -48,7 +48,7 @@ export function hasClass(elem, clazz) {
48
48
  */
49
49
  export function transition(element, value) {
50
50
  vendorPrefix.forEach((prefix) => {
51
- let t = prefix === '' ? 'transition' : prefix + 'Transition';
51
+ let t = prefix === "" ? "transition" : prefix + "Transition";
52
52
  element.style[t] = value;
53
53
  });
54
54
  }
@@ -59,7 +59,7 @@ export function transition(element, value) {
59
59
  */
60
60
  export function transform(element, value) {
61
61
  vendorPrefix.forEach((prefix) => {
62
- let t = prefix === '' ? 'transform' : prefix + 'Transform';
62
+ let t = prefix === "" ? "transform" : prefix + "Transform";
63
63
  element.style[t] = value;
64
64
  });
65
65
  }
@@ -72,24 +72,24 @@ export function transform(element, value) {
72
72
  */
73
73
  export function on(element, listener, fn, once = false) {
74
74
  let eventExtra = { eventStop: false };
75
- if (typeof once === 'boolean') {
75
+ if (typeof once === "boolean") {
76
76
  eventExtra.once = once;
77
77
  }
78
78
  else {
79
79
  eventExtra = once;
80
80
  }
81
81
  if (eventExtra.eventFlag != null) {
82
- element.setAttribute(eventExtra.eventFlag, '__stop__');
82
+ element.setAttribute(eventExtra.eventFlag, "__stop__");
83
83
  element.addEventListener(listener, (e) => {
84
84
  let target = e.target;
85
- let flag = '';
85
+ let flag = "";
86
86
  do {
87
- flag = target.getAttribute(eventExtra.eventFlag) || '';
88
- if (flag === '') {
87
+ flag = target.getAttribute(eventExtra.eventFlag) || "";
88
+ if (flag === "") {
89
89
  target = target.parentNode;
90
90
  }
91
- } while (flag === '');
92
- if (flag !== '__stop__' || eventExtra.eventStop) {
91
+ } while (flag === "");
92
+ if (flag !== "__stop__" || eventExtra.eventStop) {
93
93
  fn(e, target, flag);
94
94
  }
95
95
  }, eventExtra);
@@ -150,10 +150,10 @@ export function iterate(elems, fn) {
150
150
  */
151
151
  export function attr(elem, key, value) {
152
152
  if (value != null) {
153
- elem.setAttribute('data-' + key, value);
153
+ elem.setAttribute("data-" + key, value);
154
154
  }
155
155
  else {
156
- return elem.getAttribute('data-' + key);
156
+ return elem.getAttribute("data-" + key);
157
157
  }
158
158
  }
159
159
  /**
@@ -172,11 +172,11 @@ export function parent(el) {
172
172
  */
173
173
  export function queryHideNodeSize(hideNode, parent = document.body) {
174
174
  // 计算折叠菜单的高度
175
- let $tmp = document.createElement('div');
176
- $tmp.style.cssText = 'position:fixed;left:-1000px;top:-1000px;opacity:0;';
177
- let $tmpInner = document.createElement('div');
178
- $tmpInner.style.cssText = 'position:relative;';
179
- if (typeof hideNode === 'string') {
175
+ let $tmp = document.createElement("div");
176
+ $tmp.style.cssText = "position:fixed;left:-1000px;top:-1000px;opacity:0;";
177
+ let $tmpInner = document.createElement("div");
178
+ $tmpInner.style.cssText = "position:relative;";
179
+ if (typeof hideNode === "string") {
180
180
  $tmpInner.innerHTML = hideNode;
181
181
  }
182
182
  else {
@@ -188,3 +188,28 @@ export function queryHideNodeSize(hideNode, parent = document.body) {
188
188
  parent.removeChild($tmp);
189
189
  return { width: rect.width, height: rect.height };
190
190
  }
191
+ /**
192
+ * 判断元素是否在父元素的可视区域内。
193
+ *
194
+ * @param el 要检查的元素
195
+ * @param parent 元素的父元素,默认为document.body
196
+ * @param direction 检查的方向,默认为"horizontal"
197
+ * @returns 如果元素在父元素的可视区域内,则返回true;否则返回false。
198
+ */
199
+ export function isVisible(el, parent = document.body, direction = "horizontal") {
200
+ // 获取父元素的边界信息
201
+ const containerRect = parent.getBoundingClientRect();
202
+ // 获取元素的边界信息
203
+ const elementRect = el.getBoundingClientRect();
204
+ // 根据检查方向,确定元素的起始和结束位置
205
+ // 元素的上、下边界
206
+ let elStart = direction === "horizontal" ? elementRect.left : elementRect.top;
207
+ let elEnd = direction === "horizontal" ? elementRect.right : elementRect.bottom;
208
+ // 根据检查方向,确定父元素的起始和结束位置
209
+ // 容器的可视区域的上、下边界
210
+ let containerStart = direction === "horizontal" ? containerRect.left : containerRect.top;
211
+ let containerEnd = direction === "horizontal" ? containerRect.right : containerRect.bottom;
212
+ // 判断元素是否在父元素的可视区域内
213
+ // 判断元素是否完全在容器的可视区域内
214
+ return elStart >= containerStart && elEnd <= containerEnd;
215
+ }
package/lib/file.js CHANGED
@@ -12,19 +12,20 @@ import fs from "node:fs/promises";
12
12
  * @returns 文件内容
13
13
  */
14
14
  export async function read(filepath, defaultValue) {
15
- let content;
16
- try {
17
- content = await fs.readFile(filepath, "utf8");
18
- if (defaultValue != null && typeof defaultValue === "object") {
19
- return JSON.parse(content);
15
+ let content;
16
+ try {
17
+ content = await fs.readFile(filepath, "utf8");
18
+ if (defaultValue != null && typeof defaultValue === "object") {
19
+ return JSON.parse(content);
20
+ }
21
+ return content;
20
22
  }
21
- return content;
22
- } catch (error) {
23
- if (defaultValue === undefined) {
24
- throw error;
23
+ catch (error) {
24
+ if (defaultValue === undefined) {
25
+ throw error;
26
+ }
27
+ return defaultValue;
25
28
  }
26
- return defaultValue;
27
- }
28
29
  }
29
30
  /**
30
31
  * 写入 JSON 格式的数据到文件
@@ -35,12 +36,12 @@ export async function read(filepath, defaultValue) {
35
36
  * @property opts.format 是否在写入 json 数据时,将 JSON 数据格式化2个空格写入, 默认为 true
36
37
  */
37
38
  export async function write(file, data, opts) {
38
- let writeData = data.toString();
39
- opts = { json: true, format: true, ...opts };
40
- if (opts.json === true && typeof data === "object") {
41
- writeData = JSON.stringify(data, null, opts.format === true ? 2 : 0);
42
- }
43
- return await fs.writeFile(path.resolve(file), writeData);
39
+ let writeData = data.toString();
40
+ opts = { json: true, format: true, ...opts };
41
+ if (opts.json === true && typeof data === "object") {
42
+ writeData = JSON.stringify(data, null, opts.format === true ? 2 : 0);
43
+ }
44
+ return await fs.writeFile(path.resolve(file), writeData);
44
45
  }
45
46
  /**
46
47
  * 根据文件的 stat 获取文件的 etag
@@ -48,6 +49,6 @@ export async function write(file, data, opts) {
48
49
  * @returns file stat etag
49
50
  */
50
51
  export async function statTag(filePath) {
51
- let stat = await fs.stat(filePath);
52
- return `${stat.size.toString(16)}-${stat.mtimeMs.toString(16)}`;
52
+ let stat = await fs.stat(filePath);
53
+ return `${stat.size.toString(16)}-${stat.mtimeMs.toString(16)}`;
53
54
  }
@@ -0,0 +1,62 @@
1
+ type LoggerLevel = "debug" | "info" | "warn" | "error" | "fatal";
2
+ /** 日志消息类型 */
3
+ type MessageIntf = number | string | boolean | object | any[] | Error;
4
+ /** 日志消息选项 */
5
+ type MessageOption = {
6
+ /** 日志名称 */
7
+ name?: string;
8
+ /** 日志级别 */
9
+ level?: LoggerLevel;
10
+ /** 日志消息 */
11
+ message: MessageIntf;
12
+ /** 当前消息是否美化输出 */
13
+ pretty?: boolean;
14
+ /** 如果消息是 JSON 格式, 转换为字符串时, 是否格式化 JSON */
15
+ jsonSpace?: number;
16
+ };
17
+ type LoggerOption = {
18
+ /** 记录的日志名称, 通常用于表明哪个页面 */
19
+ name?: string;
20
+ /** 记录日志级别, 通常上线时 error 或者禁用日志, 默认: debug */
21
+ level?: LoggerLevel;
22
+ /** 是否需要美化输出, 默认: true */
23
+ pretty?: boolean;
24
+ };
25
+ /**
26
+ * 日志记录器
27
+ */
28
+ export declare class Logger {
29
+ /** 日志级别 */
30
+ levels: string[];
31
+ colors: {
32
+ debug: string;
33
+ info: string;
34
+ warn: string;
35
+ error: string;
36
+ };
37
+ option: LoggerOption & {
38
+ levelNum: number;
39
+ };
40
+ /** 构造日志记录器 */
41
+ constructor(option?: LoggerOption);
42
+ setOption(option: LoggerOption): void;
43
+ log(message: MessageIntf | MessageOption): void;
44
+ info(message: MessageIntf | MessageOption): void;
45
+ debug(message: MessageIntf | MessageOption): void;
46
+ warn(message: MessageIntf | MessageOption): void;
47
+ error(message: MessageIntf | MessageOption): void;
48
+ fatal(message: MessageIntf | MessageOption): void;
49
+ getLevel(): string;
50
+ getName(): string | undefined;
51
+ getOption(): LoggerOption & {
52
+ levelNum: number;
53
+ };
54
+ private generateLog;
55
+ /** 格式化显示 */
56
+ private formatShow;
57
+ }
58
+ /** 默认日志记录器 */
59
+ export declare const logger: Logger;
60
+ /** 获取新的日志记录器, 属性采用之前的 */
61
+ export declare const getLogger: (option?: LoggerOption) => Logger;
62
+ export {};
package/lib/logger.js ADDED
@@ -0,0 +1,123 @@
1
+ import { format } from "./date";
2
+ /**
3
+ * 日志记录器
4
+ */
5
+ export class Logger {
6
+ /** 日志级别 */
7
+ levels = ["debug", "info", "warn", "error", "fatal"];
8
+ colors = {
9
+ debug: "#909399",
10
+ info: "#1677ff",
11
+ warn: "#fadb14",
12
+ error: "#eb2f96",
13
+ };
14
+ option;
15
+ /** 构造日志记录器 */
16
+ constructor(option) {
17
+ this.setOption(option || {});
18
+ }
19
+ setOption(option) {
20
+ let opts = { level: "debug", levelNum: 0, pretty: true, ...option };
21
+ opts.levelNum = this.levels.indexOf(opts.level);
22
+ this.option = opts;
23
+ }
24
+ log(message) {
25
+ let msgInfo = {
26
+ name: this.option.name,
27
+ level: "info",
28
+ time: format(null, "yyyy-mm-dd HH:MM:ss.S"),
29
+ pretty: this.option.pretty,
30
+ jsonSpace: 0,
31
+ };
32
+ let msgContent = message;
33
+ if (typeof message === "object") {
34
+ if (message instanceof Error) {
35
+ msgInfo.level = "error";
36
+ msgContent = msgContent.stack;
37
+ }
38
+ else if (message.message != null) {
39
+ msgContent = message.message;
40
+ msgInfo = { ...msgInfo, ...message };
41
+ }
42
+ }
43
+ if (typeof msgContent === "object") {
44
+ try {
45
+ msgInfo.message = JSON.stringify(msgContent, null, msgInfo.jsonSpace);
46
+ }
47
+ catch (error) {
48
+ msgInfo.message = msgContent.toString();
49
+ }
50
+ }
51
+ else {
52
+ msgInfo.message = msgContent;
53
+ }
54
+ if (msgInfo.pretty == null) {
55
+ msgInfo.pretty = this.option.pretty;
56
+ }
57
+ let levelIndex = this.levels.indexOf(msgInfo.level);
58
+ if (levelIndex >= this.option.levelNum) {
59
+ this.formatShow(msgInfo);
60
+ }
61
+ }
62
+ info(message) {
63
+ this.log(this.generateLog(message, "info"));
64
+ }
65
+ debug(message) {
66
+ this.log(this.generateLog(message, "debug"));
67
+ }
68
+ warn(message) {
69
+ this.log(this.generateLog(message, "warn"));
70
+ }
71
+ error(message) {
72
+ this.log(this.generateLog(message, "error"));
73
+ }
74
+ fatal(message) {
75
+ this.log(this.generateLog(message, "fatal"));
76
+ }
77
+ getLevel() {
78
+ return this.levels[this.option.levelNum];
79
+ }
80
+ getName() {
81
+ return this.option.name;
82
+ }
83
+ getOption() {
84
+ return this.option;
85
+ }
86
+ generateLog(message, level = "info") {
87
+ let msgInfo = {
88
+ message: message,
89
+ };
90
+ if (typeof message === "object") {
91
+ if (message.message != null) {
92
+ msgInfo = message;
93
+ }
94
+ }
95
+ msgInfo["level"] = level;
96
+ return msgInfo;
97
+ }
98
+ /** 格式化显示 */
99
+ formatShow(msg) {
100
+ if (msg.level === "fatal") {
101
+ msg.level = "error";
102
+ }
103
+ const res = [`[${msg.time}]`];
104
+ if (msg.name != null) {
105
+ res.push(`[${msg.name}]`);
106
+ }
107
+ res.push(`- ${msg.message}`);
108
+ if (!msg.pretty) {
109
+ res.splice(1, 0, `${msg.level.toUpperCase()}`);
110
+ console[msg.level](res.join(" "));
111
+ }
112
+ else {
113
+ const color = this.colors[msg.level];
114
+ console.log(`%c ${`${msg.level.toUpperCase()}`} %c ${res.join(" ")} %c`, `background:${color};border:1px solid ${color}; padding: 1px; border-radius: 2px 0 0 2px; color: #fff;`, `border:1px solid ${color}; padding: 1px; border-radius: 0 2px 2px 0; color: ${color};`, "background:transparent");
115
+ }
116
+ }
117
+ }
118
+ /** 默认日志记录器 */
119
+ export const logger = new Logger({ name: "APP" });
120
+ /** 获取新的日志记录器, 属性采用之前的 */
121
+ export const getLogger = (option) => {
122
+ return new Logger({ ...logger.getOption(), ...option });
123
+ };
package/package.json CHANGED
@@ -52,7 +52,7 @@
52
52
  },
53
53
  "./*": "./lib/*"
54
54
  },
55
- "version": "0.6.2",
55
+ "version": "0.8.0",
56
56
  "type": "module",
57
57
  "repository": {
58
58
  "type": "git",