[{"data":1,"prerenderedAt":1609},["ShallowReactive",2],{"search-dialog-posts":3,"post-\u002Fposts\u002Fnpm-publish-vue2-component":316,"post-surround-\u002Fposts\u002Fnpm-publish-vue2-component":1602},[4,12,21,29,37,47,57,67,77,85,96,104,112,121,129,137,147,155,164,173,181,188,195,207,215,224,236,241,247,254,260,266,272,279,286,291,298,304,310],{"path":5,"title":6,"description":7,"category":8,"tags":9},"\u002Fposts\u002Fgit-commands-cheatsheet","Git 常用指令與終端機筆記","2018 年整理的 Git 學習筆記，包含基本終端機指令、Git 操作、分支、reset、SourceTree、Vim 與一些常用設定。","notes",[10,11],"Git","版本控制",{"path":13,"title":14,"description":15,"category":16,"tags":17},"\u002Fposts\u002Fjs-prototype-inheritance","JavaScript 物件導向：建構函式、prototype 與繼承三步驟","整理 ES5 時代用建構函式加 prototype 手刻物件導向的完整流程——封裝屬性與方法、共用函式為什麼要掛在 prototype 上、以及繼承的三個步驟（call 借用母類別建構子、Object.create 接上原型鏈、修正 constructor 指向），並附上物件縮寫與計算屬性這兩個順便學到的 ES6 寫法。","frontend",[18,19,20],"JavaScript","物件導向","prototype",{"path":22,"title":23,"description":24,"category":16,"tags":25},"\u002Fposts\u002Fflexbox-notes","Flexbox 對齊與彈性尺寸筆記","記錄 Flexbox 的主軸與交錯軸對齊、flex-direction、flex-wrap，以及 flex-grow、flex-shrink、flex-basis 等常用屬性。",[26,27,28],"CSS","Flexbox","版面",{"path":30,"title":31,"description":32,"category":16,"tags":33},"\u002Fposts\u002Fscreen-orientation-api","screen.orientation：現在判斷與鎖定螢幕方向的做法","整理現在 JavaScript 判斷螢幕方向的方式，包括 screen.orientation、change 事件與 lock()，並說明 RWD 使用 matchMedia 或 CSS orientation 會更適合。",[18,34,35,36],"RWD","螢幕方向","PWA",{"path":38,"title":39,"description":40,"category":16,"tags":41},"\u002Fposts\u002Fpinia-vuex-state-management","Pinia \u002F Vuex 狀態管理及差異","紀錄 Vuex、Pinia 的狀態管理概念、差異與用法。",[42,43,44,45,46],"Pinia","Vuex","Vue3","狀態管理","Nuxt",{"path":48,"title":49,"description":50,"category":8,"tags":51},"\u002Fposts\u002Fpyenv-python-version-management","Python 多版本管理 pyenv","紀錄 macOS 與 Windows 使用 pyenv 管理 Python 版本的方式。",[52,53,54,55,56],"Python","pyenv","macOS","Windows","版本管理",{"path":58,"title":59,"description":60,"category":8,"tags":61},"\u002Fposts\u002Fnpm-publish-vue2-component","npm 發布流程","紀錄 Vue 2 元件的 npm 發布、dist-tag 與打包流程。",[62,63,64,65,66],"npm","Vue2","Vue CLI","套件發布","MIT",{"path":68,"title":69,"description":70,"category":8,"tags":71},"\u002Fposts\u002Fmobile-debugging-today","現在怎麼 debug 手機網頁：從裝一堆工具到幾乎不用裝","對照 2022 年那套 scoop、iTunes、remotedebug-ios-webkit-adapter 的繁瑣設定，整理現在偵錯手機網頁的做法：Android 無線偵錯、iOS 的實際選項、on-device console、Playwright 裝置模擬，以及本機 HTTPS 的處理。",[72,73,74,75,76],"debug","iOS","Android","Chrome DevTools","Playwright",{"path":78,"title":79,"description":80,"category":16,"tags":81},"\u002Fposts\u002Fplaywright-vs-cypress","E2E 測試現在選什麼：Playwright 與 Cypress 的實際差異","對照幾年前用 Cypress 的做法，說明 Playwright 為什麼變成多數新專案的預設選擇：真正的多瀏覽器支援、免費的平行執行、trace viewer 除錯，以及兩者在架構上的根本差異與各自仍然適合的場景。",[76,82,83,84],"Cypress","E2E","測試",{"path":86,"title":87,"description":88,"category":89,"tags":90},"\u002Fposts\u002Fjs-encoding-today","現在處理編碼：TextEncoder、Uint8Array 的 Base64 方法與 URLSearchParams","整理 JavaScript 現代編碼方式，使用 TextEncoder、TextDecoder 與 Uint8Array 處理 UTF-8 與 Base64，並說明 Base64URL、URLSearchParams 與 encodeURIComponent 的差異。","research",[91,92,93,94,95,18],"編碼","TextEncoder","Base64","URLSearchParams","Uint8Array",{"path":97,"title":98,"description":99,"category":16,"tags":100},"\u002Fposts\u002Fdart-sass-migration","Dart Sass 遷移筆記：node-sass 之後怎麼裝 Sass","node-sass 與 LibSass 已停止維護，現在改用 Dart Sass。整理 webpack 與 Vite 的安裝方式，以及為什麼不再像 node-sass 一樣容易遇到 Node.js 版本與原生編譯問題。",[101,102,103],"Sass","Webpack","Vite",{"path":105,"title":106,"description":107,"category":16,"tags":108},"\u002Fposts\u002Fdayjs-vue3-computed","day.js 搭配 Vue 3 的日期格式化","整理 Vue 3 日期格式化的常見做法，使用 day.js 取代舊專案常見的 moment.js，並以 method 或 computed 取代 Vue 2 filter，也補充原生 Intl.DateTimeFormat 的使用方式。",[44,109,110,111],"day.js","日期","Intl",{"path":113,"title":114,"description":115,"category":16,"tags":116},"\u002Fposts\u002Fes-modules-today","ES Module 現在的樣子：Node ESM、exports 與 import maps","整理現代 JavaScript ES Module 的常見用法，包括 Node.js 原生 ESM、package.json exports、瀏覽器 import maps、JSON import attributes，以及 Vite 動態載入的注意事項。",[117,118,119,120,103,18],"ES Module","Node.js","import maps","exports",{"path":122,"title":123,"description":124,"category":89,"tags":125},"\u002Fposts\u002Fstructured-clone","structuredClone()：終於有內建的深層拷貝","整理 JavaScript structuredClone() 的深層拷貝用法，說明 Date、Map、Set、循環參考的處理方式，以及 Function、class 與 Vue reactive Proxy 的注意事項。",[18,126,127,128],"structuredClone","深拷貝","Vue",{"path":130,"title":131,"description":132,"category":16,"tags":133},"\u002Fposts\u002Fdynamic-import","JavaScript 動態載入：import() 與 Vue 非同步元件","整理靜態 import、動態 import() 與 Vue defineAsyncComponent 的使用方式，並簡單補充 Vite import.meta.glob 的用途。",[18,134,135,103,136],"ES Modules","Vue 3","Code Splitting",{"path":138,"title":139,"description":140,"category":16,"tags":141},"\u002Fposts\u002Fscreen-wake-lock-api","Screen Wake Lock API：不用套件也能讓頁面保持亮著","整理 Screen Wake Lock API 的基本用法，說明 HTTPS、頁面可見性、切換分頁後重新取得 wake lock，以及 Vue／Nuxt 計時器使用時的注意事項。",[142,128,143,144,145,146],"Wake Lock","Nuxt4","行動裝置","計時器","Web API",{"path":148,"title":149,"description":150,"category":16,"tags":151},"\u002Fposts\u002Fhtml-meta-boilerplate-today","現在的 HTML meta 標籤怎麼寫","整理現在一個新頁面該有的 meta 標籤骨架——viewport 補上 viewport-fit=cover 因應瀏海與圓角螢幕、color-scheme 讓表單控制項跟著深色模式換色、theme-color 決定行動瀏覽器工具列顏色，以及基本的 SEO 與 Open Graph 標籤。",[152,153,154],"HTML","meta","SEO",{"path":156,"title":157,"description":158,"category":8,"tags":159},"\u002Fposts\u002Fdocker-node-postgres","把 Node + PostgreSQL 的 backend 裝進 Docker：Dockerfile、.dockerignore 與 compose","從「本機裝了就跑」到打包成容器的通用做法——Dockerfile 每一行的理由與 layer cache 為什麼決定了指令順序、.dockerignore 漏掉 node_modules 對原生模組是災難級的問題、容器之間為什麼不能用 localhost 互相找到對方，以及怎麼驗證資料真的寫進了 volume。",[160,161,118,162,163],"Docker","Docker Compose","PostgreSQL","Express",{"path":165,"title":166,"description":167,"category":16,"tags":168},"\u002Fposts\u002Fnuxt-server-proxy","Nuxt 3 \u002F 4 用 Server API 做代理與轉發","整理 Nuxt 3 與 Nuxt 4 使用 server\u002Fapi 轉發第三方 API 的方式，可以避免瀏覽器 CORS 問題、隱藏 API Key，也能在伺服器端加入快取。",[169,143,170,171,172],"Nuxt3","CORS","Nitro","API",{"path":174,"title":175,"description":176,"category":16,"tags":177},"\u002Fposts\u002Fnuxt4-project-setup","Nuxt 4 建立專案：和 Nuxt 3 有哪些不同","整理 Nuxt 4 建立專案的基本流程與目錄結構，並對照 Nuxt 3 的差異，包括 app\u002F 目錄、路徑別名、TypeScript，以及目前常用的 ESLint 與 Tailwind CSS 4 設定。",[143,44,178,179,180],"TypeScript","ESLint","Tailwind CSS 4",{"path":182,"title":183,"description":184,"category":16,"tags":185},"\u002Fposts\u002Fnuxt3-route-middleware","Nuxt 3 \u002F 4 的 Route Middleware：進頁面前先做判斷","整理 Nuxt 3 與 Nuxt 4 的 Route Middleware，用 defineNuxtRouteMiddleware 在進入頁面前檢查登入狀態，搭配 navigateTo 重新導向，並說明一般 middleware、global middleware 與 definePageMeta 的用法。",[169,143,186,187],"Middleware","驗證",{"path":189,"title":190,"description":191,"category":16,"tags":192},"\u002Fposts\u002Fnuxt-route-rules-redirect","Nuxt 3 \u002F 4 的 routeRules：重新導向與頁面設定","整理 Nuxt 3 與 Nuxt 4 的 routeRules 用法，可以依照不同網址設定重新導向、預渲染、SSR 與快取，並簡單對照 Nuxt 2 的舊做法。",[169,143,193,194],"routeRules","重新導向",{"path":196,"title":197,"description":198,"category":16,"tags":199},"\u002Fposts\u002Fios-iframe-google-login-blank-page","iOS iframe 串接 Google 登入出現空白頁：Popup 與頁面回收問題排查紀錄","記錄 iframe 內串接 Google 第三方登入時，部分 iOS 裝置因背景頁面遭到回收並重新載入，導致 Popup 登入流程中斷，以及最後透過 Redirect 分流與登入狀態接回機制處理的過程。",[73,200,201,202,203,204,205,206],"Safari","iframe","Google Login","GIS","OAuth","Popup","Redirect",{"path":208,"title":209,"description":210,"category":16,"tags":211},"\u002Fposts\u002Fios-login-tab-return-behavior","iOS 第三方登入後回不到原頁？分頁開啟關係與回頁行為實測","記錄 iOS Safari 與 Chrome 在多分頁第三方登入流程中，登入頁關閉後不一定回到原頁的實測，以及分頁開啟關係、window.close 與 window.focus 的限制。",[73,200,212,202,204,201,213,214],"Chrome","window.close","window.focus",{"path":216,"title":217,"description":218,"category":16,"tags":219},"\u002Fposts\u002Fgoogle-app-about-blank-placeholder","Google App 內建瀏覽器：about:blank 佔位頁被關閉的排查紀錄","記錄 iOS Google App 內建瀏覽器在非同步開啟外部頁面時，about:blank 佔位分頁被自動關閉，導致第三方登入或外部導轉失敗的排查與解法。",[73,220,221,222,204,223],"Google App","window.open","about:blank","WebView",{"path":225,"title":226,"description":227,"category":228,"tags":229},"\u002Fposts\u002Fclaude-code-codex-cli-init-basics","AI 相關紀錄 v1｜Claude Code \u002F Codex CLI 初始化與基本概念","從 Claude Code 與 Codex CLI 開始，整理 CLI、Coding Agent、Context、\u002Finit 與 CLAUDE.md／AGENTS.md 這幾個一開始最容易搞混的概念，以及在既有專案中的安裝與啟動方式。","ai",[230,231,232,233,234,235],"AI","Claude Code","Codex CLI","Coding Agent","CLAUDE.md","AGENTS.md",{"path":237,"title":238,"description":239,"category":228,"tags":240},"\u002Fposts\u002Fclaude-agents-md-project-guidelines","AI 相關紀錄 v2｜CLAUDE.md \u002F AGENTS.md 怎麼寫？專案規範與實際範例","整理 CLAUDE.md 與 AGENTS.md 的用途、適合記錄的專案規範，以及可直接參考的設定範例。",[230,231,232,234,235],{"path":242,"title":243,"description":244,"category":228,"tags":245},"\u002Fposts\u002Fclaude-codex-config-locations","AI 相關紀錄 v3｜Claude Code `.claude\u002F` \u002F Codex CLI 設定位置：全域與專案設定基本概要介紹","整理 Claude Code 與 Codex CLI 的使用者層級、專案層級設定位置，以及 rules、skills、agents 等目錄的用途。",[230,231,232,246],"設定檔",{"path":248,"title":249,"description":250,"category":228,"tags":251},"\u002Fposts\u002Fclaude-settings-codex-config","AI 相關紀錄 v4｜Claude Code settings \u002F Codex config 基本設定","整理 Claude Code settings.json 與 Codex config.toml 的設定層級、權限控制和常見基本設定。",[230,231,232,252,253],"settings.json","config.toml",{"path":255,"title":256,"description":257,"category":228,"tags":258},"\u002Fposts\u002Fclaude-codex-rules-structure","AI 相關紀錄 v5｜Rules：專案規則多了之後怎麼拆？","整理 Claude Code Rules 與 Codex AGENTS.md 的拆分方式，說明何時該拆、怎麼依目錄管理專案規則。",[230,231,232,259,235],"Rules",{"path":261,"title":262,"description":263,"category":228,"tags":264},"\u002Fposts\u002Fclaude-codex-slash-commands","AI 相關紀錄 v6｜Commands \u002F Slash Commands：CLI 裡的 `\u002F` 指令是什麼？","介紹 Claude Code 與 Codex CLI 的 Slash Commands，整理常用內建指令、自訂指令與 Skills 的差異。",[230,231,232,265],"Slash Commands",{"path":267,"title":268,"description":269,"category":228,"tags":270},"\u002Fposts\u002Fclaude-codex-skills","AI 相關紀錄 v7｜Skills：把重複工作流程整理起來","介紹 Claude Code 與 Codex Skills，整理適合保存成 Skill 的重複流程、基本結構與使用方式。",[230,231,232,271],"Skills",{"path":273,"title":274,"description":275,"category":228,"tags":276},"\u002Fposts\u002Fclaude-codex-agents-subagents","AI 相關紀錄 v8｜Agent \u002F Subagent：什麼時候真的需要分工？","整理 Agent、Subagent 與 Custom Agent 的用途，說明何時適合分工，以及它們和 Rules、Skills 的差異。",[230,231,232,277,278],"Agent","Subagent",{"path":280,"title":281,"description":282,"category":228,"tags":283},"\u002Fposts\u002Fmcp-basics","AI 相關紀錄 v9｜MCP：讓 AI 使用其他工具與資料","介紹 MCP 如何讓 AI 使用外部工具與資料，並以 Pencil MCP 說明實際用途、權限風險及與 Skill 的差異。",[230,284,231,232,285],"MCP","Pencil",{"path":287,"title":288,"description":289,"category":228,"tags":290},"\u002Fposts\u002Fai-coding-agent-concepts-summary","AI 相關紀錄 v10｜基本概念小結論","用一篇快速整理 CLAUDE.md、AGENTS.md、設定檔、Rules、Commands、Skills、Agent 與 MCP 的角色和差異。",[230,231,232,284,271,277],{"path":292,"title":293,"description":294,"category":228,"tags":295},"\u002Fposts\u002Fclaude-code-codex-model-selection","Claude Code 與 Codex：不同模型怎麼選？","比較 Claude Code 與 Codex 不同模型的速度、能力與成本取捨，依工作難度整理實用的選擇方向。",[230,231,296,297],"Codex","模型選擇",{"path":299,"title":300,"description":301,"category":228,"tags":302},"\u002Fposts\u002Fclaude-model-selection","Claude 模型簡單怎麼選？","整理 Claude 各模型在速度、能力與使用情境上的差異，提供從輕量工作到複雜任務的選擇方向。",[230,231,303,297],"Claude",{"path":305,"title":306,"description":307,"category":228,"tags":308},"\u002Fposts\u002Fcodex-model-selection","Codex 模型簡單怎麼選？","整理 Codex 各模型在速度、能力與使用情境上的差異，提供從簡單修改到大型端到端任務的選擇方向。",[230,296,309,297],"OpenAI",{"path":311,"title":312,"description":313,"category":228,"tags":314},"\u002Fposts\u002Fclaude-code-codex-cli-command-cheatsheet","Claude Code \u002F Codex CLI 常用指令速查表","整理 Claude Code 與 Codex CLI 的常用斜線指令、快捷操作與進階功能，方便需要時快速查找。",[230,231,232,265,315],"速查表",{"id":317,"title":59,"body":318,"category":8,"description":60,"draft":1591,"extension":1592,"image":1593,"meta":1594,"navigation":737,"path":58,"publishedAt":1595,"relatedExperiments":1596,"seo":1597,"stem":1598,"tags":1599,"updatedAt":1600,"__hash__":1601},"posts\u002Fposts\u002F20250122.npm-publish-vue2-component.md",{"type":319,"value":320,"toc":1562},"minimark",[321,338,342,383,387,431,435,463,466,481,487,501,504,524,527,530,547,550,569,572,591,597,616,619,623,635,639,642,675,685,689,697,701,707,825,840,844,1088,1091,1139,1142,1145,1148,1160,1174,1177,1192,1195,1207,1210,1224,1227,1239,1242,1258,1261,1277,1280,1292,1296,1299,1318,1321,1341,1348,1354,1357,1383,1386,1389,1394,1399,1437,1442,1460,1466,1470,1480,1483,1514,1520,1524,1532,1535,1558],[322,323,324,325,329,330,337],"p",{},"把寫好的年份選擇器（",[326,327,328],"code",{},"vue2-year-picker","）發到 npm 的流程紀錄。前置作業只有一項：先去 ",[331,332,336],"a",{"href":333,"rel":334},"https:\u002F\u002Fwww.npmjs.com\u002F",[335],"nofollow","npmjs.com"," 註冊帳號。",[339,340,341],"h2",{"id":341},"為什麼要另開一個發布專案",[343,344,345,354,357,363,377],"ul",{},[346,347,348,349,353],"li",{},"元件是在既有專案裡寫出來的，但",[350,351,352],"strong",{},"發布時要把它拆到一個乾淨的新專案","，不要直接從原專案發。",[346,355,356],{},"三個理由：",[346,358,359,362],{},[350,360,361],{},"專案獨立性","：元件作為 npm 套件應該只有單一職責，專注在提供該元件的功能，不需要攜帶跟其他專案有關的程式碼。",[346,364,365,368,369,372,373,376],{},[350,366,367],{},"打包簡化","：發布到 npm 時只需要包含與元件相關的檔案（編譯後的 ",[326,370,371],{},".js"," 與 ",[326,374,375],{},".css","），不需要其他專案的內容。檔案體積小，使用者也不會被無關的東西搞混。",[346,378,379,382],{},[350,380,381],{},"方便維護","：拆出來之後可以獨立更版、獨立寫文件、獨立發布，不會影響到原本的專案。",[339,384,386],{"id":385},"npm-的標籤dist-tag","npm 的標籤（dist-tag）",[343,388,389,392,401,411,425],{},[346,390,391],{},"在講流程之前先搞懂標籤，因為它決定了「使用者裝到哪一版」。",[346,393,394,395,400],{},"每個發布的版本都會被指到一個標籤，預設是 ",[350,396,397],{},[326,398,399],{},"latest","。",[346,402,403,404,407,408,410],{},"使用者直接 ",[326,405,406],{},"npm install"," 拿到的就是 ",[326,409,399],{}," 指向的那一版。",[346,412,413,414,417,418,417,421,424],{},"你可以自定義標籤，例如 ",[326,415,416],{},"next","、",[326,419,420],{},"beta",[326,422,423],{},"alpha","，用來區分測試版與正式版。",[346,426,427,430],{},[350,428,429],{},"用測試標籤發布的版本，除非使用者明確指定，否則看不到也裝不到","——這就是它的用處。",[432,433,434],"h3",{"id":434},"用測試標籤發布",[436,437,442],"pre",{"className":438,"code":439,"language":440,"meta":441,"style":441},"language-bash shiki shiki-themes github-light github-dark-default","npm publish --tag next\n","bash","",[326,443,444],{"__ignoreMap":441},[445,446,449,452,456,460],"span",{"class":447,"line":448},"line",1,[445,450,62],{"class":451},"sYRkA",[445,453,455],{"class":454},"sNbzA"," publish",[445,457,459],{"class":458},"sPgVT"," --tag",[445,461,462],{"class":454}," next\n",[322,464,465],{},"使用者要明確指定才裝得到：",[436,467,469],{"className":438,"code":468,"language":440,"meta":441,"style":441},"npm install vue2-year-picker@next\n",[326,470,471],{"__ignoreMap":441},[445,472,473,475,478],{"class":447,"line":448},[445,474,62],{"class":451},[445,476,477],{"class":454}," install",[445,479,480],{"class":454}," vue2-year-picker@next\n",[322,482,483,484,486],{},"不指定的話，拿到的是 ",[326,485,399],{},"（正式版）：",[436,488,490],{"className":438,"code":489,"language":440,"meta":441,"style":441},"npm install vue2-year-picker\n",[326,491,492],{"__ignoreMap":441},[445,493,494,496,498],{"class":447,"line":448},[445,495,62],{"class":451},[445,497,477],{"class":454},[445,499,500],{"class":454}," vue2-year-picker\n",[432,502,503],{"id":503},"測試標籤的用途",[343,505,506,512,518],{},[346,507,508,511],{},[350,509,510],{},"內部測試","：自己或團隊成員先裝來試",[346,513,514,517],{},[350,515,516],{},"提前試用","：讓特定開發者先用到新功能並回饋",[346,519,520,523],{},[350,521,522],{},"不影響正式使用者","：測試版不會被當成正式版，不會干擾別人的安裝",[432,525,526],{"id":526},"管理標籤",[322,528,529],{},"查看套件目前有哪些標籤與版本：",[436,531,533],{"className":438,"code":532,"language":440,"meta":441,"style":441},"npm dist-tag ls vue2-year-picker\n",[326,534,535],{"__ignoreMap":441},[445,536,537,539,542,545],{"class":447,"line":448},[445,538,62],{"class":451},[445,540,541],{"class":454}," dist-tag",[445,543,544],{"class":454}," ls",[445,546,500],{"class":454},[322,548,549],{},"把某個標籤指到某個版本（沒有就新增，有就更新）：",[436,551,553],{"className":438,"code":552,"language":440,"meta":441,"style":441},"npm dist-tag add vue2-year-picker@1.1.0-beta.1 next\n",[326,554,555],{"__ignoreMap":441},[445,556,557,559,561,564,567],{"class":447,"line":448},[445,558,62],{"class":451},[445,560,541],{"class":454},[445,562,563],{"class":454}," add",[445,565,566],{"class":454}," vue2-year-picker@1.1.0-beta.1",[445,568,462],{"class":454},[322,570,571],{},"移除標籤：",[436,573,575],{"className":438,"code":574,"language":440,"meta":441,"style":441},"npm dist-tag rm vue2-year-picker next\n",[326,576,577],{"__ignoreMap":441},[445,578,579,581,583,586,589],{"class":447,"line":448},[445,580,62],{"class":451},[445,582,541],{"class":454},[445,584,585],{"class":454}," rm",[445,587,588],{"class":454}," vue2-year-picker",[445,590,462],{"class":454},[322,592,593,594,596],{},"測試滿意後轉成正式版，就是把 ",[326,595,399],{}," 指過去：",[436,598,600],{"className":438,"code":599,"language":440,"meta":441,"style":441},"npm dist-tag add vue2-year-picker@1.1.0 latest\n",[326,601,602],{"__ignoreMap":441},[445,603,604,606,608,610,613],{"class":447,"line":448},[445,605,62],{"class":451},[445,607,541],{"class":454},[445,609,563],{"class":454},[445,611,612],{"class":454}," vue2-year-picker@1.1.0",[445,614,615],{"class":454}," latest\n",[339,617,618],{"id":618},"建立發布專案",[432,620,622],{"id":621},"_1-初始化","1. 初始化",[436,624,626],{"className":438,"code":625,"language":440,"meta":441,"style":441},"npm init\n",[326,627,628],{"__ignoreMap":441},[445,629,630,632],{"class":447,"line":448},[445,631,62],{"class":451},[445,633,634],{"class":454}," init\n",[432,636,638],{"id":637},"_2-安裝相依套件","2. 安裝相依套件",[322,640,641],{},"這裡發布的是 Vue 2 元件，所以要裝 2.6.0：",[436,643,645],{"className":438,"code":644,"language":440,"meta":441,"style":441},"npm install vue@2.6.0 vue-template-compiler@2.6.0 --save\nnpm install -D @vue\u002Fcli-service\n",[326,646,647,662],{"__ignoreMap":441},[445,648,649,651,653,656,659],{"class":447,"line":448},[445,650,62],{"class":451},[445,652,477],{"class":454},[445,654,655],{"class":454}," vue@2.6.0",[445,657,658],{"class":454}," vue-template-compiler@2.6.0",[445,660,661],{"class":458}," --save\n",[445,663,665,667,669,672],{"class":447,"line":664},2,[445,666,62],{"class":451},[445,668,477],{"class":454},[445,670,671],{"class":458}," -D",[445,673,674],{"class":454}," @vue\u002Fcli-service\n",[322,676,677,680,681,684],{},[326,678,679],{},"vue-template-compiler"," 的版本",[350,682,683],{},"必須跟 vue 完全一致","，差一個修訂號都會在編譯時報錯。",[432,686,688],{"id":687},"_3-目錄結構","3. 目錄結構",[436,690,695],{"className":691,"code":693,"language":694,"meta":441},[692],"language-text","vue-year-picker\u002F\n├── src\u002F\n│   └── YearPicker.vue\n├── index.js\n├── package.json\n├── package-lock.json\n├── LICENSE\n└── README.md\n","text",[326,696,693],{"__ignoreMap":441},[432,698,700],{"id":699},"_4-建立入口點","4. 建立入口點",[322,702,703,706],{},[326,704,705],{},"index.js","：",[436,708,712],{"className":709,"code":710,"language":711,"meta":441,"style":441},"language-js shiki shiki-themes github-light github-dark-default","import YearPicker from '.\u002Fsrc\u002FYearPicker.vue';\n\nexport default {\n  install(Vue) {\n    Vue.component('YearPicker', YearPicker);\n  },\n};\n\n\u002F\u002F 支援按需引入\nexport { YearPicker };\n","js",[326,713,714,733,739,752,771,788,797,805,810,817],{"__ignoreMap":441},[445,715,716,720,724,727,730],{"class":447,"line":448},[445,717,719],{"class":718},"sDgYj","import",[445,721,723],{"class":722},"szmH1"," YearPicker ",[445,725,726],{"class":718},"from",[445,728,729],{"class":454}," '.\u002Fsrc\u002FYearPicker.vue'",[445,731,732],{"class":722},";\n",[445,734,735],{"class":447,"line":664},[445,736,738],{"emptyLinePlaceholder":737},true,"\n",[445,740,742,745,748],{"class":447,"line":741},3,[445,743,744],{"class":718},"export",[445,746,747],{"class":718}," default",[445,749,751],{"class":750},"sfpNf"," {\n",[445,753,755,759,762,765,768],{"class":447,"line":754},4,[445,756,758],{"class":757},"sVjZL","  install",[445,760,761],{"class":750},"(",[445,763,128],{"class":764},"sjlk-",[445,766,767],{"class":750},") ",[445,769,770],{"class":722},"{\n",[445,772,774,777,780,782,785],{"class":447,"line":773},5,[445,775,776],{"class":722},"    Vue.",[445,778,779],{"class":757},"component",[445,781,761],{"class":722},[445,783,784],{"class":454},"'YearPicker'",[445,786,787],{"class":722},", YearPicker);\n",[445,789,791,794],{"class":447,"line":790},6,[445,792,793],{"class":722},"  }",[445,795,796],{"class":750},",\n",[445,798,800,803],{"class":447,"line":799},7,[445,801,802],{"class":750},"}",[445,804,732],{"class":722},[445,806,808],{"class":447,"line":807},8,[445,809,738],{"emptyLinePlaceholder":737},[445,811,813],{"class":447,"line":812},9,[445,814,816],{"class":815},"sPyeA","\u002F\u002F 支援按需引入\n",[445,818,820,822],{"class":447,"line":819},10,[445,821,744],{"class":718},[445,823,824],{"class":722}," { YearPicker };\n",[343,826,827,837],{},[346,828,829,832,833,836],{},[326,830,831],{},"install(Vue)"," 是 Vue 2 外掛的約定介面，讓使用者可以 ",[326,834,835],{},"Vue.use(YearPicker)"," 一次註冊全域元件。",[346,838,839],{},"下面那行具名匯出則是給只想在單一檔案裡 import 的人用，兩種都留著比較有彈性。",[432,841,843],{"id":842},"_5-packagejson","5. package.json",[436,845,849],{"className":846,"code":847,"language":848,"meta":441,"style":441},"language-json shiki shiki-themes github-light github-dark-default","{\n  \"name\": \"vue2-year-picker\",\n  \"version\": \"1.0.0\",\n  \"main\": \"dist\u002Findex.js\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"build\": \"vue-cli-service build --target lib --name YearPicker .\u002Fsrc\u002FYearPicker.vue\"\n  },\n  \"peerDependencies\": {\n    \"vue\": \"^2.6.0\"\n  },\n  \"author\": \"traveltime1221\",\n  \"license\": \"MIT\",\n  \"description\": \"一個用於只有選擇年份的 Vue2 組件，支持西元轉民國年份轉換。\",\n  \"dependencies\": {\n    \"vue\": \"^2.6.0\",\n    \"vue-template-compiler\": \"^2.6.0\"\n  },\n  \"devDependencies\": {\n    \"@vue\u002Fcli-service\": \"^4.5.19\"\n  }\n}\n","json",[326,850,851,855,869,881,893,901,906,911,919,943,953,959,967,978,983,996,1009,1022,1030,1042,1052,1057,1065,1076,1082],{"__ignoreMap":441},[445,852,853],{"class":447,"line":448},[445,854,770],{"class":722},[445,856,857,861,864,867],{"class":447,"line":664},[445,858,860],{"class":859},"swgif","  \"name\"",[445,862,863],{"class":722},": ",[445,865,866],{"class":454},"\"vue2-year-picker\"",[445,868,796],{"class":722},[445,870,871,874,876,879],{"class":447,"line":741},[445,872,873],{"class":859},"  \"version\"",[445,875,863],{"class":722},[445,877,878],{"class":454},"\"1.0.0\"",[445,880,796],{"class":722},[445,882,883,886,888,891],{"class":447,"line":754},[445,884,885],{"class":859},"  \"main\"",[445,887,863],{"class":722},[445,889,890],{"class":454},"\"dist\u002Findex.js\"",[445,892,796],{"class":722},[445,894,895,898],{"class":447,"line":773},[445,896,897],{"class":859},"  \"files\"",[445,899,900],{"class":722},": [\n",[445,902,903],{"class":447,"line":790},[445,904,905],{"class":454},"    \"dist\"\n",[445,907,908],{"class":447,"line":799},[445,909,910],{"class":722},"  ],\n",[445,912,913,916],{"class":447,"line":807},[445,914,915],{"class":859},"  \"scripts\"",[445,917,918],{"class":722},": {\n",[445,920,921,924,926,929,933,936,938,941],{"class":447,"line":812},[445,922,923],{"class":859},"    \"test\"",[445,925,863],{"class":722},[445,927,928],{"class":454},"\"echo ",[445,930,932],{"class":931},"sw7DY","\\\"",[445,934,935],{"class":454},"Error: no test specified",[445,937,932],{"class":931},[445,939,940],{"class":454}," && exit 1\"",[445,942,796],{"class":722},[445,944,945,948,950],{"class":447,"line":819},[445,946,947],{"class":859},"    \"build\"",[445,949,863],{"class":722},[445,951,952],{"class":454},"\"vue-cli-service build --target lib --name YearPicker .\u002Fsrc\u002FYearPicker.vue\"\n",[445,954,956],{"class":447,"line":955},11,[445,957,958],{"class":722},"  },\n",[445,960,962,965],{"class":447,"line":961},12,[445,963,964],{"class":859},"  \"peerDependencies\"",[445,966,918],{"class":722},[445,968,970,973,975],{"class":447,"line":969},13,[445,971,972],{"class":859},"    \"vue\"",[445,974,863],{"class":722},[445,976,977],{"class":454},"\"^2.6.0\"\n",[445,979,981],{"class":447,"line":980},14,[445,982,958],{"class":722},[445,984,986,989,991,994],{"class":447,"line":985},15,[445,987,988],{"class":859},"  \"author\"",[445,990,863],{"class":722},[445,992,993],{"class":454},"\"traveltime1221\"",[445,995,796],{"class":722},[445,997,999,1002,1004,1007],{"class":447,"line":998},16,[445,1000,1001],{"class":859},"  \"license\"",[445,1003,863],{"class":722},[445,1005,1006],{"class":454},"\"MIT\"",[445,1008,796],{"class":722},[445,1010,1012,1015,1017,1020],{"class":447,"line":1011},17,[445,1013,1014],{"class":859},"  \"description\"",[445,1016,863],{"class":722},[445,1018,1019],{"class":454},"\"一個用於只有選擇年份的 Vue2 組件，支持西元轉民國年份轉換。\"",[445,1021,796],{"class":722},[445,1023,1025,1028],{"class":447,"line":1024},18,[445,1026,1027],{"class":859},"  \"dependencies\"",[445,1029,918],{"class":722},[445,1031,1033,1035,1037,1040],{"class":447,"line":1032},19,[445,1034,972],{"class":859},[445,1036,863],{"class":722},[445,1038,1039],{"class":454},"\"^2.6.0\"",[445,1041,796],{"class":722},[445,1043,1045,1048,1050],{"class":447,"line":1044},20,[445,1046,1047],{"class":859},"    \"vue-template-compiler\"",[445,1049,863],{"class":722},[445,1051,977],{"class":454},[445,1053,1055],{"class":447,"line":1054},21,[445,1056,958],{"class":722},[445,1058,1060,1063],{"class":447,"line":1059},22,[445,1061,1062],{"class":859},"  \"devDependencies\"",[445,1064,918],{"class":722},[445,1066,1068,1071,1073],{"class":447,"line":1067},23,[445,1069,1070],{"class":859},"    \"@vue\u002Fcli-service\"",[445,1072,863],{"class":722},[445,1074,1075],{"class":454},"\"^4.5.19\"\n",[445,1077,1079],{"class":447,"line":1078},24,[445,1080,1081],{"class":722},"  }\n",[445,1083,1085],{"class":447,"line":1084},25,[445,1086,1087],{"class":722},"}\n",[322,1089,1090],{},"幾個欄位的意義：",[343,1092,1093,1104,1119,1131],{},[346,1094,1095,1100,1101,1103],{},[350,1096,1097],{},[326,1098,1099],{},"main","：使用者 ",[326,1102,719],{}," 這個套件時實際載入的檔案",[346,1105,1106,706,1111,1114,1115,1118],{},[350,1107,1108],{},[326,1109,1110],{},"files",[350,1112,1113],{},"只有列在這裡的東西會被打包上傳","。不寫的話整個資料夾（含 ",[326,1116,1117],{},"src\u002F","、測試檔）都會被發出去",[346,1120,1121,1126,1127,1130],{},[350,1122,1123],{},[326,1124,1125],{},"peerDependencies","：宣告「我需要宿主專案提供 vue 2.6 以上」，而不是自己再帶一份。",[350,1128,1129],{},"元件套件一定要這樣寫","，不然使用者的專案裡會出現兩份 vue，狀態不共用，畫面就開始出現各種靈異現象",[346,1132,1133,1138],{},[350,1134,1135],{},[326,1136,1137],{},"--target lib","：Vue CLI 的 library 模式，會產出 UMD 與 CommonJS 兩種格式",[339,1140,1141],{"id":1141},"發布",[432,1143,1144],{"id":1144},"確認打包內容",[322,1146,1147],{},"在真的發出去之前，先看看會包進去哪些檔案：",[436,1149,1151],{"className":438,"code":1150,"language":440,"meta":441,"style":441},"npm pack\n",[326,1152,1153],{"__ignoreMap":441},[445,1154,1155,1157],{"class":447,"line":448},[445,1156,62],{"class":451},[445,1158,1159],{"class":454}," pack\n",[322,1161,1162,1163,1166,1167,1170,1171,1173],{},"它會產生一個 ",[326,1164,1165],{},".tgz","，解開來看就知道使用者實際會拿到什麼。",[350,1168,1169],{},"這一步不要跳過","——",[326,1172,1110],{}," 寫錯的話會把整個開發目錄發到 npm 上，而且 npm 的版本不能覆寫，只能再發一版。",[432,1175,1176],{"id":1176},"打包",[436,1178,1180],{"className":438,"code":1179,"language":440,"meta":441,"style":441},"npm run build\n",[326,1181,1182],{"__ignoreMap":441},[445,1183,1184,1186,1189],{"class":447,"line":448},[445,1185,62],{"class":451},[445,1187,1188],{"class":454}," run",[445,1190,1191],{"class":454}," build\n",[432,1193,1194],{"id":1194},"登入",[436,1196,1198],{"className":438,"code":1197,"language":440,"meta":441,"style":441},"npm login\n",[326,1199,1200],{"__ignoreMap":441},[445,1201,1202,1204],{"class":447,"line":448},[445,1203,62],{"class":451},[445,1205,1206],{"class":454}," login\n",[432,1208,1209],{"id":1209},"發布測試版",[436,1211,1212],{"className":438,"code":439,"language":440,"meta":441,"style":441},[326,1213,1214],{"__ignoreMap":441},[445,1215,1216,1218,1220,1222],{"class":447,"line":448},[445,1217,62],{"class":451},[445,1219,455],{"class":454},[445,1221,459],{"class":458},[445,1223,462],{"class":454},[322,1225,1226],{},"裝來試：",[436,1228,1229],{"className":438,"code":468,"language":440,"meta":441,"style":441},[326,1230,1231],{"__ignoreMap":441},[445,1232,1233,1235,1237],{"class":447,"line":448},[445,1234,62],{"class":451},[445,1236,477],{"class":454},[445,1238,480],{"class":454},[432,1240,1241],{"id":1241},"轉正式版",[436,1243,1244],{"className":438,"code":599,"language":440,"meta":441,"style":441},[326,1245,1246],{"__ignoreMap":441},[445,1247,1248,1250,1252,1254,1256],{"class":447,"line":448},[445,1249,62],{"class":451},[445,1251,541],{"class":454},[445,1253,563],{"class":454},[445,1255,612],{"class":454},[445,1257,615],{"class":454},[322,1259,1260],{},"測試標籤用不到了就刪掉：",[436,1262,1263],{"className":438,"code":574,"language":440,"meta":441,"style":441},[326,1264,1265],{"__ignoreMap":441},[445,1266,1267,1269,1271,1273,1275],{"class":447,"line":448},[445,1268,62],{"class":451},[445,1270,541],{"class":454},[445,1272,585],{"class":454},[445,1274,588],{"class":454},[445,1276,462],{"class":454},[322,1278,1279],{},"或者確認套件名稱在 npm 上是唯一的之後，直接發正式版：",[436,1281,1283],{"className":438,"code":1282,"language":440,"meta":441,"style":441},"npm publish\n",[326,1284,1285],{"__ignoreMap":441},[445,1286,1287,1289],{"class":447,"line":448},[445,1288,62],{"class":451},[445,1290,1291],{"class":454}," publish\n",[339,1293,1295],{"id":1294},"mit-license","MIT License",[322,1297,1298],{},"授權要在發布前就決定好，發出去之後再改會很麻煩。常見的選擇：",[343,1300,1301,1306,1312],{},[346,1302,1303,1305],{},[350,1304,66],{},"：最寬鬆，允許任何用途包含商業使用",[346,1307,1308,1311],{},[350,1309,1310],{},"GPL","：強制要求其他人開源修改後的程式碼",[346,1313,1314,1317],{},[350,1315,1316],{},"CC BY-NC","：只允許非商業使用",[322,1319,1320],{},"這裡選 MIT。它是世界上最簡單、最常用的開源授權之一，特點是：",[343,1322,1323,1329,1335],{},[346,1324,1325,1328],{},[350,1326,1327],{},"簡單易懂","：條款只有幾段文字",[346,1330,1331,1334],{},[350,1332,1333],{},"非常寬鬆","：任何人都能免費使用、修改，包括商業用途",[346,1336,1337,1340],{},[350,1338,1339],{},"保護作者免責","：程式碼「按原樣」（AS IS）提供，別人用出問題不用你負責",[322,1342,1343,1344,1347],{},"範本（",[326,1345,1346],{},"LICENSE"," 檔案）：",[436,1349,1352],{"className":1350,"code":1351,"language":694,"meta":441},[692],"MIT License\n\nCopyright (c) [年份] [您的名字或團隊名稱]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and\u002For sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n",[326,1353,1351],{"__ignoreMap":441},[339,1355,1356],{"id":1356},"發布後注意事項",[343,1358,1359,1372,1378],{},[346,1360,1361,1363,1364,1367,1368,1371],{},[350,1362,56],{},"：每次更新記得改 ",[326,1365,1366],{},"package.json"," 的 ",[326,1369,1370],{},"version","。npm 不允許重複發同一個版號",[346,1373,1374,1377],{},[350,1375,1376],{},"README.md","：寫清楚怎麼安裝、怎麼用、有哪些 props，這是使用者唯一會看的文件",[346,1379,1380,1382],{},[350,1381,84],{},"：確保元件在 Vue 2 環境下真的能跑",[432,1384,1385],{"id":1385},"相容性要顧到哪裡",[322,1387,1388],{},"發給別人用的東西，跟自己專案裡的程式碼標準不一樣——你不知道對方的瀏覽器版本與建置環境。",[343,1390,1391],{},[346,1392,1393],{},"想涵蓋大部分使用者，有幾個方向：",[322,1395,1396],{},[350,1397,1398],{},"打包設定",[343,1400,1401,1415,1431],{},[346,1402,1403,1406,1407,1410,1411,1414],{},[350,1404,1405],{},"Babel","：把 ES6+ 轉成較舊的 JavaScript。用 ",[326,1408,1409],{},".browserslistrc"," 或 Babel 的 ",[326,1412,1413],{},"targets"," 指定要支援到哪些瀏覽器",[346,1416,1417,706,1420,417,1423,1426,1427,1430],{},[350,1418,1419],{},"Polyfill",[326,1421,1422],{},"Promise",[326,1424,1425],{},"fetch"," 這類新特性舊瀏覽器沒有，用 ",[326,1428,1429],{},"core-js"," 補上",[346,1432,1433,1436],{},[350,1434,1435],{},"ESM \u002F CommonJS 都給","：現代工具吃 ESM，較舊的 Node.js 與前端工具吃 CommonJS，兩種都輸出相容性最高",[322,1438,1439],{},[350,1440,1441],{},"多版本建置",[343,1443,1444,1450],{},[346,1445,1446,1449],{},[350,1447,1448],{},"ESM（ES Module）","：現代瀏覽器與 Node.js 都支援，模組化效率較好，可以 tree-shaking",[346,1451,1452,1455,1456,1459],{},[350,1453,1454],{},"UMD（Universal Module Definition）","：最廣泛支援的格式，瀏覽器與 Node.js 都能跑，用 ",[326,1457,1458],{},"\u003Cscript>"," 直接引入也行",[322,1461,1462,1465],{},[326,1463,1464],{},"vue-cli-service build --target lib"," 預設就會同時產出這幾種格式，這也是選它的原因。",[339,1467,1469],{"id":1468},"其他遇到的問題舊-node-需要-python-2","其他遇到的問題：舊 Node 需要 Python 2",[322,1471,1472,1473,1476,1477,1479],{},"切到比較舊的 Node 版本時（",[350,1474,1475],{},"Node 14 以下","），有些原生模組需要 Python 2 才能編譯。手上如果只有 Python 3 就會在 ",[326,1478,406],{}," 階段爆掉。",[322,1481,1482],{},"Python 也有版本管理工具，用 pyenv 裝一份 2.7 放著：",[436,1484,1486],{"className":438,"code":1485,"language":440,"meta":441,"style":441},"pyenv versions\npyenv install 2.7.18\npyenv global 3.9.6\n",[326,1487,1488,1495,1504],{"__ignoreMap":441},[445,1489,1490,1492],{"class":447,"line":448},[445,1491,53],{"class":451},[445,1493,1494],{"class":454}," versions\n",[445,1496,1497,1499,1501],{"class":447,"line":664},[445,1498,53],{"class":451},[445,1500,477],{"class":454},[445,1502,1503],{"class":458}," 2.7.18\n",[445,1505,1506,1508,1511],{"class":447,"line":741},[445,1507,53],{"class":451},[445,1509,1510],{"class":454}," global",[445,1512,1513],{"class":458}," 3.9.6\n",[322,1515,1516,1517,400],{},"pyenv 的完整用法另外寫在 ",[331,1518,1519],{"href":48},"pyenv 與 Python 版本管理",[339,1521,1523],{"id":1522},"_2026-年後記","2026 年後記",[343,1525,1526,1529],{},[346,1527,1528],{},"本文保留 Vue 2 與 Vue CLI 的舊發布流程。",[346,1530,1531],{},"npm 的驗證、套件輸出與發布設定會隨工具版本改變，若重新發布套件請先核對目前 npm 與框架文件，也不要把發布憑證放進專案。",[339,1533,1534],{"id":1534},"參考資料",[343,1536,1537,1544,1551],{},[346,1538,1539],{},[331,1540,1543],{"href":1541,"rel":1542},"https:\u002F\u002Fdocs.npmjs.com\u002Fcli\u002Fcommands\u002Fnpm-dist-tag",[335],"npm dist-tag 文件",[346,1545,1546],{},[331,1547,1550],{"href":1548,"rel":1549},"https:\u002F\u002Fcli.vuejs.org\u002Fguide\u002Fbuild-targets.html#library",[335],"Vue CLI：Library 模式",[346,1552,1553],{},[331,1554,1557],{"href":1555,"rel":1556},"https:\u002F\u002Fchoosealicense.com\u002F",[335],"Choose a License",[1559,1560,1561],"style",{},"html pre.shiki code .sYRkA, html code.shiki .sYRkA{--shiki-default:#6F42C1;--shiki-dark:#FFA657}html pre.shiki code .sNbzA, html code.shiki .sNbzA{--shiki-default:#032F62;--shiki-dark:#A5D6FF}html pre.shiki code .sPgVT, html code.shiki .sPgVT{--shiki-default:#005CC5;--shiki-dark:#79C0FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sDgYj, html code.shiki .sDgYj{--shiki-default:#D73A49;--shiki-dark:#FF7B72}html pre.shiki code .szmH1, html code.shiki .szmH1{--shiki-default:#24292E;--shiki-dark:#E6EDF3}html pre.shiki code .sfpNf, html code.shiki .sfpNf{--shiki-default:#24292E;--shiki-dark:#FFA657}html pre.shiki code .sVjZL, html code.shiki .sVjZL{--shiki-default:#6F42C1;--shiki-dark:#D2A8FF}html pre.shiki code .sjlk-, html code.shiki .sjlk-{--shiki-default:#E36209;--shiki-dark:#FFA657}html pre.shiki code .sPyeA, html code.shiki .sPyeA{--shiki-default:#6A737D;--shiki-dark:#8B949E}html pre.shiki code .swgif, html code.shiki .swgif{--shiki-default:#005CC5;--shiki-dark:#7EE787}html pre.shiki code .sw7DY, html code.shiki .sw7DY{--shiki-default:#005CC5;--shiki-dark:#FF7B72}",{"title":441,"searchDepth":741,"depth":741,"links":1563},[1564,1565,1570,1577,1584,1585,1588,1589,1590],{"id":341,"depth":664,"text":341},{"id":385,"depth":664,"text":386,"children":1566},[1567,1568,1569],{"id":434,"depth":741,"text":434},{"id":503,"depth":741,"text":503},{"id":526,"depth":741,"text":526},{"id":618,"depth":664,"text":618,"children":1571},[1572,1573,1574,1575,1576],{"id":621,"depth":741,"text":622},{"id":637,"depth":741,"text":638},{"id":687,"depth":741,"text":688},{"id":699,"depth":741,"text":700},{"id":842,"depth":741,"text":843},{"id":1141,"depth":664,"text":1141,"children":1578},[1579,1580,1581,1582,1583],{"id":1144,"depth":741,"text":1144},{"id":1176,"depth":741,"text":1176},{"id":1194,"depth":741,"text":1194},{"id":1209,"depth":741,"text":1209},{"id":1241,"depth":741,"text":1241},{"id":1294,"depth":664,"text":1295},{"id":1356,"depth":664,"text":1356,"children":1586},[1587],{"id":1385,"depth":741,"text":1385},{"id":1468,"depth":664,"text":1469},{"id":1522,"depth":664,"text":1523},{"id":1534,"depth":664,"text":1534},false,"md",null,{},"2025-01-22",[],{"title":59,"description":60},"posts\u002F20250122.npm-publish-vue2-component",[62,63,64,65,66],"2026-08-12","9e4hZyx7_gzB6xGMwlhFAfQINAs7kabRjcRtpoOuXv0",[1603,1606],{"title":69,"path":68,"stem":1604,"description":70,"category":8,"publishedAt":1605,"children":-1},"posts\u002F20250725.mobile-debugging-today","2025-07-25",{"title":49,"path":48,"stem":1607,"description":50,"category":8,"publishedAt":1608,"children":-1},"posts\u002F20240807.pyenv-python-version-management","2024-08-07",1791786901503]