Commit 2bcf5fd8 authored by haiyoucuv's avatar haiyoucuv

init & svga

parent 8ed5e9af
...@@ -11,13 +11,20 @@ ...@@ -11,13 +11,20 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
"playground": "pnpm --filter playground run dev" "playground": "pnpm --filter=playground run dev"
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-decorators": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.25.9",
"@eslint/js": "^9.13.0",
"@vitejs/plugin-react": "^4.3.3",
"eslint": "^9.13.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.13",
"globals": "^15.11.0",
"less": "^4.2.0", "less": "^4.2.0",
"typescript": "^5.6.3", "typescript": "^5.6.3",
"typescript-eslint": "^8.10.0",
"vite": "^5.4.10", "vite": "^5.4.10",
"vite-plugin-dts": "^4.3.0" "vite-plugin-dts": "^4.3.0"
}, },
......
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
)
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
{
"name": "@grace/built-in",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"build:watch": "tsc -b && vite build -w --mode development",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"dependencies": {
"intersection-observer": "^0.12.2"
}
}
export * from "./md";
export * from "./net";
\ No newline at end of file
import { doClickLog, doShowLog } from "./main";
import { getReference } from "../utils";
import { IAutoMdData } from "./interface.ts";
// 如果点击埋点和跳转埋点只能添加一个的话,两个mapper可以合并成为一个mapper
const clickMapper = new Map();
const generatorClick = (item: IAutoMdData) => {
const ele = getReference(item.ele);
if (!!ele && !clickMapper.get(item.ele)) {
const handler = doClickLog.bind(null, item.data);
clickMapper.set(item.ele, {
ele,
handler,
});
ele.addEventListener("click", handler);
}
// 元素不在文档,绑定了点击埋点(其实不是不在文档,而是比如class改变导致选择器无法再选中而已)
// 那么需要将点击埋点移除
if (!ele && clickMapper.get(item.ele)) {
console.log("元素不在文档");
clickMapper.get(item.ele).ele.removeEventListener("click", clickMapper.get(item.ele).handler);
clickMapper.set(item.ele, null);
}
}
export const MDAuto = (config: { show: IAutoMdData[]; click: IAutoMdData[]; }) => {
const { show, click } = config;
doShowLog(show);
if (click && click.length) {
click.forEach((item) => generatorClick(item));
// 每次dom 插入节点的时候重新检测
const observer = new MutationObserver(() => {
click.forEach((item) => generatorClick(item));
});
observer.observe(document, {
attributes: true,
childList: true,
subtree: true,
});
}
}
export * from './auto.ts';
export * from './manual.ts';
export interface IMdData extends Record<string, any> {
dpm: string;
dcm: string;
dom?: string;
domain: string;
appId: string;
}
export interface IAutoMdData {
ele: string;
data: IMdData;
once: boolean;
}
\ No newline at end of file
This diff is collapsed.
import "./intersection-observer.polyfill.js";
import "intersection-observer";
import { jsonp } from "../net";
// import axios from "axios";
import { obj2query } from "../utils";
import { IAutoMdData } from "./interface.ts";
const showedMapper = {};
const intersectionObservers: IntersectionObserver[] = []
function registryIntersectionObserver(items: any[]) {
for (const observer of intersectionObservers) {
observer.disconnect()
}
intersectionObservers.splice(0)
items.forEach((item) => {
if (typeof item.ele === "string") {
generatorShow(item);
} else {
item.ele.map((eleChild: any) => generatorShow({ ...item, ele: eleChild }));
}
});
}
const generatorShow = (item: IAutoMdData) => {
const { once = true, ele, data } = item;
const element = document.querySelector(item.ele);
// 目标元素在dom中则处理
if (element) {
const observer = new IntersectionObserver((changes) => {
changes.forEach((change) => {
// 如果出现在页面中
if (change.intersectionRatio > 0) {
// 已经曝光过了
if (showedMapper[ele]) return;
showedMapper[ele] = true;
observer.unobserve(change.target);
jsonp(`${data.domain}/exposure/standard?${obj2query(data)}`);
} else {
// 消失在视口
if (!once) {
// 如果需要曝光多次就移除
showedMapper[ele] = false;
}
}
});
}, {});
// 为目标元素注册IntersectionObserver
element && observer.observe(element);
intersectionObservers.push(observer)
}
};
export function doShowLog(items) {
// 先注册一次
registryIntersectionObserver(items);
// 每次dom 插入节点的时候重新检测
const observer = new MutationObserver(function () {
registryIntersectionObserver(items);
});
observer.observe(document, { childList: true, subtree: true });
}
export function doClickLog(data) {
jsonp(`${location.host}/log/click?${obj2query(data)}`);
// axios.get(`/log/click?${obj2query(data)}`);
}
import { doClickLog } from "./main.ts";
import { IMdData } from "./interface.ts";
export function handleLogExposure(data: IMdData) {
}
export function handleLogClick(data: IMdData) {
doClickLog(data);
}
export * from "./jsonp.ts";
\ No newline at end of file
import { obj2query, urlJoin } from "../utils";
export function jsonp(url: string, params: any = {}) {
return new Promise<void>((resolve, reject) => {
const src = urlJoin(url, obj2query(params));
const scriptEl = document.createElement('script');
scriptEl.src = src;
scriptEl.onload = function () {
resolve();
document.body.removeChild(scriptEl);
};
scriptEl.onerror = function () {
reject();
document.body.removeChild(scriptEl);
};
/*const callbackFuncName = '__zeroing_jsonp_callback__' + Math.random();
window[callbackFuncName] = function () {
callback(result);
};*/
document.body.appendChild(scriptEl);
})
}
\ No newline at end of file
export * from "./utils.ts";
\ No newline at end of file
/**
* 对象转query字符串
* @param obj
*/
export function obj2query(obj: string[][] | Record<string, string> | string | URLSearchParams): string {
return new URLSearchParams(obj).toString();
// if(!obj) {
// return '';
// }
// const arr: string[] = [];
// for(const key in obj) {
// arr.push(key + (key ? '=' : '') + obj[key]);
// }
// return arr.join('&');
}
export function urlJoin(url: string, query: any) {
if (query) {
url += url.indexOf('?') < 0 ? '?' : '';
url += url[url.length - 1] === '?' ? '' : '&';
return url + query;
} else {
return url;
}
}
export const getReference = (ele: string | HTMLElement) => {
if (ele instanceof HTMLElement) {
return ele;
} else if (typeof ele === "string") {
return document.querySelector(ele);
}
}
\ No newline at end of file
/// <reference types="vite/client" />
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noFallthroughCasesInSwitch": true,
"declaration": true,
"sourceMap": true,
},
"include": ["src"]
}
{"root":["./src/main.tsx","./src/vite-env.d.ts","./src/md/auto.ts","./src/md/index.ts","./src/md/interface.ts","./src/md/main.ts","./src/md/manual.ts","./src/net/index.ts","./src/net/jsonp.ts","./src/utils/index.ts","./src/utils/utils.ts"],"version":"5.6.3"}
\ No newline at end of file
{
"files": [],
"compilerOptions": {
"composite": false
},
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}
{
"compilerOptions": {
"target": "ES2022",
"lib": [
"ES2023",
"dom"
],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["vite.config.ts"]
}
{"root":["./vite.config.ts"],"version":"5.6.3"}
\ No newline at end of file
import { defineConfig, UserConfig } from 'vite'
import react from '@vitejs/plugin-react'
import dts from 'vite-plugin-dts';
// https://vite.dev/config/
export default defineConfig(({ mode }): UserConfig => {
const isDev = mode == "development";
return {
build: {
sourcemap: isDev,
lib: {
entry: "./src/main.tsx",
name: 'builtIn',
fileName: 'index',
},
cssTarget: 'chrome61',
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: [],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
},
},
},
},
plugins: [
react(),
dts({ rollupTypes: true, tsconfigPath: './tsconfig.app.json' })
],
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
},
},
modules: {
localsConvention: 'camelCase'
}
}
}
})
...@@ -15,20 +15,5 @@ ...@@ -15,20 +15,5 @@
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"dependencies": { "dependencies": {
"svga": "^2.1.1" "svga": "^2.1.1"
},
"peerDependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"eslint": "^9.13.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.13",
"globals": "^15.11.0",
"typescript-eslint": "^8.10.0"
} }
} }
{ {
"compilerOptions": {
"composite": false
},
"files": [], "files": [],
"references": [ "references": [
{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.app.json" },
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@grace/built-in": "workspace:^",
"@grace/svgaplayer": "workspace:^", "@grace/svgaplayer": "workspace:^",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1" "react-dom": "^18.3.1"
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment