周尚緯
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
1
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
# .NET Framework 裡,有關 Web.config (App.config) 的應用 [![hackmd-github-sync-badge](https://hackmd.io/K0ALoDQWSSKmWy5jMWEjPA/badge)](https://hackmd.io/K0ALoDQWSSKmWy5jMWEjPA) ## 依不同組建組態發佈不同的設定檔 正常來說,本機開發、測試環境以及正式環境的 Web.config (App.config) 設定都會不一樣,如果每次更新程式時,都要將設定改為對應環境的設定值,過於麻煩;如果選擇更新程式不更新 Web.config (App.config),又有可能會造成有新增或調整設定時,忘記調整測試/開發環境上的設定檔內容。 有一種作法是每次更新程式都覆蓋設定檔,但是在發佈更新程式時,會直接產製對應環境的設定檔。 ### 組建組態 如果有需要依照不同的設定來建置專案時,會需要設定組建組態。 不同的設定涵蓋產出不同的設定檔、編譯選項或依不同的專案常數產出不同的編譯結果,詳情請參閱「[了解組建組態](https://learn.microsoft.com/zh-tw/visualstudio/ide/understanding-build-configurations?view=vs-2022)」。 預設組建組態有 `debug` 和 `release`,可從 IDE 上進行切換。 ![](https://i.imgur.com/a3ekJqD.png) ### Web 專案發佈 有關專案發佈的部分,這邊僅針對資料夾發佈的部分進行說明,其他發佈方式我也沒玩過,如果有需要,請參閱「[快速入門:發佈 ASP.NET Web 應用程式](https://learn.microsoft.com/zh-tw/visualstudio/deployment/quickstart-deploy-aspnet-web-app)」。 #### 新增發佈設定檔 1. 對專案點選右鍵按「發佈」。 ![](https://i.imgur.com/WtryszZ.png) 2. 點擊「新增發佈設定」。 ![](https://i.imgur.com/Pr58IWg.png) 3. 這篇文章只講資料夾發佈,所以選擇資料夾。 ![](https://i.imgur.com/3HksWmy.png) 4. 設定輸出資料夾,我習慣上會設定成「bin\Publish\{組態名稱}」,這邊設定成「bin\Publish\Release」。 ![](https://i.imgur.com/vBWDUf7.png) 5. 後續新增完建議更改發佈檔名稱,建議和組態名稱一致或有簡易說明。 ![](https://i.imgur.com/WGWFUXp.png) 6. 編輯發佈設定,基本的設定可以使用 UI 編輯,這邊我會全打勾,實務上請依需求調整,像是如果是使用發佈到網站,又設定成「發佈前刪除所有的檔案」會造成網站上的儲存的暫存檔案(e.g. 上傳的檔案)都被一併刪除。 ![](https://i.imgur.com/3PSZyYm.png) 7. 可以直接修改 XML 變更發佈的設定,例如增加`<ExcludeFilesFromDeployment>packages.config;Scripts\_references.js</ExcludeFilesFromDeployment>`,使之在發佈時,排除特定檔案,至於 XML 具體有哪些發佈設定,目前並無在 MSDN 上查到相關說明。 ![](https://i.imgur.com/ArhmVwa.png) :::info 當建立發佈設定檔時,會再產生一個名為「{Profile}.pubxml.user」的檔案,此檔案不知用途,實際看起來比較像是發佈紀錄,但這就和 MSDN 上說明不同,總之這個檔案是不該進入版控,實際上 Viusal Studio 預設的「.gitignore」也會忽略附檔名為「.user」這類使用者設置檔。 ::: #### Web.config Transform 當建立一個新的 Web 專案時,會發現專案根目錄預設有三個 Config 檔案,「Web.config」、「Web.Debug.config」和「Web.Release.config」,但在建置專案時,會發現都是使用「Web.config」的設定,其餘兩個 Config 其實是在發佈時,用來轉換「Web.config」的部分內容。 * 當有發生缺漏組建組態對應的「Web.{組態名稱}.config」檔案時(有可能是誤刪除或是有新建其他組建組態),在「Web.config」上點右鍵,可以看到「新增設定轉換」可以點選,點選後就會建立缺漏的 Config 檔案。 ![](https://i.imgur.com/QAE1IzD.png) * 對著「Web.{組態名稱}.config」點右鍵,選擇「預覽和轉換」,可以查看轉換結果。 ![](https://i.imgur.com/6HPVafy.png) * Transform 的替換機制。 Transform 是用 XML 結構來定位要替換內容,`xdt:Transform` 屬性設定替換方式,使用以下範例內容進行解說。 ```xml <a> <b> <c> <e name="e1" valu1="v1"></e> <e name="e2" valu1="v2"></e> </c> <d></d> </b> </a> ``` 如果要替換 `<d>` 節點的內容,就需要準備一個包含 `<d>` 節點及全部父節點的 XML,結構如下。 ```xml <a> <b> <d xdt:Transform="Replace"></d> </b> </a> ``` 而像`<e>` 這種同一節點底下,有多個相同節點名的,就需要使用屬性`xdt:Locator` 來定位,舉例來說,如果要替換`<e name="e1"></e>`的話,則 XML 內容為。 ```xml <a> <b> <c> <e name="e1" value="v11" xdt:Locator="Match(name)" xdt:Transform="SetAttributes"></e> </c> </b> </a> ``` * 常用的轉換設定 * 更換 `connectionStrings` ```xml <!--全部的 connectionStrings 都更換--> <connectionStrings xdt:Transform="Replace"> <add name="Default" connectionString="{connectionString}" providerName="System.Data.SqlClient" /> </connectionStrings> <!--只替換單一字串--> <add name="Default" connectionString="{connectionString}" providerName="System.Data.SqlClient" xdt:Locator="Match(name)" xdt:Transform="SetAttributes" /> ``` * 更換 `appSettings` ```xml <!--建議單獨替換,而不是整個 appSettings 都替換--> <add key="key" value="value1" xdt:Locator="Match(key)" xdt:Transform="SetAttributes" /> ``` * `system.web` 常見替換項目 ```xml <!--將 mode="Off" 改為 RemoteOnly,並新增 defaultRedirect --> <customErrors mode="RemoteOnly" xdt:Transform="SetAttributes" /> <!--將 enableVersionHeader 改為 false--> <httpRuntime enableVersionHeader="false" xdt:Transform="SetAttributes(enableVersionHeader)" /> <!--將 requireSSL 改為 true--> <httpCookies requireSSL="true" xdt:Transform="SetAttributes(requireSSL)" /> <!--移除 debug="true" 的設定--> <compilation xdt:Transform="RemoveAttributes(debug)" /> ``` 完整的 Transform 語法,可以參考「[使用 Visual Studio 部署 Web 項目的 Web.config 轉換語法](https://learn.microsoft.com/en-us/previous-versions/aspnet/dd465326(v=vs.110))」。 #### 發佈 選擇發佈後,會在目標資料夾看到輸出後的檔案,此時會發現產出的「Web.config」是合併後的內容。 ![](https://i.imgur.com/zUV2lLy.png) #### 範例 原本 Web.config ```xml <?xml version="1.0" encoding="utf-8"?> <configuration> <connectionStrings> <add name="MyDB" connectionString="Data Source=SQLServer;Initial Catalog=MyDB;Integrated Security=True" /> </connectionStrings> <appSettings> <add key="webpages:Version" value="3.0.0.0" /> <add key="webpages:Enabled" value="false" /> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> <add key="MyKey" value="MyValue" /> </appSettings> <system.web> <compilation debug="true" targetFramework="4.8.1" /> <customErrors mode="Off" /> <httpRuntime targetFramework="4.8.1" /> <httpCookies requireSSL="false" /> </system.web> <!--後面的沒異動,這邊範例省略--> </configuration> ``` Web.Release.config ```xml <?xml version="1.0" encoding="utf-8"?> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <connectionStrings> <add name="MyDB" connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" /> </connectionStrings> <appSettings> <add key="MyKey" value="MyReleaseValue" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" /> </appSettings> <system.web> <compilation xdt:Transform="RemoveAttributes(debug)" /> <customErrors mode="RemoteOnly" xdt:Transform="SetAttributes" /> <httpRuntime enableVersionHeader="false" xdt:Transform="SetAttributes(enableVersionHeader)" /> <!--將 requireSSL 改為 true--> <httpCookies requireSSL="true" xdt:Transform="SetAttributes(requireSSL)" /> </system.web> </configuration> ``` 發佈後的 Web.config ```xml <?xml version="1.0" encoding="utf-8"?> <configuration> <connectionStrings> <add name="MyDB" connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" /> </connectionStrings> <appSettings> <add key="webpages:Version" value="3.0.0.0" /> <add key="webpages:Enabled" value="false" /> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> <add key="MyKey" value="MyReleaseValue" /> </appSettings> <system.web> <compilation targetFramework="4.8.1" /> <customErrors mode="RemoteOnly" /> <httpRuntime targetFramework="4.8.1" enableVersionHeader="false" /> <httpCookies requireSSL="true" /> </system.web> <runtime> <!--後面的沒異動,這邊範例省略--> </configuration> ``` ### **非** Web 專案發佈 非 Web 專案預設並無支援「App.config」Transform,所以需要安裝其他套件處理。 #### 套件 * Visual Studio:在延伸模組安裝「SlowCheetah」。 * NuGet:在要使用 Config Transform 的專案上安裝「Microsoft.VisualStudio.SlowCheetah」。 當 Visual Studio 安裝「SlowCheetah」以後,非 Web 專案的 App.config 右鍵選單會增加一個 「Add Transform」的選項,選擇可以產生其他組態的 Config。 ![](https://i.imgur.com/lV7Hlzk.png) 如果 NuGet 未安裝「Microsoft.VisualStudio.SlowCheetah」,會提醒並自動安裝。 ![](https://i.imgur.com/3o0nvC5.png) :::info 其實 Visual Studio 還有另外一個擴充套件 「ConfigTransformation」可支援 Config Transform,且不需要在專案上額外安裝 NuGet 套件,但 Visual Studio 2022 並不支援此擴充套件,且只能針對完整 Config 結構(根節點為 `<configuration />`)的 XML 進行轉換。 ::: #### 建置 「.NET Framework」的非 Web 專案的發佈是使用 ClickOnce,無法像 Web一樣用一般的發佈到資料夾,但是它的建置會觸發 Config Transform,所以選擇要發佈的組態設定後,建置專案即可,建議建置專案前,先刪除「bin」資料夾。 ![](https://i.imgur.com/4Nz2dVs.png) #### 範例 原本的 App.config ```xml <?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="MyDB" connectionString="Data Source=SQLServer;Initial Catalog=MyDB;Integrated Security=True" /> </connectionStrings> <appSettings> <add key="MyKey" value="MyValue" /> </appSettings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.1" /> </startup> </configuration> ``` App.Release.config ```xml <?xml version="1.0" encoding="utf-8"?> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <connectionStrings> <add name="MyDB" connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" /> </connectionStrings> <appSettings> <add key="MyKey" value="MyReleaseValue" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" /> </appSettings> </configuration> ``` 建置後的 {專案名稱}.exe.config ```xml <?xml version="1.0" encoding="utf-8"?> <configuration> <connectionStrings> <add name="MyDB" connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" /> </connectionStrings> <appSettings> <add key="MyKey" value="MyReleaseValue" /> </appSettings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.1" /> </startup> </configuration> ``` ## 不同專案共用設定檔 如果整個方案底下有多個專案需要連同一個資料庫,例如有網站、多個排程程式或 Web API 等,而每當更換資料庫環境時,就需要全部的專案都進行修改,此時可以考慮將 `<connectionStrings />` 單獨放置一個檔案,來讓多個專案進行引用。 ### 設定步驟 以下建立一個專案 Library 專案,並新增「AppGlobal.config」、「Connection.config」和「Smtp.config」三個設定檔,三個設定檔都設定 Config Transform。 為了方便,後續會將這三個設定檔統稱為外部設定檔,Config Transform 產出生出來的稱為外部組態設定檔。 ![](https://i.imgur.com/kbqSDeH.png) #### 設定 Config 內容 這邊以僅以 AppGlobal.config 為例。 AppGlobal.config ```xml <?xml version="1.0" encoding="utf-8" ?> <appSettings> <add key="Test" value="TestValue1" /> </appSettings> ``` ```xml <?xml version="1.0" encoding="utf-8" ?> <!--根節點必須包含屬性 xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" --> <appSettings xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <add key="Test" value="TestReleaseValue1" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" /> </appSettings> ``` #### 從 Web 專案加入引用 * 安裝「Microsoft.VisualStudio.SlowCheetah」來處理這些外部設定檔的轉換。 * Web 專案除了加入 Library 的專案參考 * 新建的三個 Config 及相關組態檔的檔案連結。 Web 專案選擇加入現有項目。 ![](https://i.imgur.com/5XqOo6H.png) 使用加入連結的方式來新增外部設定檔及相關的外部組態設定檔。 ![](https://i.imgur.com/bUwNQOb.png) * 開啟專案檔(csproj)進行以下修改: * 增加 `<TransformOnBuild>true</TransformOnBuild>`,標註要建置時要執行 Config Transform。 * 外部設定檔增加 `<CopyToOutputDirectory>Always</CopyToOutputDirectory>`。 * 將外部組態設定檔改從 `<Content />` 節點改為 `<None />` 節點,避免發佈時,也同時被發佈出去。 * 外部組態設定檔增加 `<DependentUpon />` 節點,使之在 Visual Studio 上面是巢狀顯示在外部設定檔下方。 ```xml <Content Include="..\BuildConfigSample.Library\AppGlobal.config"> <Link>AppGlobal.config</Link> <TransformOnBuild>true</TransformOnBuild> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> <None Include="..\BuildConfigSample.Library\AppGlobal.Debug.config"> <Link>AppGlobal.Debug.config</Link> <DependentUpon>AppGlobal.config</DependentUpon> <TransformOnBuild>true</TransformOnBuild> </None> <None Include="..\BuildConfigSample.Library\AppGlobal.Release.config"> <Link>AppGlobal.Release.config</Link> <DependentUpon>AppGlobal.config</DependentUpon> <TransformOnBuild>true</TransformOnBuild> </None> <!--Connection.config、Smtp.config 改法一樣--> ``` * 修改「Web.config」和「Web.Release.config」來外部引用外部設定檔。 * `configSource` 和 `file` 屬性的差別是後者允許增加其他設定做合併。 * `<connectionStrings />` 和 `<smtp />` 皆不可使用 `file`。 * `<appSettings />` 允許使用 `configSource`,但建議使用 `file`。 * `<appSettings />` 如果外部引用設定檔的 `key`,與自己增加的 `key` 相同,會使用外部引用的值,所以無法藉由定義相同的 `key` 來覆蓋設定。 * 使用連結的方式加入設定檔,實際上專案根目錄不會有檔案,導致 Web 在執行 Debug 模式時,「Web.config」會無法在同層資料夾找到外部設定檔,所以改引用「bin」底下的檔案(前面在設定時,有將外部設定檔設定「複製到輸出目錄」)。 Web.config ```xml <configuration> <connectionStrings configSource="bin\Connection.config" /> <appSettings file="bin\AppGlobal.config"> <add key="webpages:Version" value="3.0.0.0" /> <add key="webpages:Enabled" value="false" /> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> <add key="MyKey" value="MyValue" /> </appSettings> <system.net> <mailSettings> <smtp configSource="bin\Smtp.config" /> </mailSettings> </system.net> <!--後續內容省略--> </configuration> ``` Web.Release.config ```xml <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <connectionStrings configSource="Connection.config" xdt:Transform="SetAttributes" /> <appSettings file="AppGlobal.config" xdt:Transform="SetAttributes"> <add key="MyKey" value="MyReleaseValue" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" /> </appSettings> <system.net> <mailSettings> <smtp configSource="Smtp.config" xdt:Transform="Replace" /> </mailSettings> </system.net> <!--後續內容省略--> </configuration> ``` #### 從**非** Web 專案加入引用 前面操作步驟都和 Web 一樣,但修改專案檔和 App.config 的內容稍微有點不同。 專案檔裡的外部設定檔是使用 `<None />` 節點。 ```xml <None Include="..\BuildConfigSample.Library\AppGlobal.config"> <Link>AppGlobal.config</Link> <TransformOnBuild>true</TransformOnBuild> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Include="..\BuildConfigSample.Library\AppGlobal.Debug.config"> <Link>AppGlobal.Debug.config</Link> <DependentUpon>AppGlobal.config</DependentUpon> <TransformOnBuild>true</TransformOnBuild> </None> <None Include="..\BuildConfigSample.Library\AppGlobal.Release.config"> <Link>AppGlobal.Release.config</Link> <DependentUpon>AppGlobal.config</DependentUpon> <TransformOnBuild>true</TransformOnBuild> </None> ``` :::info `<None />` 節點和 `<Content />`,分別對應建置行為的「None(無)」和「Content(內容)」,其中「Content(內容)」是給 Web 使用的,詳情請參閱「[建置動作值](https://learn.microsoft.com/zh-tw/visualstudio/ide/build-actions?view=vs-2022#build-action-values)」。 ::: ##### App.config 由於 Debug 模式,設定檔本身就是使用「bin\{組態名稱}」底下的 「{專案名稱}.exe.config」檔案,所以路徑不需要指定到「bin」底下。 ```xml <?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings configSource="Connection.config" /> <appSettings file="AppGlobal.config"> <add key="MyKey" value="MyValue" /> </appSettings> <system.net> <mailSettings> <smtp configSource="Smtp.config" /> </mailSettings> </system.net> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.1" /> </startup> </configuration> ``` ##### App.Release.config 改成外部引用後 App.Release.config 就不需要轉換 connectionStrings 內容。 ```xml <?xml version="1.0" encoding="utf-8"?> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <appSettings> <add key="MyKey" value="MyReleaseValue" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" /> </appSettings> </configuration> ``` :::warning 如果使用 Entity Framework 的 Database First,則該專案的 App.config 的連線字串不能使用外部引用檔的方式設定,否則 Entity Framework 的 UI 會找不到已經設定好的連線字串。 ::: ## 切斷 Web.config 的繼承關係 IIS 允許在網站底下建置子網站,此時子網站的 Web.config 會繼承父網站的設定,有時候會發生衝突,特別是在兩邊的 Framework 版本有差異的情況下,此時可以在父網站使用 `<location>` 來切斷繼承,寫法如下: ```xml <location path="." inheritInChildApplications="false"> <system.web> <!--...內部程式碼...--> </system.web> </location> ``` :::info 理論上`<location />` 寫在 `<system.web />` 外就夠了,但如果有需要,也可以加在其他節點外,但如果專案有使用 Entity Framework 的 Database First,那千萬不要寫在 `<connectionStrings />` 外層,反則會造成 Entity Framework 的 UI 無法讀到已設定的連線字串(又是這個問題 orz)。 ::: ### 相關連結 * [如何讓同一個 IIS 站台設定兩個不同的 ASP.NET 應用程式](https://blog.miniasp.com/post/2008/06/15/Making-child-ASPNET-applications-work) ###### tags: `.NET` `.NET Framework`

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully