init
This commit is contained in:
		
							
								
								
									
										2
									
								
								.npmignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.npmignore
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
.npmrc
 | 
			
		||||
tests/
 | 
			
		||||
							
								
								
									
										3
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN}
 | 
			
		||||
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
 | 
			
		||||
ignore-workspace-root-check=true
 | 
			
		||||
							
								
								
									
										38
									
								
								css/reset.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								css/reset.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
 | 
			
		||||
/* Base Reset CSS */
 | 
			
		||||
* {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
html {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
body {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
#root {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
 | 
			
		||||
  line-height: 1.5;
 | 
			
		||||
  -webkit-font-smoothing: antialiased;
 | 
			
		||||
  -moz-osx-font-smoothing: grayscale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
img, picture, video, canvas, svg {
 | 
			
		||||
  display: block;
 | 
			
		||||
  max-width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input, button, textarea, select {
 | 
			
		||||
  font: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
p, h1, h2, h3, h4, h5, h6 {
 | 
			
		||||
  overflow-wrap: break-word;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										142
									
								
								import-map.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								import-map.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,142 @@
 | 
			
		||||
// 生成缓存键,基于当前模块的URL
 | 
			
		||||
const getCacheKey = () => {
 | 
			
		||||
  const url = new URL(import.meta.url);
 | 
			
		||||
  const basePath = url.pathname.replace('/import-map.js', '');
 | 
			
		||||
  return `importMap_${btoa(basePath).replace(/[+/=]/g, '_')}`;
 | 
			
		||||
};
 | 
			
		||||
const getCurrentScriptData = () => {
 | 
			
		||||
  try {
 | 
			
		||||
    const script = document.getElementById('importmap');
 | 
			
		||||
    if (script) {
 | 
			
		||||
      return {
 | 
			
		||||
        run: script.dataset.run !== 'false',
 | 
			
		||||
        // 可以获取其他data属性
 | 
			
		||||
        element: script,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.warn('Error finding script with id "importmap":', error);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return { run: true, element: null };
 | 
			
		||||
};
 | 
			
		||||
// 从localStorage获取缓存
 | 
			
		||||
const getCachedImportMap = () => {
 | 
			
		||||
  try {
 | 
			
		||||
    const cacheKey = getCacheKey();
 | 
			
		||||
    const cached = localStorage.getItem(cacheKey);
 | 
			
		||||
    if (cached) {
 | 
			
		||||
      const { data, timestamp } = JSON.parse(cached);
 | 
			
		||||
 | 
			
		||||
      // 检查缓存是否过期(1天 = 24 * 60 * 60 * 1000 毫秒)
 | 
			
		||||
      const oneDay = 24 * 60 * 60 * 1000;
 | 
			
		||||
      const isExpired = Date.now() - timestamp > oneDay;
 | 
			
		||||
      if (isExpired) {
 | 
			
		||||
        localStorage.removeItem(cacheKey);
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
      return { data, timestamp };
 | 
			
		||||
    }
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.warn('Error reading cache:', error);
 | 
			
		||||
  }
 | 
			
		||||
  return null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 保存到localStorage
 | 
			
		||||
const setCachedImportMap = (data) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const cacheKey = getCacheKey();
 | 
			
		||||
    const cacheData = {
 | 
			
		||||
      data,
 | 
			
		||||
      timestamp: Date.now(),
 | 
			
		||||
      url: import.meta.url,
 | 
			
		||||
    };
 | 
			
		||||
    localStorage.setItem(cacheKey, JSON.stringify(cacheData));
 | 
			
		||||
    console.log('Import map cached to localStorage');
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.warn('Error saving cache:', error);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 创建import map脚本元素
 | 
			
		||||
const createImportMapScript = (data) => {
 | 
			
		||||
  const script = document.createElement('script');
 | 
			
		||||
  script.type = 'importmap';
 | 
			
		||||
  script.textContent = JSON.stringify(data);
 | 
			
		||||
  document.head.appendChild(script);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const loadErrorDefualt = () => {
 | 
			
		||||
  const baseImportMap = {
 | 
			
		||||
    imports: {
 | 
			
		||||
      main: './index.js',
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  createImportMapScript(baseImportMap);
 | 
			
		||||
  console.log('Loaded default import map (not cached due to error)');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const loadImportMap = async () => {
 | 
			
		||||
  try {
 | 
			
		||||
    // 首先尝试从缓存加载
 | 
			
		||||
    const cached = getCachedImportMap();
 | 
			
		||||
    if (cached) {
 | 
			
		||||
      createImportMapScript(cached.data);
 | 
			
		||||
      // 后台更新缓存(可选:如果想要每次都检查更新的话)
 | 
			
		||||
      // 注释掉下面这行可以完全依赖缓存,直到手动清除
 | 
			
		||||
      // updateCacheInBackground();
 | 
			
		||||
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const response = await fetch('./imports.json');
 | 
			
		||||
    if (!response.ok) {
 | 
			
		||||
      throw new Error(`HTTP error! status: ${response.status}`);
 | 
			
		||||
    }
 | 
			
		||||
    const data = await response.json();
 | 
			
		||||
 | 
			
		||||
    // 创建import map并缓存
 | 
			
		||||
    createImportMapScript(data);
 | 
			
		||||
    setCachedImportMap(data);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    // 错误情况下不缓存,直接使用默认配置
 | 
			
		||||
    loadErrorDefualt();
 | 
			
		||||
    console.error('Error loading import map:', error);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 后台更新缓存(可选功能)
 | 
			
		||||
export const updateCacheInBackground = async () => {
 | 
			
		||||
  try {
 | 
			
		||||
    const response = await fetch('./imports.json');
 | 
			
		||||
    if (response.ok) {
 | 
			
		||||
      const data = await response.json();
 | 
			
		||||
      setCachedImportMap(data);
 | 
			
		||||
      console.log('Cache updated in background');
 | 
			
		||||
    }
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.warn('Background cache update failed:', error);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const runMain = async () => {
 | 
			
		||||
  const { render } = await import('main');
 | 
			
		||||
  render();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const main = async () => {
 | 
			
		||||
  const { run, element } = getCurrentScriptData();
 | 
			
		||||
  if (!run) {
 | 
			
		||||
    console.log('Script execution is disabled by data-run attribute');
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  try {
 | 
			
		||||
    await loadImportMap();
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error('Error loading import map:', error);
 | 
			
		||||
  }
 | 
			
		||||
  await runMain();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
main();
 | 
			
		||||
							
								
								
									
										20
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "@kevisual/native",
 | 
			
		||||
  "version": "0.0.1",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "files": [
 | 
			
		||||
    "*"
 | 
			
		||||
  ],
 | 
			
		||||
  "publishConfig": {
 | 
			
		||||
    "access": "public"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "test": "echo \"Error: no test specified\" && exit 1"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": [],
 | 
			
		||||
  "author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "packageManager": "pnpm@10.7.0",
 | 
			
		||||
  "type": "module"
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user