├── .DS_Store ├── .gitattributes ├── .gitignore ├── LICENSE ├── LICENSE.md ├── converter ├── converter.go └── util.go ├── effect.png ├── example ├── .DS_Store └── gogs_zh │ ├── .DS_Store │ ├── 07fbf67d05c29c0bca39917e2baee1b0.png │ ├── 538.html │ ├── 539.html │ ├── 540.html │ ├── 542.html │ ├── 543.html │ ├── 544.html │ ├── 545.html │ ├── 546.html │ ├── 547.html │ ├── 548.html │ ├── 549.html │ ├── 550.html │ ├── 551.html │ ├── 552.html │ ├── 553.html │ ├── 554.html │ ├── 555.html │ ├── 556.html │ ├── 557.html │ ├── 558.html │ ├── 559.html │ ├── 560.html │ ├── 8b35028d0518c77d8308ff3dd97e97a0.png │ ├── 99327ac61c6444a0839c551d6fd06e5f.gif │ ├── a16e019f33ab5660b83b52f2ee5c8a24.png │ ├── a97fed77a57e0e7788343c4674bb4c45.png │ ├── config.json │ ├── d4643fd6157facd3f4178141fb4ab85d.png │ ├── d92fc8f1c8954dda582909a8d37bc6c6.png │ ├── e00b4e8899e00091e6ac46d230d53c2f.png │ ├── editormd.css │ ├── output │ ├── book.epub │ ├── book.mobi │ └── book.pdf │ └── statement.html ├── go.mod ├── go.sum ├── main.go └── readme.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=go 2 | *.css linguist-language=go 3 | *.html linguist-language=go -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Go template 3 | # Binaries for programs and plugins 4 | #*.exe 5 | *.dll 6 | *.so 7 | *.dylib 8 | 9 | # Test binary, build with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 16 | .glide/ 17 | ### JetBrains template 18 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 19 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 20 | 21 | # User-specific stuff: 22 | .idea/**/workspace.xml 23 | .idea/**/tasks.xml 24 | .idea/dictionaries 25 | 26 | # Sensitive or high-churn files: 27 | .idea/**/dataSources/ 28 | .idea/**/dataSources.ids 29 | .idea/**/dataSources.xml 30 | .idea/**/dataSources.local.xml 31 | .idea/**/sqlDataSources.xml 32 | .idea/**/dynamic.xml 33 | .idea/**/uiDesigner.xml 34 | 35 | # Gradle: 36 | .idea/**/gradle.xml 37 | .idea/**/libraries 38 | 39 | # CMake 40 | cmake-build-debug/ 41 | 42 | # Mongo Explorer plugin: 43 | .idea/**/mongoSettings.xml 44 | 45 | ## File-based project format: 46 | *.iws 47 | 48 | ## Plugin-specific files: 49 | 50 | # IntelliJ 51 | out/ 52 | 53 | # mpeltonen/sbt-idea plugin 54 | .idea_modules/ 55 | 56 | # JIRA plugin 57 | atlassian-ide-plugin.xml 58 | 59 | # Cursive Clojure plugin 60 | .idea/replstate.xml 61 | 62 | # Crashlytics plugin (for Android Studio and IntelliJ) 63 | com_crashlytics_export_strings.xml 64 | crashlytics.properties 65 | crashlytics-build.properties 66 | fabric.properties 67 | ### Windows template 68 | # Windows thumbnail cache files 69 | Thumbs.db 70 | ehthumbs.db 71 | ehthumbs_vista.db 72 | 73 | # Dump file 74 | *.stackdump 75 | 76 | # Folder config file 77 | [Dd]esktop.ini 78 | 79 | # Recycle Bin used on file shares 80 | $RECYCLE.BIN/ 81 | 82 | # Windows Installer files 83 | *.cab 84 | *.msi 85 | *.msm 86 | *.msp 87 | 88 | # Windows shortcuts 89 | *.lnk 90 | 91 | .gitignore 92 | .idea/ 93 | #example/gogs_zh/output 94 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /converter/converter.go: -------------------------------------------------------------------------------- 1 | // Author:TruthHun 2 | // Email:TruthHun@QQ.COM 3 | // Date:2018-01-21 4 | package converter 5 | 6 | import ( 7 | "bytes" 8 | "fmt" 9 | "io/ioutil" 10 | "os" 11 | "path/filepath" 12 | "strings" 13 | 14 | "time" 15 | 16 | "os/exec" 17 | 18 | "errors" 19 | 20 | "github.com/TruthHun/gotil/cryptil" 21 | "github.com/TruthHun/gotil/filetil" 22 | "github.com/TruthHun/gotil/ziptil" 23 | ) 24 | 25 | type Converter struct { 26 | BasePath string 27 | Config Config 28 | Debug bool 29 | GeneratedCover string 30 | Callback func(identifier, ebookPath string, err error) // 每本电子书生成后的回调 31 | } 32 | 33 | // 目录结构 34 | type Toc struct { 35 | Id int `json:"id"` 36 | Link string `json:"link"` 37 | Pid int `json:"pid"` 38 | Title string `json:"title"` 39 | } 40 | 41 | // config.json文件解析结构 42 | type Config struct { 43 | Charset string `json:"charset"` //字符编码,默认utf-8编码 44 | Cover string `json:"cover"` //封面图片,或者封面html文件 45 | Timestamp string `json:"date"` //时间日期,如“2018-01-01 12:12:21”,其实是time.Time格式,但是直接用string就好 46 | Description string `json:"description"` //摘要 47 | Footer string `json:"footer"` //pdf的footer 48 | Header string `json:"header"` //pdf的header 49 | Identifier string `json:"identifier"` //即uuid,留空即可 50 | Language string `json:"language"` //语言,如zh、en、zh-CN、en-US等 51 | Creator string `json:"creator"` //作者,即author 52 | Publisher string `json:"publisher"` //出版单位 53 | Contributor string `json:"contributor"` //同Publisher 54 | Title string `json:"title"` //文档标题 55 | Format []string `json:"format"` //导出格式,可选值:pdf、epub、mobi、docx 56 | FontSize string `json:"font_size"` //默认的pdf导出字体大小 57 | PaperSize string `json:"paper_size"` //页面大小 58 | MarginLeft string `json:"margin_left"` //PDF文档左边距,写数字即可,默认72pt 59 | MarginRight string `json:"margin_right"` //PDF文档左边距,写数字即可,默认72pt 60 | MarginTop string `json:"margin_top"` //PDF文档左边距,写数字即可,默认72pt 61 | MarginBottom string `json:"margin_bottom"` //PDF文档左边距,写数字即可,默认72pt 62 | More []string `json:"more"` //更多导出选项[PDF导出选项,具体参考:https://manual.calibre-ebook.com/generated/en/ebook-convert.html#pdf-output-options] 63 | Toc []Toc `json:"toc"` //目录 64 | /////////////////////////////////////////// 65 | Order []string `json:"-"` //这个不需要赋值 66 | } 67 | 68 | var ( 69 | output = "output" //文档导出文件夹 70 | ebookConvert = "ebook-convert" 71 | ) 72 | 73 | // 根据json配置文件,创建文档转化对象 74 | func NewConverter(configFile string, debug ...bool) (converter *Converter, err error) { 75 | var ( 76 | cfg Config 77 | basepath string 78 | db bool 79 | ) 80 | if len(debug) > 0 { 81 | db = debug[0] 82 | } 83 | 84 | if cfg, err = parseConfig(configFile); err == nil { 85 | if basepath, err = filepath.Abs(filepath.Dir(configFile)); err == nil { 86 | //设置默认值 87 | if len(cfg.Timestamp) == 0 { 88 | cfg.Timestamp = time.Now().Format("2006-01-02 15:04:05") 89 | } 90 | if len(cfg.Charset) == 0 { 91 | cfg.Charset = "utf-8" 92 | } 93 | converter = &Converter{ 94 | Config: cfg, 95 | BasePath: basepath, 96 | Debug: db, 97 | } 98 | } 99 | } 100 | return 101 | } 102 | 103 | // 执行文档转换 104 | func (this *Converter) Convert() (err error) { 105 | if !this.Debug { //调试模式下不删除生成的文件 106 | defer this.converterDefer() //最后移除创建的多余而文件 107 | } 108 | 109 | if err = this.generateMimeType(); err != nil { 110 | return 111 | } 112 | if err = this.generateMetaInfo(); err != nil { 113 | return 114 | } 115 | if err = this.generateTocNcx(); err != nil { //生成目录 116 | return 117 | } 118 | if err = this.generateSummary(); err != nil { //生成文档内目录 119 | return 120 | } 121 | if err = this.generateTitlePage(); err != nil { //生成封面 122 | return 123 | } 124 | if err = this.generateContentOpf(); err != nil { //这个必须是generate*系列方法的最后一个调用 125 | return 126 | } 127 | 128 | //将当前文件夹下的所有文件压缩成zip包,然后直接改名成content.epub 129 | f := this.BasePath + "/content.epub" 130 | 131 | os.Remove(f) //如果原文件存在了,则删除; 132 | if err = ziptil.Zip(f, this.BasePath); err != nil { 133 | return 134 | } 135 | 136 | //创建导出文件夹 137 | os.Mkdir(this.BasePath+"/"+output, os.ModePerm) 138 | 139 | //处理直接压缩后的content.epub文件,将其转成新的content-tmp.epub文件 140 | //再用content-tmp.epub文件替换掉content.epub文件,这样content.epub文件转PDF的时候,就不会出现空白页的情况了 141 | tmp := this.BasePath + "/content-tmp.epub" 142 | if _, err = execCommand(ebookConvert, []string{f, tmp}); err == nil { 143 | // 重命名文件 144 | os.Remove(f) 145 | os.Rename(tmp, f) 146 | } 147 | 148 | // 只生成PDF电子书 149 | formatLen := len(this.Config.Format) 150 | if formatLen == 0 { 151 | err = this.convertToPdf() 152 | return 153 | } 154 | 155 | var errs []string 156 | for _, v := range this.Config.Format { 157 | fmt.Println("\nconvert to " + v) 158 | v = strings.ToLower(v) 159 | switch strings.ToLower(v) { 160 | case "epub", ".epub": 161 | //注意:由于之前已经将其转成content.epub了,所以这里直接复制就好了,不需要再次转一遍 162 | target := this.BasePath + "/" + output + "/book.epub" 163 | b, err := ioutil.ReadFile(f) 164 | if err == nil { 165 | if err = ioutil.WriteFile(target, b, os.ModePerm); err != nil { 166 | errs = append(errs, err.Error()) 167 | } 168 | } else { 169 | errs = append(errs, err.Error()) 170 | } 171 | if this.Callback != nil { 172 | this.Callback(this.Config.Identifier, target, err) 173 | } 174 | case "mobi", ".mobi": 175 | if err = this.convertToMobi(); err != nil { 176 | errs = append(errs, err.Error()) 177 | } 178 | case "pdf", ".pdf": 179 | if err = this.convertToPdf(); err != nil { 180 | errs = append(errs, err.Error()) 181 | } 182 | case "docx", ".docx": 183 | if err = this.convertToWord(); err != nil { 184 | errs = append(errs, err.Error()) 185 | } 186 | } 187 | } 188 | err = errors.New(strings.Join(errs, "\n")) 189 | return 190 | } 191 | 192 | // 删除生成导出文档而创建的文件 193 | func (this *Converter) converterDefer() { 194 | //删除不必要的文件 195 | os.RemoveAll(this.BasePath + "/META-INF") 196 | os.RemoveAll(this.BasePath + "/content.epub") 197 | os.RemoveAll(this.BasePath + "/mimetype") 198 | os.RemoveAll(this.BasePath + "/toc.ncx") 199 | os.RemoveAll(this.BasePath + "/content.opf") 200 | os.RemoveAll(this.BasePath + "/titlepage.xhtml") //封面图片待优化 201 | os.RemoveAll(this.BasePath + "/summary.html") //文档目录 202 | } 203 | 204 | // 生成metainfo 205 | func (this *Converter) generateMetaInfo() (err error) { 206 | xml := ` 207 | 208 | 209 | 210 | 211 | 212 | ` 213 | folder := this.BasePath + "/META-INF" 214 | os.MkdirAll(folder, os.ModePerm) 215 | err = ioutil.WriteFile(folder+"/container.xml", []byte(xml), os.ModePerm) 216 | return 217 | } 218 | 219 | // 生成mimetyppe 220 | func (this *Converter) generateMimeType() (err error) { 221 | return ioutil.WriteFile(this.BasePath+"/mimetype", []byte("application/epub+zip"), os.ModePerm) 222 | } 223 | 224 | // 生成封面 225 | func (this *Converter) generateTitlePage() (err error) { 226 | if ext := strings.ToLower(filepath.Ext(this.Config.Cover)); !(ext == ".html" || ext == ".xhtml") { 227 | xml := ` 228 | 229 | 230 | 231 | 232 | Cover 233 | 237 | 238 | 239 |
240 | 241 | 242 | 243 |
244 | 245 | 246 | ` 247 | if err = ioutil.WriteFile(this.BasePath+"/titlepage.xhtml", []byte(xml), os.ModePerm); err == nil { 248 | this.GeneratedCover = "titlepage.xhtml" 249 | } 250 | } 251 | return 252 | } 253 | 254 | // 生成文档目录 255 | func (this *Converter) generateTocNcx() (err error) { 256 | ncx := ` 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | %v 266 | 267 | %v 268 | 269 | ` 270 | codes, _ := this.tocToXml(0, 1) 271 | ncx = fmt.Sprintf(ncx, this.Config.Language, this.Config.Title, strings.Join(codes, "")) 272 | return ioutil.WriteFile(this.BasePath+"/toc.ncx", []byte(ncx), os.ModePerm) 273 | } 274 | 275 | // 生成文档目录,即summary.html 276 | func (this *Converter) generateSummary() (err error) { 277 | //目录 278 | summary := ` 279 | 280 | 281 | 282 | 目录 283 | 287 | 288 | 289 |

目    录

290 | %v 291 | 292 | ` 293 | summary = fmt.Sprintf(summary, strings.Join(this.tocToSummary(0), "")) 294 | return ioutil.WriteFile(this.BasePath+"/summary.html", []byte(summary), os.ModePerm) 295 | } 296 | 297 | // 将toc转成toc.ncx文件 298 | func (this *Converter) tocToXml(pid, idx int) (codes []string, next_idx int) { 299 | var code string 300 | for _, toc := range this.Config.Toc { 301 | if toc.Pid == pid { 302 | code, idx = this.getNavPoint(toc, idx) 303 | codes = append(codes, code) 304 | for _, item := range this.Config.Toc { 305 | if item.Pid == toc.Id { 306 | code, idx = this.getNavPoint(item, idx) 307 | codes = append(codes, code) 308 | var code_arr []string 309 | code_arr, idx = this.tocToXml(item.Id, idx) 310 | codes = append(codes, code_arr...) 311 | codes = append(codes, ``) 312 | } 313 | } 314 | codes = append(codes, ``) 315 | } 316 | } 317 | next_idx = idx 318 | return 319 | } 320 | 321 | // 将toc转成summary目录 322 | func (this *Converter) tocToSummary(pid int) (summarys []string) { 323 | summarys = append(summarys, "") 340 | return 341 | } 342 | 343 | // 生成navPoint 344 | func (this *Converter) getNavPoint(toc Toc, idx int) (navpoint string, nextidx int) { 345 | navpoint = ` 346 | 347 | 348 | %v 349 | 350 | ` 351 | navpoint = fmt.Sprintf(navpoint, toc.Id, idx, toc.Title, toc.Link) 352 | this.Config.Order = append(this.Config.Order, toc.Link) 353 | nextidx = idx + 1 354 | return 355 | } 356 | 357 | // 生成content.opf文件 358 | // 倒数第二步调用 359 | func (this *Converter) generateContentOpf() (err error) { 360 | var ( 361 | guide string 362 | manifest string 363 | manifestArr []string 364 | spine string //注意:如果存在封面,则需要把封面放在第一个位置 365 | spineArr []string 366 | ) 367 | 368 | meta := `%v 369 | %v 370 | %v 371 | %v 372 | %v 373 | %v 374 | 375 | ` 376 | meta = fmt.Sprintf(meta, this.Config.Title, this.Config.Contributor, this.Config.Publisher, this.Config.Description, this.Config.Language, this.Config.Creator, this.Config.Timestamp) 377 | if len(this.Config.Cover) > 0 { 378 | meta = meta + `` 379 | guide = `` 380 | manifest = fmt.Sprintf(``, this.Config.Cover, GetMediaType(filepath.Ext(this.Config.Cover))) 381 | spineArr = append(spineArr, ``) 382 | } 383 | 384 | if _, err := os.Stat(this.BasePath + "/summary.html"); err == nil { 385 | spineArr = append(spineArr, ``) //目录 386 | 387 | } 388 | 389 | //扫描所有文件 390 | if files, err := filetil.ScanFiles(this.BasePath); err == nil { 391 | basePath := strings.Replace(this.BasePath, "\\", "/", -1) 392 | for _, file := range files { 393 | if !file.IsDir { 394 | ext := strings.ToLower(filepath.Ext(file.Path)) 395 | sourcefile := strings.TrimPrefix(file.Path, basePath+"/") 396 | id := "ncx" 397 | if ext != ".ncx" { 398 | if file.Name == "titlepage.xhtml" { //封面 399 | id = "titlepage" 400 | } else if file.Name == "summary.html" { //目录 401 | id = "summary" 402 | } else { 403 | id = cryptil.Md5Crypt(sourcefile) 404 | } 405 | } 406 | if mt := GetMediaType(ext); mt != "" { //不是封面图片,且media-type不为空 407 | if sourcefile != strings.TrimLeft(this.Config.Cover, "./") { //不是封面图片,则追加进来。封面图片前面已经追加进来了 408 | manifestArr = append(manifestArr, fmt.Sprintf(``, sourcefile, id, mt)) 409 | } 410 | } 411 | } 412 | } 413 | 414 | items := make(map[string]string) 415 | for _, link := range this.Config.Order { 416 | id := cryptil.Md5Crypt(link) 417 | if _, ok := items[id]; !ok { //去重 418 | items[id] = id 419 | spineArr = append(spineArr, fmt.Sprintf(``, id)) 420 | } 421 | } 422 | manifest = manifest + strings.Join(manifestArr, "\n") 423 | spine = strings.Join(spineArr, "\n") 424 | } else { 425 | return err 426 | } 427 | 428 | pkg := ` 429 | 430 | 431 | %v 432 | 433 | 434 | %v 435 | 436 | 437 | %v 438 | 439 | %v 440 | 441 | ` 442 | if len(guide) > 0 { 443 | guide = `` + guide + `` 444 | } 445 | pkg = fmt.Sprintf(pkg, meta, manifest, spine, guide) 446 | return ioutil.WriteFile(this.BasePath+"/content.opf", []byte(pkg), os.ModePerm) 447 | } 448 | 449 | // 转成epub 450 | func (this *Converter) convertToEpub() (err error) { 451 | args := []string{ 452 | this.BasePath + "/content.epub", 453 | this.BasePath + "/" + output + "/book.epub", 454 | } 455 | 456 | if this.Debug { 457 | fmt.Println(ebookConvert, args) 458 | } 459 | _, err = execCommand(ebookConvert, args) 460 | return 461 | } 462 | 463 | // 转成mobi 464 | func (this *Converter) convertToMobi() (err error) { 465 | target := this.BasePath + "/" + output + "/book.mobi" 466 | args := []string{ 467 | this.BasePath + "/content.epub", 468 | target, 469 | } 470 | 471 | if this.Debug { 472 | fmt.Println(ebookConvert, args) 473 | } 474 | _, err = execCommand(ebookConvert, args) 475 | if this.Callback != nil { // 回调,告知 476 | this.Callback(this.Config.Identifier, target, err) 477 | } 478 | return 479 | } 480 | 481 | // 转成word文档 482 | func (this *Converter) convertToWord() (err error) { 483 | target := this.BasePath + "/" + output + "/book.docx" 484 | args := []string{ 485 | this.BasePath + "/content.epub", 486 | target, 487 | } 488 | if this.Debug { 489 | fmt.Println(ebookConvert, args) 490 | } 491 | _, err = execCommand(ebookConvert, args) 492 | if this.Callback != nil { // 回调,告知 493 | this.Callback(this.Config.Identifier, target, err) 494 | } 495 | return 496 | } 497 | 498 | // 转成pdf 499 | func (this *Converter) convertToPdf() (err error) { 500 | target := this.BasePath + "/" + output + "/book.pdf" 501 | args := []string{ 502 | this.BasePath + "/content.epub", 503 | target, 504 | } 505 | //页面大小 506 | if len(this.Config.PaperSize) > 0 { 507 | args = append(args, "--paper-size", this.Config.PaperSize) 508 | } 509 | //文字大小 510 | if len(this.Config.FontSize) > 0 { 511 | args = append(args, "--pdf-default-font-size", this.Config.FontSize) 512 | } 513 | 514 | //header template 515 | if len(this.Config.Header) > 0 { 516 | args = append(args, "--pdf-header-template", this.Config.Header) 517 | } 518 | 519 | //footer template 520 | if len(this.Config.Footer) > 0 { 521 | args = append(args, "--pdf-footer-template", this.Config.Footer) 522 | } 523 | 524 | if len(this.Config.MarginLeft) > 0 { 525 | args = append(args, "--pdf-page-margin-left", this.Config.MarginLeft) 526 | } 527 | if len(this.Config.MarginTop) > 0 { 528 | args = append(args, "--pdf-page-margin-top", this.Config.MarginTop) 529 | } 530 | if len(this.Config.MarginRight) > 0 { 531 | args = append(args, "--pdf-page-margin-right", this.Config.MarginRight) 532 | } 533 | if len(this.Config.MarginBottom) > 0 { 534 | args = append(args, "--pdf-page-margin-bottom", this.Config.MarginBottom) 535 | } 536 | 537 | //更多选项 538 | if len(this.Config.More) > 0 { 539 | args = append(args, this.Config.More...) 540 | } 541 | 542 | if this.Debug { 543 | fmt.Println(ebookConvert, args) 544 | } 545 | _, err = execCommand(ebookConvert, args) 546 | if this.Callback != nil { 547 | this.Callback(this.Config.Identifier, target, err) 548 | } 549 | return 550 | } 551 | 552 | // ExecCommand 执行cmd命令操作 553 | func execCommand(name string, args []string, timeout ...time.Duration) (out string, err error) { 554 | var ( 555 | stderr, stdout bytes.Buffer 556 | expire = 60 * time.Minute 557 | ) 558 | 559 | if len(timeout) > 0 { 560 | expire = timeout[0] 561 | } 562 | 563 | cmd := exec.Command(name, args...) 564 | cmd.Stdout = &stdout 565 | cmd.Stderr = &stderr 566 | time.AfterFunc(expire, func() { 567 | if cmd.Process != nil && cmd.Process.Pid != 0 { 568 | out = out + fmt.Sprintf("\nexecute timeout: %v seconds.", expire.Seconds()) 569 | cmd.Process.Kill() 570 | } 571 | }) 572 | err = cmd.Run() 573 | if err != nil { 574 | err = fmt.Errorf("%v\n%v", err.Error(), stderr.String()) 575 | } 576 | out = stdout.String() 577 | return 578 | } 579 | -------------------------------------------------------------------------------- /converter/util.go: -------------------------------------------------------------------------------- 1 | //Author:TruthHun 2 | //Email:TruthHun@QQ.COM 3 | //Date:2018-01-21 4 | package converter 5 | 6 | import ( 7 | "encoding/json" 8 | "io/ioutil" 9 | "strings" 10 | ) 11 | 12 | //media-type 13 | var MediaType = map[string]string{ 14 | ".jpeg": "image/jpeg", 15 | ".png": "image/png", 16 | ".jpg": "image/jpeg", 17 | ".gif": "image/gif", 18 | ".ico": "image/x-icon", 19 | ".bmp": "image/bmp", 20 | ".html": "application/xhtml+xml", 21 | ".xhtml": "application/xhtml+xml", 22 | ".htm": "application/xhtml+xml", 23 | ".otf": "application/x-font-opentype", 24 | ".ttf": "application/x-font-ttf", 25 | ".js": "application/x-javascript", 26 | ".ncx": "x-dtbncx+xml", 27 | ".txt": "text/plain", 28 | ".xml": "text/xml", 29 | ".css": "text/css", 30 | } 31 | 32 | //根据文件扩展名,获取media-type 33 | func GetMediaType(ext string) string { 34 | if mt, ok := MediaType[strings.ToLower(ext)]; ok { 35 | return mt 36 | } 37 | return "" 38 | } 39 | 40 | //解析配置文件 41 | func parseConfig(configFile string) (cfg Config, err error) { 42 | var b []byte 43 | if b, err = ioutil.ReadFile(configFile); err == nil { 44 | err = json.Unmarshal(b, &cfg) 45 | } 46 | return 47 | } 48 | -------------------------------------------------------------------------------- /effect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/effect.png -------------------------------------------------------------------------------- /example/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/.DS_Store -------------------------------------------------------------------------------- /example/gogs_zh/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/.DS_Store -------------------------------------------------------------------------------- /example/gogs_zh/07fbf67d05c29c0bca39917e2baee1b0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/07fbf67d05c29c0bca39917e2baee1b0.png -------------------------------------------------------------------------------- /example/gogs_zh/538.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

5. 高级用法

12 |
13 |

高级用法

14 |
15 | 16 | -------------------------------------------------------------------------------- /example/gogs_zh/540.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

5.2 公告与高阶指南

12 |
13 |

公告与高阶指南

公告博文

15 |

高阶指南

17 | 18 |
19 | 20 | -------------------------------------------------------------------------------- /example/gogs_zh/542.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

6. 捐赠我们

12 |
13 |

捐赠我们


在您的支持与鼓励下,Gogs 开发团队将会更加努力地开发出更好的产品!

14 | 15 |


支付宝捐赠

16 | 17 |


Paypal 捐赠









19 | 20 |

您的捐赠将被用于:

    21 |
  • 持续和深入的开发
  • 维护社区的运行稳定
  • 租用更好的带宽
  • 奖励团队的杰出贡献者
  • 社区活动或讲座
22 |

捐赠列表(按照捐赠时间倒序)

23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 |
捐赠时间捐赠人金额
2017-11-23朱同学¥20.00
2017-11-20余同学¥10.00
2017-10-28寒子¥6.66
2017-10-26向同学¥10.00
2017-10-21向同学¥200.00
2017-10-12向同学¥5.00
2017-10-05向同学¥5.00
2017-09-30向同学¥200.00
2017-09-14适同学¥101.00
2017-09-14九梦¥10.00
2017-09-06朱同学¥98.98
2017-08-17向同学¥5.00
2017-07-21老韩¥100.00
2017-05-26Refactoring¥100.00
2017-04-03胜同学¥100.00
2017-03-26向同学¥18.00
2017-03-21陈同学¥100.00
2017-03-16godlike¥200.00
2017-03-16向同学¥100.00
2017-02-21智同学¥100.00
2017-02-14曾同学¥100.00
2017-02-14自富¥200.00
2017-02-14刘同学¥100.00
2017-01-11亚同学¥3.00
2016-12-29涛同学¥15.00
2016-12-25明同学¥18.80
2016-10-18倩同学¥200.00
2016-10-16nivk¥400.00
2016-10-14东威¥9.99
2016-09-21悟道人¥50.00
2016-08-01冒险王¥100.00
2016-07-25诸葛同学¥50.00
2016-07-10峰同学¥100.00
2016-06-30null¥20.00
2016-06-24细同学¥20.00
2016-06-21ZNing¥6.88
2016-06-16天涯同学¥20.00
2016-06-11军同学¥200.00
2016-05-30老K¥5.00
2016-05-16百同学¥100.00
2016-05-04军同学¥100.00
2016-04-16秦同学¥50.00
2016-04-10greatpie¥6.66
2016-04-05kuuyee¥500.00
2016-03-23崔同学¥100.00
2016-03-19李同学¥100.00
2016-03-07binzu6.66
2016-02-05huihoo¥50.00
2016-02-02鹏同学¥100.00
2016-01-31huihoo¥100.00
2015-12-14维同学¥20.00
2015-11-28无同学¥100.00
2015-09-17雪同学¥100.00
2015-09-13匿名¥100.00
2015-09-11霍同学¥100.00
2015-08-20马同学¥100.00
2015-07-19谭同学¥100.00
2015-07-16军同学¥100.00
2014-05-05吴同学¥50.00
2014-05-02李同学¥8.88
2014-05-02熊同学¥9.99
2014-05-01艾同学¥0.50
2014-05-01何同学¥50.00
2014-05-01codepapa¥199.00多出教程
354 | 355 |
356 | 357 | -------------------------------------------------------------------------------- /example/gogs_zh/543.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

4. 功能介绍

12 |
13 |

功能介绍


14 | 15 |
16 | 17 | -------------------------------------------------------------------------------- /example/gogs_zh/544.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

4.4 授权认证

12 |
13 |

授权认证

LDAP

基于 BindDN 和 simple auth 的 LDAP 授权方式共享以下字段:

14 |
    15 |
  • 认证名称 (必填)

    16 |
      17 |
    • A name to assign to the new method of authorization.
    18 |
  • 主机地址 (必填)

    19 |
      20 |
    • The address where the LDAP server can be reached.
    • Example: mydomain.com
    21 |
  • 主机端口 (必填)

    22 |
      23 |
    • The port to use when connecting to the server.
    • Example: 636
    24 |
  • 启用 TLS 加密(可选)

    25 |
      26 |
    • Whether to use TLS when connecting to the LDAP server.
    27 |
  • 管理员过滤规则(可选)

    28 |
      29 |
    • An LDAP filter specifying if a user should be given administrator
      privileges. If a user accounts passes the filter, the user will be
      privileged as an administrator.
    • Example: (objectClass=adminAccount)
    30 |
31 |
    32 |
  • 用户名属性(可选)
      33 |
    • The attribute of the user’s LDAP record containing the user name. Given
      attribute value will be used for new Gogs account user name after first
      successful sign-in. Leave empty to use login name given on sign-in form.
    • This is useful when supplied login name is matched against multiple
      attributes, but only single specific attribute should be used for Gogs
      account name, see “User Filter”.
    • 例如:uid
    34 |
35 |
    36 |
  • 名字属性(可选)

    37 |
      38 |
    • The attribute of the user’s LDAP record containing the user’s first name.
      This will be used to populate their account information.
    • Example: givenName
    39 |
  • 姓氏属性(可选)

    40 |
      41 |
    • The attribute of the user’s LDAP record containing the user’s surname This
      will be used to populate their account information.
    • Example: sn
    42 |
  • 邮箱属性 (必填)

    43 |
      44 |
    • The attribute of the user’s LDAP record containing the user’s email
      address. This will be used to populate their account information.
    • Example: mail
    45 |
46 |

基于 BindDN 需要填充以下字段:

47 |
    48 |
  • 绑定 DN(可选)

    49 |
      50 |
    • The DN to bind to the LDAP server with when searching for the user. This
      may be left blank to perform an anonymous search.
    • Example: cn=Search,dc=mydomain,dc=com
    51 |
  • 绑定密码(可选)

    52 |
      53 |
    • The password for the Bind DN specified above, if any. Note: The password
      is stored in plaintext at the server. As such, ensure that your Bind DN
      has as few privileges as possible.
    54 |
  • 用户搜索基准 (必填)

    55 |
      56 |
    • The LDAP base at which user accounts will be searched for.
    • Example: ou=Users,dc=mydomain,dc=com
    57 |
  • 用户过滤规则 (必填)

    58 |
      59 |
    • An LDAP filter declaring how to find the user record that is attempting to
      authenticate. The %s matching parameter will be substituted with login
      name given on sign-in form.
    • Example: (&(objectClass=posixAccount)(uid=%s))
    • To substitute more than once %[1]s should be used instead, eg. when
      matching supplied login name against multiple attributes such as user
      identifier, email or even phone number.
    • Example: (&(objectClass=Person)(|(uid=%[1]s)(mail=%[1]s)(mobile=%[1]s)))
    60 |
61 |

基于 simple auth 需要填充以下字段:

62 |
    63 |
  • User DN (必填)

    64 |
      65 |
    • A template to use as the user’s DN. The %s matching parameter will be substituted with login name given on sign-in form.
    • Example: cn=%s,ou=Users,dc=mydomain,dc=com
    • Example: uid=%s,ou=Users,dc=mydomain,dc=com
    66 |
  • 用户过滤规则 (必填)

    67 |
      68 |
    • An LDAP filter declaring when a user should be allowed to log in. The %s
      matching parameter will be substituted with login name given on sign-in
      form.
    • Example: (&(objectClass=posixAccount)(cn=%s))
    • Example: (&(objectClass=posixAccount)(uid=%s))
    69 |
70 |

验证组成员 需要填充以下字段:

71 |
    72 |
  • 组搜索基准 DN(可选)

    73 |
      74 |
    • The LDAP DN used for groups.
    • Example: ou=group,dc=mydomain,dc=com
    75 |
  • 组名称过滤(可选)

    76 |
      77 |
    • An LDAP filter declaring how to find valid groups in the above DN.
    • Example: (|(cn=gogs_users)(cn=admins))
    78 |
  • 包含用户的组属性(可选)

    79 |
      80 |
    • Which group LDAP attribute contains an array above user attribute names.
    • Example: memberUID
    81 |
  • 组内用户属性(可选)

    82 |
      83 |
    • Which user LDAP attribute is listed in the group.
    • Example: uid
    84 |
85 |

PAM

To configure this you just need to set the ‘PAM Service Name’ to a filename in /etc/pam.d/.
If you want it to work with normal Linux passwords, the user running Gogs must have read access to /etc/shadow.

86 |

SMTP

Gogs 支持通过指定邮箱服务器来对用户进行创建和认证,可以通过配置以下选项启用该功能:

87 |
    88 |
  • 认证名称 (必填)

    89 |
      90 |
    • A name to assign to the new method of authorization.
    91 |
  • SMTP 认证类型 (必填)

    92 |
      93 |
    • Type of authentication for use on your SMTP host, PLAIN or LOGIN.
    94 |
  • 主机地址 (必填)

    95 |
      96 |
    • The address where the SMTP host can be reached.
    • Example: smtp.mydomain.com
    97 |
  • 端口号 (必填)

    98 |
      99 |
    • The port to use when connecting to the server.
    • Example: 587
    100 |
  • 域名白名单

    101 |
      102 |
    • Restrict what domains can log in if you’re using public SMTP host or SMTP host with multiple domains.
    • Example: gogs.io,mydomain.com,mydomain2.com
    103 |
  • 启用 TLS 加密

    104 |
      105 |
    • Enable TLS encryption on authentication.
    106 |
  • 忽略 TLS 验证

    107 |
      108 |
    • Disable TLS verify on authentication.
    109 |
  • This authentication is activate

    110 |
      111 |
    • Enable or disable this auth.
    112 |
113 |

Freeipa

    114 |
  • In order to login to the Gogs using FreeIPA credentials, you need to create a bind account for Gogs to use:

    115 |
  • On the FreeIPA server, create a gogs.ldif file, replacing dc=example,dc=com with your DN, and providing an appropriately secure password:

    116 |
    1. dn: uid=gogs,cn=sysaccounts,cn=etc,dc=example,dc=com
    2. changetype: add
    3. objectclass: account
    4. objectclass: simplesecurityobject
    5. uid: gogs
    6. userPassword: secure password
    7. passwordExpirationTime: 20380119031407Z
    8. nsIdleTimeout: 0
  • Import the LDIF (change localhost to an IPA server if needed), you’ll be prompted for your Directory Manager password:

    117 |
    1. ldapmodify -h localhost -p 389 -x -D \
    2. "cn=Directory Manager" -W -f gogs.ldif
  • Add an IPA group for gogs_users :
    1. ipa group-add --desc="Gogs Users" gogs_users
  • Note! if you get error about ipa credentials please run kinit admin and give your admin accound password.

    118 |
  • Now login to the gogs as an Admin, click on “Authentication” under Admin Panel. Then click New LDAP Source and fill in the details, changing all where appropriate to your own domain as photo below:

    119 |
120 |

Freeipa-Gogs

121 | 122 |
123 | 124 | -------------------------------------------------------------------------------- /example/gogs_zh/545.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

4.1 自定义模板

12 |
13 |

自定义模板

您可以不需要修改仓库源码就能注入自定义头部和尾部内容,这对添加分析代码和自定义静态资源非常有用。

14 |

了解更多有关 注入自定义头部和尾部

15 |

添加自定义 CSS 文件

这里展示如何为您的 Gogs 实例添加自定义 CSS 文件,目录和文件名都是为了方便演示,您可以把文件放在任何能够通过网络访问的目录。

16 |
    17 |
  1. public/css 目录下创建一个名为 custom.css 的文件
  2. 向文件中添加一些 CSS 规则
  3. 编辑 custom/templates/inject/head.tmpl 文件并添加一行内容 <link rel="stylesheet" href="/css/custom.css">
  4. 重启 Gogs
  5. 后续对自定义 CSS 文件的编辑不需要重启 Gogs
18 | 19 |
20 | 21 | -------------------------------------------------------------------------------- /example/gogs_zh/546.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

4.3 多国语言支持

12 |
13 |

本地化 Gogs 应用

Gogs 项目从 v0.5.0 版本开始支持应用的本地化,而您只需要鼠标单击就可实现即时语言切换。

14 |

custom/conf/app/ini 文件中启用它们(默认启用全部):

15 |
  1. [i18n]
  2. LANGS = en-US,zh-CN,zh-HK,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT
  3. NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano
16 |

贡献翻译

Crowdin 注册一个用户然后填补未翻译的字段。

17 |

有时候您会发现您无法将一个句子准确地从英文翻译到您的语言,没关系,这很正常!只需要使用您的语言将中心思想表达出来就可以,而不需要斤斤计较。

18 |

如果您想要测试翻译好的本地化文件,但又不想涉及到 Git 历史的变动,您可以将本地化文件放至 custom/conf/locale/<file> 然后重启 Gogs。

19 |

自定义本地化文件

如果您对官方的本地化翻译不够满意,可以修改其中的部分字段并保存到 custom/conf/locale/locale_<lang>.ini 中,然后重启 Gogs。

20 | 21 |
22 | 23 | -------------------------------------------------------------------------------- /example/gogs_zh/547.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

4.2 Web 钩子

12 |
13 |

Web 钩子

Gogs 支持针对仓库事件的 Web 钩子服务,您可以在仓库的设置相关页面中找到(/:username/:reponame/settings/hooks)。所有的事件推送均为 POST 请求,目前支持 Gogs 和 Slack 两种格式的内容。

14 |

事件信息

以下为 Gogs 向 Payload URL 发送的事件信息示例:

15 |
  1. X-Gogs-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473
  2. X-Gogs-Event: push
  3. X-Gogs-Signature: 1921679ed6274399b6514721056337f6913b6ff1cb35a24d340e983745d637f1
  1. {
  2. "ref": "refs/heads/develop",
  3. "before": "28e1879d029cb852e4844d9c718537df08844e03",
  4. "after": "bffeb74224043ba2feb48d137756c8a9331c449a",
  5. "compare_url": "http://localhost:3000/unknwon/webhooks/compare/28e1879d029cb852e4844d9c718537df08844e03...bffeb74224043ba2feb48d137756c8a9331c449a",
  6. "commits": [
  7. {
  8. "id": "bffeb74224043ba2feb48d137756c8a9331c449a",
  9. "message": "!@#0^%\u003e\u003e\u003e\u003e\u003c\u003c\u003c\u003c\u003e\u003e\u003e\u003e\n",
  10. "url": "http://localhost:3000/unknwon/webhooks/commit/bffeb74224043ba2feb48d137756c8a9331c449a",
  11. "author": {
  12. "name": "Unknwon",
  13. "email": "u@gogs.io",
  14. "username": "unknwon"
  15. },
  16. "committer": {
  17. "name": "Unknwon",
  18. "email": "u@gogs.io",
  19. "username": "unknwon"
  20. },
  21. "timestamp": "2017-03-13T13:52:11-04:00"
  22. }
  23. ],
  24. "repository": {
  25. "id": 140,
  26. "owner": {
  27. "id": 1,
  28. "login": "unknwon",
  29. "full_name": "Unknwon",
  30. "email": "u@gogs.io",
  31. "avatar_url": "https://secure.gravatar.com/avatar/d8b2871cdac01b57bbda23716cc03b96",
  32. "username": "unknwon"
  33. },
  34. "name": "webhooks",
  35. "full_name": "unknwon/webhooks",
  36. "description": "",
  37. "private": false,
  38. "fork": false,
  39. "html_url": "http://localhost:3000/unknwon/webhooks",
  40. "ssh_url": "ssh://unknwon@localhost:2222/unknwon/webhooks.git",
  41. "clone_url": "http://localhost:3000/unknwon/webhooks.git",
  42. "website": "",
  43. "stars_count": 0,
  44. "forks_count": 1,
  45. "watchers_count": 1,
  46. "open_issues_count": 7,
  47. "default_branch": "master",
  48. "created_at": "2017-02-26T04:29:06-05:00",
  49. "updated_at": "2017-03-13T13:51:58-04:00"
  50. },
  51. "pusher": {
  52. "id": 1,
  53. "login": "unknwon",
  54. "full_name": "Unknwon",
  55. "email": "u@gogs.io",
  56. "avatar_url": "https://secure.gravatar.com/avatar/d8b2871cdac01b57bbda23716cc03b96",
  57. "username": "unknwon"
  58. },
  59. "sender": {
  60. "id": 1,
  61. "login": "unknwon",
  62. "full_name": "Unknwon",
  63. "email": "u@gogs.io",
  64. "avatar_url": "https://secure.gravatar.com/avatar/d8b2871cdac01b57bbda23716cc03b96",
  65. "username": "unknwon"
  66. }
  67. }
16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /example/gogs_zh/548.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

2. 下载安装

12 |
13 |

下载安装

环境要求

    14 |
  • 数据库(选择以下一项):
      15 |
    • MySQL:版本 >= 5.5.3
    • PostgreSQL
    • MSSQL
    • TiDB(实验性支持,使用 MySQL 协议连接)
    • 或者 什么都不安装 直接使用 SQLite3
    16 |
  • git(bash):
      17 |
    • 服务端和客户端均需版本 >= 1.7.1
    • Windows 系统建议使用最新版
    18 |
  • SSH 服务器:
      19 |
    • 如果您只使用 HTTP/HTTPS 的话请忽略此项
    • 如果您选择在 Windows 系统使用内置 SSH 服务器,请确保添加 ssh-keygen 到您的 %PATH% 环境变量中
    • 推荐 Windows 系统使用 Cygwin OpenSSHCopssh
    20 |
21 |

安装数据库

请根据您的选择进行安装:

22 | 24 |

注意事项 您可以使用 etc/mysql.sql 来自动创建名为 gogs 的数据库。如果您选择手动创建,请务必将编码设置为 utf8mb4

25 |

安装其它要求

Mac OS X

假设您已经安装 Homebrew

26 |
  1. $ brew update
  2. $ brew install git
27 |

Debian/Ubuntu

  1. $ sudo apt-get update
  2. $ sudo apt-get install git
28 |

Windows

下载并安装 Git

29 |

安装 Gogs

31 | 32 |
33 | 34 | -------------------------------------------------------------------------------- /example/gogs_zh/549.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

2.1 注册 Windows 服务

12 |
13 |

注册为 Windows 服务运行

前提要求

想要使 Gogs 通过 Windows 服务的方式运行,必须满足以下两个条件:

14 |
    15 |
  1. 使用 miniwinsvc 构建标签获得内置 Windows 服务支持。
  2. 不使用 miniwinsvc 构建标签并通过 NSSM 注册为服务。
16 |

在注册成为服务之前,需要确保给予 Gogs 二进制相应目录的读写权限,包括存放仓库的根目录([repository] ROOT)。

17 |

修改 C:\Gogs\custom\conf\app.ini 文件的相应信息:

18 |
  1. RUN_USER = COMPUTERNAME$

通过上面的配置将 Gogs 的运行用户设置为本地系统用户。COMPUTERNAME 的值可以通过命令 echo %COMPUTERNAME% 获得,如果该命令的返回值为 USER-PC 则使用 RUN_USER = USER-PC$

19 |
  1. [server]
  2. DOMAIN = gogs
  3. PROTOCOL = http
  4. HTTP_ADDR = 127.0.1.1
  5. HTTP_PORT = 80
  6. OFFLINE_MODE = true
  7. ROOT_URL = http://gogs/

Moves Gogs’ listen port to 80 on the local interface subnet, and tells the Gogs HTTPd that its virtual host is the “gogs” domain.
This lets you forgo including a port number when browsing, and prevents collision with other localhost services.
The IP address can be anything in the range 127.0.0.2 - 127.254.254.254, so long as it’s unique to Gogs.

20 |

To complete that network route, open Notepad.exe as administrator and include the following in C:\Windows\System32\drivers\etc\hosts:

21 |
  1. # Gogs local HTTPd
  2. 127.0.1.1 gogs

The hosts file entry will guarantee that all requests to the “gogs” domain are captured by your localhost interface.
In a web browser, generally, gogs/ in the address bar is sufficient to trigger that route.

22 |

Use Builtin Functionality

Open a command prompt (cmd.exe) as an Administrator. Run the following command:

23 |
  1. C:\> sc create gogs start= auto binPath= "\"C:\gogs\gogs.exe\" web --config \"C:\gogs\custom\conf\app.ini\""

Ensure there is a space after each =. You can choose to add additional Arguments to further modify your service, or modify it manually in the service management console.

24 |

To start the service run following command:

25 |
  1. C:\> net start gogs

You should see following output:

26 |
  1. The gogs service is starting.
  2. The gogs service was started successfully.

Use NSSM

Get the nssm.exe needed for your machine (32 or 64 bit; they’re packaged together in Iain’s zip file), and place it in a directory that is in (or will be added to) your %PATH% environment variable.

27 |

Open a command line as administrator and do following command to configure Gogs as a service:

28 |
  1. C:\>nssm install gogs

“NSSM service installer” will appear. Configure it as follows:

29 |

Application tab:

30 |
    31 |
  • Path: C:\gogs\gogs.exe
  • Startup directory: C:\gogs
  • Arguments: web
32 |

install_gogs_on_windows_nssm_1.png

33 |

Details tab:

34 |
    35 |
  • Display name: Gogs
  • Description: A painless self-hosted Git service.
  • Startup type: Automatic (Delayed Start)
36 |

Note that we’ve chosen delayed start, so that the service will not impact the early boot time. Gogs will start two minutes after the non-delayed services.

37 |

install_gogs_on_windows_nssm_2.png

38 |

I/O tab:

39 |
    40 |
  • Output (stdout): C:\gogs\log\gogs-nssm.txt
  • Error (stderr): C:\gogs\log\gogs-nssm.txt
41 |

That will capture all text output that you would normally receive from Gogs on the command line console, and log it to that file instead.

42 |

install_gogs_on_windows_nssm_3.png

43 |

File rotation tab:

44 |
    45 |
  • Check: Rotate files
  • Restrict rotation to files bigger than: 1000000 bytes
46 |

install_gogs_on_windows_nssm_4.png

47 |

Environment tab:

48 |
    49 |
  • Environment variables: PATH=%PATH%;C:\gogs;C:\Program Files (x86)\Git\bin
50 |

That is a guarantee that both gogs.exe and git.exe will be on the Gogs service’s path variable during runtime.

51 |

install_gogs_on_windows_nssm_5.png

52 |

Click “Install service”, and you should be confirmed that it succeeded.

53 |

If it failed, refer back to the command line console you started, for the error message. When it succeeds, go to command line and do:

54 |
  1. nssm start gogs

You should see:

55 |
  1. gogs: START: The operation completed successfully.

Check that this is true by opening C:\gogs\log\gogs-nssm.txt. You should see Gogs’ start up procedures, ending with:

56 |
  1. timestamp [I] Run Mode: Production
  2. timestamp [I] Listen: http://127.0.1.1:80

Now point your web browser at http://gogs/ and log in.

57 |

Gogs is running as a service, and will not need to be run manually, unless something goes wrong. NSSM will attempt to restart the service for you, if the Gogs server crashes.

58 |

When you need to restart it after app.ini changes, go to an administrator command line after the changes, and do:

59 |
  1. nssm restart gogs

See the configuration cheat sheet for reference of the custom\conf\app.ini settings.

60 |

An example of the logging and error handling in action:

61 |
  1. [log]
  2. ROOT_PATH = C:\gogs\log

At the time of writing this line, it will cause the following to print in C:\gogs\log\gogs-nssm.txt:

62 |
  1. timestamp [T] Custom path: C:/gogs/custom
  2. timestamp [T] Log path: C:\gogs\log
  3. timestamp [I] Gogs x.y.z
  4. timestamp [log.go:294 Error()] [E] Fail to set logger(file): invalid character 'g' in string escape code

This is what was expected in C:\custom\conf\app.ini:

63 |
  1. ROOT_PATH = C:/gogs/log

And this was the nssm interaction while solving it:

64 |
  1. C:\>nssm restart gogs
  2. gogs: STOP: The operation completed successfully.
  3. gogs: Unexpected status SERVICE_PAUSED in response to START control.
  4. C:\>nssm start gogs
  5. gogs: START: An instance of the service is already running.
  6. C:\>nssm stop gogs
  7. gogs: STOP: The operation completed successfully.
  8. C:\>nssm start gogs
  9. gogs: Unexpected status SERVICE_PAUSED in response to START control.
  10. C:\>nssm restart gogs
  11. gogs: STOP: The operation completed successfully.
  12. gogs: START: The operation completed successfully.
65 |
66 | 67 | -------------------------------------------------------------------------------- /example/gogs_zh/550.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

2.2 配置与运行

12 |
13 |

配置与运行

配置文件

默认配置文件

默认配置都保存在 conf/app.ini,您 永远不需要 编辑它。该文件从 v0.6.0 版本开始被嵌入到二进制中。

14 |

自定义配置文件

那么,在不允许修改默认配置文件 conf/app.ini 的情况下,怎么才能自定义配置呢?很简单,只要创建 custom/conf/app.ini 就可以!在 custom/conf/app.ini 文件中修改相应选项的值即可。

15 |

例如,需要改变仓库根目录的路径:

16 |
  1. [repository]
  2. ROOT = /home/jiahuachen/gogs-repositories

当然,您也可以修改数据库配置:

17 |
  1. [database]
  2. PASSWD = root

为什么要这么做?

乍一看,这么做有些复杂,但是这么做可以有效地保护您的自定义配置不被破坏:

18 |
    19 |
  • 从二进制安装的用户,可以直接替换二进制及其它文件而不至于重新编写自定义配置。
  • 从源码安装的用户,可以避免由于版本管理系统导致的文件修改冲突。
20 |

运行 Gogs 服务

开发者模式

    21 |
  • 您需要在 custom/conf/app.ini 文件中将选项 security -> INSTALL_LOCK 的值设置为 true
  • 您可以使用超能的 make 命令:

    22 |
    1. $ make
    2. $ ./gogs web
    23 |
24 |

部署模式

脚本均放置在 scripts 目录,但请在仓库根目录执行它们

25 |
    26 |
  • Gogs 支持多种方式的启动:
      27 |
    • 普通:只需执行 ./gogs web
    • 守护进程:详见 scripts 文件夹
    28 |
  • 然后访问 /install 来完成首次运行的配置工作
29 | 30 |
31 | 32 | -------------------------------------------------------------------------------- /example/gogs_zh/551.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

2.3 二进制安装

12 |
13 |

二进制安装

目前只提供最近发布的小版本二进制下载,更多版本下载请前往 GitHub 查看。

14 |

所有的版本都支持 MySQLPostgreSQLMSSQLTiDB(使用 MySQL 协议)作为数据库,并且均使用构建标签(build tags)cert 进行构建。需要注意的是,不同的版本的支持状态有所不同,请根据实际的 Gogs 提示进行操作。

15 |

备注

    16 |
  • mws 表示提供内置 Windows 服务支持,如果您使用 NSSM 请使用另外一个版本。
17 |

如何使用下载好的压缩包?

    18 |
  1. 解压压缩包。
  2. 使用命令 cd 进入到刚刚创建的目录。
  3. 执行命令 ./gogs web,然后,就没有然后了。
19 |

如何通过二进制升级?

    20 |
  1. 下载最新版的压缩包。
  2. 删除当前的 templates 目录。
  3. 解压压缩包并将所有内容复制粘贴到相应(当前)的位置。
21 |

0.11.34 @ 2017-11-22

22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
系统名称系统类型SQLitePAM下载(GitHub
Linux386HTTPS: ZIP \TAR.GZ - CDN: ZIP \TAR.GZ
Linuxamd64HTTPS: ZIP \TAR.GZ - CDN: ZIP \TAR.GZ
Linuxarmv5HTTPS: ZIP - CDN: ZIP
Raspberry Piv2&v3 / armv6HTTPS: ZIP - CDN: ZIP
Windows386HTTPS: ZIP \ZIP w/ mws - CDN: ZIP \ZIP w/mws
Windowsamd64HTTPS: ZIP \ZIP w/ mws - CDN: ZIP \ZIP w/ mws
Mac OSamd64HTTPS: ZIP - CDN: ZIP
91 |

0.11.29 @ 2017-08-15

92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 |
系统名称系统类型SQLitePAM下载(GitHub
Linux386HTTPS: ZIP \TAR.GZ - CDN: ZIP \TAR.GZ
Linuxamd64HTTPS: ZIP \TAR.GZ - CDN: ZIP \TAR.GZ
Linuxarmv5HTTPS: ZIP - CDN: ZIP
Raspberry Piv2 / armv6HTTPS: ZIP - CDN: ZIP
Windows386HTTPS: ZIP \ZIP w/ mws - CDN: ZIP \ZIP w/mws
Windowsamd64HTTPS: ZIP \ZIP w/ mws - CDN: ZIP \ZIP w/ mws
Mac OSamd64HTTPS: ZIP - CDN: ZIP
161 |

0.10.18 @ 2017-03-14

162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 |
系统名称系统类型SQLitePAM下载(GitHub
Linux386HTTPS: ZIP \TAR.GZ - CDN: ZIP \TAR.GZ
Linuxamd64HTTPS: ZIP \TAR.GZ - CDN: ZIP \TAR.GZ
Linuxarmv5HTTPS: ZIP - CDN: ZIP
Raspberry Piv2 / armv6HTTPS: ZIP - CDN: ZIP
Windows386HTTPS: ZIP \ZIP w/ mws - CDN: ZIP \ZIP w/mws
Windowsamd64HTTPS: ZIP \ZIP w/ mws - CDN: ZIP \ZIP w/ mws
Mac OSamd64HTTPS: ZIP - CDN: ZIP
231 |

v0.9.141 @ 2017-02-11

232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 |
系统名称系统类型SQLitePAM下载(GitHub
Linux386HTTPS: ZIP \TAR.GZ - CDN: ZIP \TAR.GZ
Linuxamd64HTTPS: ZIP \TAR.GZ - CDN: ZIP \TAR.GZ
Linuxarmv5HTTPS: ZIP - CDN: ZIP
Linuxarmv6HTTPS: ZIP - CDN: ZIP
Raspberry Piv2HTTPS: ZIP - CDN: ZIP
Windows386HTTPS: ZIP \ZIP w/ mws - CDN: ZIP \ZIP w/mws
Windowsamd64HTTPS: ZIP \ZIP w/ mws - CDN: ZIP \ZIP w/ mws
Mac OSamd64HTTPS: ZIP - CDN: ZIP
308 |

安装完成后可继续参照 [配置与运行]。

309 | 310 |
311 | 312 | -------------------------------------------------------------------------------- /example/gogs_zh/552.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

2.4 包管理安装

12 |
13 |

包管理安装

以下均为第三方提供,后果自负!

14 |

Packager.io

    15 |
  • 当前支持 Ubuntu 12.04 + 14.04、CentOS 6 + 7 和 Debian 7 + 8 版本。
  • 可以从 packager.io 获取到相应包管理资源(该工具的自定义配置文件有时会放置在 /etc/default/gogs)。
16 |

Arch Linux

20 |

能可以到 Arch Linux Wiki entry 查看完整说明。

21 | 22 |
23 | 24 | -------------------------------------------------------------------------------- /example/gogs_zh/553.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

2.5 源码安装

12 |
13 |

源码安装

安装依赖

基本依赖

15 |

第三方包

请通过 gopmfile 查看完整的第三方包依赖列表。一般情况下只有在您为 Gogs 制作构建包的时候才会用到。

16 |

安装 Go 语言

如果您的系统已经安装要求版本的 Go 语言,可以跳过此小节。

17 |

下载

您可以通过以下方式安装 Go 语言到 /home/git/local/go 目录:

18 |
  1. sudo su - git
  2. cd ~
  3. # create a folder to install 'go'
  4. mkdir local
  5. # Download go (change go$VERSION.$OS-$ARCH.tar.gz to the latest release)
  6. wget https://storage.googleapis.com/golang/go$VERSION.$OS-$ARCH.tar.gz
  7. # expand it to ~/local
  8. tar -C /home/git/local -xzf go$VERSION.$OS-$ARCH.tar.gz
19 |

设置环境

请设置和您系统环境对应的路径:

20 |
  1. sudo su - git
  2. cd ~
  3. echo 'export GOROOT=$HOME/local/go' >> $HOME/.bashrc
  4. echo 'export GOPATH=$HOME/go' >> $HOME/.bashrc
  5. echo 'export PATH=$PATH:$GOROOT/bin:$GOPATH/bin' >> $HOME/.bashrc
  6. source $HOME/.bashrc
21 |

安装 Gogs

常用的安装方式:

22 |
  1. # 下载并安装依赖
  2. $ go get -u github.com/gogits/gogs
  3. # 构建主程序
  4. $ cd $GOPATH/src/github.com/gogits/gogs
  5. $ go build
23 |

构建 develop 分支版本

如果您想要安装 develop(或其它)分支版本,则可以通过以下命令:

24 |
  1. $ mkdir -p $GOPATH/src/github.com/gogits
  2. $ cd $GOPATH/src/github.com/gogits
  3. # 请确保没有使用 “https://github.com/gogits/gogs.git”
  4. $ git clone --depth=1 -b develop https://github.com/gogits/gogs
  5. $ cd gogs
  6. $ go build
25 |

测试安装

您可以通过以下方式检查 Gogs 是否可以正常工作:

26 |
  1. cd $GOPATH/src/github.com/gogits/gogs
  2. ./gogs web
27 |

如果您没有发现任何错误信息,则可以使用 Ctrl-C 来终止运行。

28 |

使用标签构建

Gogs 默认并没有支持一些功能,这些功能需要在构建时明确使用构建标签(build tags)来支持。

29 |

目前使用标签构建的功能如下:

30 |
    31 |
  • sqlite3:SQLite3 数据库支持
  • pam:PAM 授权认证支持
  • cert:生成自定义证书支持
  • miniwinsvc:Windows 服务内置支持(或者您可以使用 NSSM 来创建服务)
32 |

例如,您需要支持以上所有功能,则需要先删除 $GOPATH/pkg/{GOOS_GOARCH}/github.com/gogits/gogs 目录,然后执行以下命令:

33 |
  1. $ go get -u -tags "sqlite pam cert" github.com/gogits/gogs
  2. $ cd $GOPATH/src/github.com/gogits/gogs
  3. $ go build -tags "sqlite pam cert"
34 |

安装完成后可继续参照 [配置与运行]。

35 | 36 |
37 | 38 | -------------------------------------------------------------------------------- /example/gogs_zh/554.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

1. 简介

12 |
13 |

什么是 Gogs?

Gogs 是一款极易搭建的自助 Git 服务。

14 |

开发目的

Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发,并且支持 Go 语言支持的 所有平台,包括 Linux、Mac OS X、Windows 以及 ARM 平台。

15 |

开源组件

23 | 24 |
25 | 26 | -------------------------------------------------------------------------------- /example/gogs_zh/555.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

1.1 变更日志

12 |
13 |

变更日志

0.11.34 @ 2017-11-22

Bug 修复

    14 |
  • 回退:跨仓库合并请求无法正常工作 #4890
15 |

0.11.33 @ 2017-11-19

Bug 修复

    16 |
  • 部分安全修复
  • 合并请求后发送的 Web 钩子推送内容包含错误的提交 ID #4442
  • HTML 标签 go-import 未响应正确的值 #4832
17 |

新增特性

    18 |
  • 添加钉钉 Web 钩子支持 #4773
  • 支持合并请求前先进行衍合操作 #4798
19 |

功能改进

    20 |
  • 在 LDAP BindDN 中支持使用 ‘%s’ 作为用户名占位符 #2526
  • 允许通过环境变量指定 Docker 容器内 git 用户的 UID #3520
  • 添加仓库设置以便在检查合并请求冲突时忽略空白符的差异 #4834
21 |

其它变更

    22 |
  • 添加新语种支持:斯洛伐克语
23 |

0.11.29 @ 2017-08-15

Bug 修复

    24 |
  • 如果仓库曾经为公开的,则变为私有后相关活动信息未被设为私有 #4414
  • Web 钩子不接受 IPv6 URL #4428
  • 通过代码提交关闭工单后没有发送邮件提醒 #4430
  • 探索页面分页不正确 #4441
  • /api/v1/repos/search 返回空值 #4522
  • 创建合并请求完成后发生错误 #4572
25 |

0.11.19 @ 2017-06-10

Bug 修复

    26 |
  • 无法使用 go get 子包 #1878
  • 非首次使用 LDAP 登录无法更新用户为管理员 #2855
  • 使用 PAM 登录时发生错误 #4216
  • PostgreSQL 恢复备份后出现错误 unique constraint violation #4357
  • IPython notebook 的图片无法显示 #4366
  • 编辑文件预览时无法正确处理图片相对链接 #4368
  • 提交历史页面无法渲染 Emoji #4439
  • 查看包含文件权限更改的单个提交时 CPU 异常高 #4475
  • 无法修改协作者的权限 #4512
27 |

新增特性

    28 |
  • 支持两步验证登录 #945
  • 支持 LDAP 登录时验证组成员身份 #4398
29 |

功能改进

    30 |
  • 安装页面检查 SMTP 地址中是否包含端口号 #2243
  • 镜像仓库没有拉取新代码提交时不更新最后更新时间 #4341
  • 支持 IPython Notebook 形式的 README #4367
  • 支持自定义 TLS 相关配置 #4450
31 |

0.11.4 @ 2017-04-05

Bug 修复

    32 |
  • 在进行 HTTP/HTTPS 推送和拉取时客户端没有提示用户输入凭据
  • 镜像用户凭据没有进行 URL 编码 #4014
  • 仓库禁用合并请求时,发起合并请求按钮仍旧在分支页面显示 #4377
  • 用户在安装页面发生验证错误时应用会崩溃 #4383
33 |

0.11 @ 2017-04-03

Bug 修复

    34 |
  • 编辑个人信息发生验证错误时丢失内容 #1123
  • 组织控制面板显示错误的仓库统计 #4351
  • 从 0.10 之前的版本自动迁移失败 #4355
  • 允许公开访问工单的私有仓库没有正确处理匿名访问 #4359
35 |

0.11 RC @ 2017-03-27

Bug 修复

    36 |
  • 不正确的会话文件权限 #3363
  • API:仓库对象的权限字段返回无效的值 #4309
  • 非本地用户无法更新个人设置 #4313
  • 工单索引不存在会显示随机工单 #4315
  • 无法从二级派生仓库发起合并请求 #4324
  • 无法更新保护分支白名单 #4333
  • 派生、迁移和镜像仓库的体积没有正确更新 #4336
37 |

新增特性

    38 |
  • 支持私有仓库工单的公开访问 #649
  • 支持私有仓库 Wiki 的公开访问 #2157
  • 支持重新推送 Web 钩子的历史记录 #2187
  • API:同步镜像仓库 #2235
  • 支持在控制面板中加载更多的活动内容 #2511
  • 支持设置指定当前用户时候登录的 Cookie 值 #2885
  • 支持备份及恢复 #2924
  • 支持空仓库的工单和 Wiki 操作 #4104
  • 提交历史页面自定义每页显示的数量 #4230
  • 用户设置页面添加管理仓库面板 #4277
39 |

功能改进

    40 |
  • 探索页面显示私有但有访问权限的仓库 #3088
  • 允许在安装页面选择使用终端模式的日志 #3119
  • 允许配置 XORM 的日志器 #3183
  • 添加有关 HTML 渲染模式的配置选项 #3608
  • Web 钩子推送事件添加有关文件被添加、删除和修改的信息 #3897
  • 允许设置控制面板每页显示的活动数量 #4247
41 |

更早的变更日志可以在 GitHub 上找到。

42 | 43 |
44 | 45 | -------------------------------------------------------------------------------- /example/gogs_zh/556.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

1.2 常见问题

12 |
13 |

常见问题

部署应用

如果我已经有其它应用使用端口 3000 了怎么办?

您可以在您第一次启动 Gogs 的时候通过以下方式修改默认的监听端口:

14 |
  1. ./gogs web -port 3001

该方法同样会在您填写安装页面时生效,因此请选择一个您希望以后一直给 Gogs 使用的端口号。

15 |

如何使用 NGINX 的反向代理?

nginx.conf 文件中,将下面的 server 部分增加至 http 分区内并重载配置:

16 |
  1. server {
  2. listen 80;
  3. server_name git.crystalnetwork.us;
  4. location / {
  5. proxy_pass http://localhost:3000;
  6. }
  7. }
配置子路径

如果您想要通过域名的子路径来访问 Gogs 实例,可以将 NGINX 的配置修改为以下形式(特别注意后缀 /):

17 |
  1. server {
  2. listen 80;
  3. server_name git.crystalnetwork.us;
  4. location /gogs/ {
  5. proxy_pass http://localhost:3000/;
  6. }
  7. }

然后在配置文件中设置 [server] ROOT_URL = http://git.crystalnetwork.us/gogs/

18 |
为什么上传大文件时总是发生错误?

想要了解如何让 NGINX 支持大文件上传的讨论,可以查看 此贴 。一般 NGINX 会返回 413 错误,在配置文件中加入以下内容可以解决该问题:

19 |
  1. client_max_body_size 50m;
如果我用的是 Apache 2 怎么配置子路径?

可以尝试使用下面的配置模板:

20 |
  1. <VirtualHost *:443>
  2. ...
  3. <Proxy *>
  4. Order allow,deny
  5. Allow from all
  6. </Proxy>
  7. ProxyPass /git http://127.0.0.1:3000/
  8. ProxyPassReverse /git http://127.0.0.1:3000/
  9. </VirtualHost>
有没有用 lighttpd 配置子路径的例子?

可以尝试使用下面的配置模板:

21 |
  1. server.modules += ( "mod_proxy_backend_http" )
  2. $HTTP["url"] =~ "^/gogs" {
  3. proxy-core.protocol = "http"
  4. proxy-core.backends = ( "localhost:3000" )
  5. proxy-core.rewrite-request = (
  6. "_uri" => ( "^/gogs/?(.*)" => "/$1" ),
  7. "Host" => ( ".*" => "localhost:3000" ),
  8. )
  9. }

如何使用 HTTPS?

custom/conf/app.ini 文件中修改下列配置选项(以下仅为示例):

22 |
  1. [server]
  2. PROTOCOL = https
  3. ROOT_URL = https://try.gogs.io/
  4. CERT_FILE = custom/https/cert.pem
  5. KEY_FILE = custom/https/key.pem

如果您想要使用自签名的 HTTPS,则可以使用下列命令来生成所需文件(需要使用构建标签 cert 或直接从官方下载二进制):

23 |
  1. $ ./gogs cert -ca=true -duration=8760h0m0s -host=myhost.example.com

如何使用离线模式?

如果您需要将 Gogs 运行于内网环境下,只需将 custom/conf/app.ini 文件中的配置选项 server -> OFFLINE_MODE 修改为 true 即可。

24 |

如何使用自定义 robots.txt?

custom 目录下创建 robots.txt 文件即可。

25 |

如何以守护进程形式运行?

Gogs 拥有一些由第三方提供的脚本来支持以守护进程形式运行:

26 | 28 |

Systemd 服务

在 GitHub 上的 Gogs 仓库有一个 systemd 服务模版文件,您需要做出一定的修改才能够使用它:

29 |
    30 |
  1. 更新 UserGroupWorkingDirectoryExecStartEnvironment 为相对应的值。其中 WorkingDirectory 为您的 Gogs 实际安装路径根目录。
  2. [可选] 如果您 Gogs 安装示例使用 MySQL/MariaDBPostgreSQLRedismemcached,请去掉相应 After 属性的注释。
31 |

当您完成修改后,请将文件保存至 /etc/systemd/system/gogs.service,然后通过 sudo systemctl enable gogs 命令激活,最后执行 sudo systemctl start gogs

32 |

您可以通过 sudo systemctl status gogs -lsudo journalctl -b -u gogs 命令检查 Gogs 的运行状态。

33 |

管理权限

如何成为管理员?

    34 |
  1. 当用户注册时 ID = 1 则会自动成为管理员,无需邮箱验证。
  2. 默认管理员登录 Admin -> Users 面板并设置其它人员为管理员。
  3. 通过安装页面注册的用户会自动成为管理员。
35 |

仓库管理

如何给予用户 Git 钩子权限?

由于这是一个 可能损坏您系统的高级权限,您必须在用户管理面板(/admin/users/:userid)为您完全信任的用户单独开启。

36 |

其它

如何获取 Gogs 当前版本?

纯文本形式的 Gogs 版本存储在文件 templates/.VERSION 中。

37 | 38 |
39 | 40 | -------------------------------------------------------------------------------- /example/gogs_zh/557.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

1.3 故障排查

12 |
13 |

故障排查

安装

    14 |
  • 错误描述:../gosrc/src/github.com/gogits/gogs/cmd/cert.go:79: undefined: elliptic.P224
  • 可能原因:Go 语言的 RHEL/CentOS 官方发行版中因专利问题移除了相关加密算法的代码
  • 解决方案:从 golang.org/dl 下载安装 Go 语言
15 |

SSH

SSH 链接挂起 60 秒

    16 |
  • 可能原因:Gogs 会在每次 SSH Push 完成之后请求自身的 Web 服务,您的防火墙或服务器提供商未允许该操作
17 |

Update 钩子指向错误的二进制路径

    18 |
  • 可能原因:您升级 Gogs 后将其移动到了和之前安装位置不同的目录
  • 解决方案:到管理员控制面板(/admin)执行以下操作:
      19 |
    • 重新生成 '.ssh/authorized_keys' 文件
    • 重新同步所有仓库的 pre-receive、update 和 post-receive 钩子
    20 |
21 |

推送成功但控制面板没有活动更新

可能原因

在使用 SSH 推送时,Gogs 依赖通过执行钩子脚本(Hook Script)来更新仓库和最近活动。但出于某种原因,执行脚本的权限被拒绝了,尤其是在使用挂载(Mount)设备时。

22 |
解决方案
    23 |
  • 请确保挂载设备时没有启用 noexec 选项,必要时需要明确指定 exec 选项。
  • 如果使用 vfat(或者 cifs)类型的挂载,请确保 uidgidfmask 选项允许运行 Gogs 的用户在挂载设备上执行脚本。
  • 如果使用网络类型的挂载,请确保服务器(NFS 或 Samba)没有禁止远程文件系统的执行脚本权限。
24 |

Git

公钥使用冲突

    25 |
  • 错误描述:
      26 |
    • fatal: 'XX/XX.git' does not appear to be a git repository
    • 推送代码提交后依旧显示为空仓库
    27 |
  • 可能原因:~/.ssh/authorized_keys 文件中存在重复的 SSH 密钥,可能是由于您曾经或正在通过同一个系统用户使用 GitLab。
  • 解决方案:删除除了属于 Gogs 自动添加以外的所有密钥。
28 |

Gogs 无法调用 ‘git’ 命令

    29 |
  • 错误描述:repo.NewRepoContext(fail to set git user.email):
  • 可能原因:该错误会发生在 Windows 安装 Git Bash 时未启用 cmd 选项。
  • 解决方案:重装并启用 cmd 选项。
30 |

Cache

    31 |
  • 错误描述:cache: unknown adaptername "memcache" (forgotten import?)
  • 可能原因:为了减少不必要的导入,您需要使用构建 tags 来启用某个缓存适配器。
  • 解决方案:
      32 |
    • 下载:go get -tags memcache github.com/gogits/gogs
    • 构建:go build -tags memcache
    • 如果要启用 redis 也是一样的步骤。
    33 |
34 |

数据库

使用错误的 MySQL 存储引擎

    35 |
  • 错误描述:Error 1071: Specified key was too long; max key length is 1000 bytes
  • 可能原因:这是由于数据库引擎为 MyISAM 导致的。
  • 解决方案:在使用 config/mysql.sql 创建完数据库后,进入数据库然后执行:

    36 |
    1. use gogs;
    2. set global storage_engine=INNODB;
    37 |
38 |

最后,访问 http://localhost:3000/install 即可(感谢 @linc01n)。

39 |

过时的 MySQL 密码设置

    40 |
  • 错误描述:Database setting is not correct: This server only supports the insecure old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords
  • 可能原因:只更新了 @localhost 的密码,但 @% 用户依旧使用旧密码
  • 解决方案:GitHub 讨论
41 |

连接到错误的 SQLite3 数据库

    42 |
  • 错误描述:推送仓库显示仓库所有者(Owner)未注册或 user 数据表不存在。
  • 可能原因:您以服务形式启动 Gogs 的时候,Gogs 可能会使用和您预期所不同的 SQLite3 数据库文件。
  • 解决方案:使用绝对路径配置 SQLite3 数据库文件路径。
43 |

邮件服务

47 |

Windows

    48 |
  • 错误描述:
49 |
  1. 2014/09/18 15:04:40 [repo.go:115 CreatePost()] [E] CreatePost: initRepository: initRepository(git clone): cygwin warning:
  2. MS-DOS style path detected: C:\Users\user\gogs-repositories\unos\test3.git/.git
  3. Preferred POSIX equivalent is: /cygdrive/c/Users/user/gogs-repositories/unos/test3.git/.git
  4. CYGWIN environment variable option "nodosfilewarning" turns off this warning.
  5. Consult the user's guide for more details about POSIX paths:
  6. http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
  7. Cloning into 'C:\Users\user\AppData\Local\Temp\484264900'...
  8. fatal: '/cygdrive/d/svnroot/research/gogs/C:\Users\user\gogs-repositories\unos\test3.git' does not appear to be a git repository
  9. fatal: Could not read from remote repository.
    50 |
  • 可能原因:您在系统中安装了另一种命令行工具,并且与系统默认的 CMD 有不同路径风格。
  • 解决方案:请您尝试用默认的 CMD 启动 Gogs。
51 |
52 |
    53 |
  • 错误描述:Resource interpreted as Stylesheet but transferred with MIME type application/x-css
  • 可能原因:Windows 注册表中错误的值
  • 解决方案:在注册表中找到 HKEY_CLASSES_ROOT 下的 .css,并将其 Content Type 的值修改为 text/css
54 |

其它

    55 |
  • 错误描述:页面响应非常慢,但是显示在页面底部的时间正常(低于 100 毫秒)。
  • 可能原因:这可能是由于 Nginx 尝试通过 IPv6 的方式解析 IPv4 的地址。
  • 解决方案:显式的使用 127.0.0.1 作为主机名而不是 localhost
56 |
57 |
    58 |
  • 错误描述:Error 1062: Duplicate entry 'Unknown-Mac' for key 'UQE_public_key_name'
  • 可能原因:这是由于遗留代码导致的,public_key 表之前含有唯一索引 UQE_public_key_name
  • 解决方案:您只需删除它即可。
59 |
60 |
    61 |
  • 错误描述:GLIBC_2.14 not found
  • 解决方案:尝试 sudo apt-get -t testing install libc6-dev
62 |
63 |
    64 |
  • 错误描述:[Macaron] PANIC: session(start): mkdir data: permission denied
  • 可能原因:Gogs 会在程序所在目录创建 data 子目录。
  • 解决方案:确保 Gogs 具有在相同目录创建子目录的权限。
65 | 66 |
67 | 68 | -------------------------------------------------------------------------------- /example/gogs_zh/558.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

3. 版本升级

12 |
13 |

版本升级

14 |
15 | 16 | -------------------------------------------------------------------------------- /example/gogs_zh/559.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

3.1 二进制升级

12 |
13 |

从二进制升级

相关下载可以从 二进制安装 页面查看。

14 |

首先,确认当前安装的位置:

15 |
  1. # 默认位置在 git 用户下的家目录
  2. $ sudo su - git
  3. $ cd ~
  4. $ pwd
  5. /home/git
  6. $ ls
  7. gogs gogs-repositories
16 |

然后将当前目录移动到另一个临时的位置,但不是删除!

17 |
  1. $ mv gogs gogs_old
18 |

下载并解压新的二进制:

19 |
  1. # 请根据系统和类型获取相应的二进制版本
  2. $ wget wget https://dl.gogs.io/$VERSION/$OS_$ARCH.tar.gz
  3. $ tar -zxvf $OS_$ARCH.tar.gz
  4. $ ls
  5. gogs gogs_old gogs-repositories $OS_$ARCH.tar.gz
20 |

复制 customdatalog 目录到新解压的目录中:

21 |
  1. $ cp -R gogs_old/custom gogs
  2. $ cp -R gogs_old/data gogs
  3. $ cp -R gogs_old/log gogs
22 |

最后,运行并打开浏览器进行测试:

23 |
  1. $ cd gogs
  2. $ ./gogs web
24 |

给自己点一个赞!

25 | 26 |
27 | 28 | -------------------------------------------------------------------------------- /example/gogs_zh/560.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Gogs中文文档 - 书栈(BookStack.CN) 8 | 9 | 10 | 11 |

3.2 源码升级

12 |
13 |

从源码升级

升级 Gogs 的一般步骤:

14 |
  1. # 更新源码以及依赖
  2. $ go get -u github.com/gogits/gogs
  3. $ cd $GOPATH/src/github.com/gogits/gogs
  4. # 移除旧的二进制
  5. $ rm gogs
  6. # 或将旧的二进制进行备份
  7. $ mv gogs gogs.$(date +%Y-%m-%d).old
  8. # 重新构建 Gogs
  9. $ go build
15 |

其它操作:

16 | 18 | 19 |
20 | 21 | -------------------------------------------------------------------------------- /example/gogs_zh/8b35028d0518c77d8308ff3dd97e97a0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/8b35028d0518c77d8308ff3dd97e97a0.png -------------------------------------------------------------------------------- /example/gogs_zh/99327ac61c6444a0839c551d6fd06e5f.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/99327ac61c6444a0839c551d6fd06e5f.gif -------------------------------------------------------------------------------- /example/gogs_zh/a16e019f33ab5660b83b52f2ee5c8a24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/a16e019f33ab5660b83b52f2ee5c8a24.png -------------------------------------------------------------------------------- /example/gogs_zh/a97fed77a57e0e7788343c4674bb4c45.png: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 页面不存在 - BookStack 11 | 12 | 43 | 44 | 45 |
46 |
47 |
HTTP 404 : 页面不存在.
48 |
49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /example/gogs_zh/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "charset": "utf-8", 3 | "cover": "", 4 | "date": "2018-01-21", 5 | "description": "Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发,并且支持 Go 语言支持的 所有平台,包括 Linux、Mac OS X、Windows 以及 ARM 平台。", 6 | "footer": "

本文档使用 书栈(BookStack.CN) 构建 - _PAGENUM_ -

", 7 | "header": "

_SECTION_

", 8 | "identifier": "", 9 | "language": "zh-CN", 10 | "creator": "书栈(BookStack.CN)", 11 | "publisher": "书栈(BookStack.CN)", 12 | "contributor": "书栈(BookStack.CN)", 13 | "title": "Gogs中文文档", 14 | "format": ["epub", "mobi", "pdf"], 15 | "font_size": "13", 16 | "paper_size": "a4", 17 | "margin_left": "72", 18 | "margin_right": "72", 19 | "margin_top": "72", 20 | "margin_bottom": "72", 21 | "more": [], 22 | "toc": [{ 23 | "id": 709800000, 24 | "link": "statement.html", 25 | "pid": 0, 26 | "title": "致谢" 27 | }, { 28 | "id": 539, 29 | "link": "539.html", 30 | "pid": 538, 31 | "title": "5.1 配置文件手册" 32 | }, { 33 | "id": 545, 34 | "link": "545.html", 35 | "pid": 543, 36 | "title": "4.1 自定义模板" 37 | }, { 38 | "id": 549, 39 | "link": "549.html", 40 | "pid": 548, 41 | "title": "2.1 注册 Windows 服务" 42 | }, { 43 | "id": 554, 44 | "link": "554.html", 45 | "pid": 0, 46 | "title": "1. 简介" 47 | }, { 48 | "id": 555, 49 | "link": "555.html", 50 | "pid": 554, 51 | "title": "1.1 变更日志" 52 | }, { 53 | "id": 540, 54 | "link": "540.html", 55 | "pid": 538, 56 | "title": "5.2 公告与高阶指南" 57 | }, { 58 | "id": 547, 59 | "link": "547.html", 60 | "pid": 543, 61 | "title": "4.2 Web 钩子" 62 | }, { 63 | "id": 548, 64 | "link": "548.html", 65 | "pid": 0, 66 | "title": "2. 下载安装" 67 | }, { 68 | "id": 556, 69 | "link": "556.html", 70 | "pid": 554, 71 | "title": "1.2 常见问题" 72 | }, { 73 | "id": 559, 74 | "link": "559.html", 75 | "pid": 558, 76 | "title": "3.1 二进制升级" 77 | }, { 78 | "id": 546, 79 | "link": "546.html", 80 | "pid": 543, 81 | "title": "4.3 多国语言支持" 82 | }, { 83 | "id": 550, 84 | "link": "550.html", 85 | "pid": 548, 86 | "title": "2.2 配置与运行" 87 | }, { 88 | "id": 557, 89 | "link": "557.html", 90 | "pid": 554, 91 | "title": "1.3 故障排查" 92 | }, { 93 | "id": 558, 94 | "link": "558.html", 95 | "pid": 0, 96 | "title": "3. 版本升级" 97 | }, { 98 | "id": 560, 99 | "link": "560.html", 100 | "pid": 558, 101 | "title": "3.2 源码升级" 102 | }, { 103 | "id": 543, 104 | "link": "543.html", 105 | "pid": 0, 106 | "title": "4. 功能介绍" 107 | }, { 108 | "id": 544, 109 | "link": "544.html", 110 | "pid": 543, 111 | "title": "4.4 授权认证" 112 | }, { 113 | "id": 551, 114 | "link": "551.html", 115 | "pid": 548, 116 | "title": "2.3 二进制安装" 117 | }, { 118 | "id": 538, 119 | "link": "538.html", 120 | "pid": 0, 121 | "title": "5. 高级用法" 122 | }, { 123 | "id": 552, 124 | "link": "552.html", 125 | "pid": 548, 126 | "title": "2.4 包管理安装" 127 | }, { 128 | "id": 542, 129 | "link": "542.html", 130 | "pid": 0, 131 | "title": "6. 捐赠我们" 132 | }, { 133 | "id": 553, 134 | "link": "553.html", 135 | "pid": 548, 136 | "title": "2.5 源码安装" 137 | }] 138 | } -------------------------------------------------------------------------------- /example/gogs_zh/d4643fd6157facd3f4178141fb4ab85d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/d4643fd6157facd3f4178141fb4ab85d.png -------------------------------------------------------------------------------- /example/gogs_zh/d92fc8f1c8954dda582909a8d37bc6c6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/d92fc8f1c8954dda582909a8d37bc6c6.png -------------------------------------------------------------------------------- /example/gogs_zh/e00b4e8899e00091e6ac46d230d53c2f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/e00b4e8899e00091e6ac46d230d53c2f.png -------------------------------------------------------------------------------- /example/gogs_zh/output/book.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/output/book.epub -------------------------------------------------------------------------------- /example/gogs_zh/output/book.mobi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/output/book.mobi -------------------------------------------------------------------------------- /example/gogs_zh/output/book.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TruthHun/converter/3f6d982de99e2dfdb4bea796c8c25bfc7be8359c/example/gogs_zh/output/book.pdf -------------------------------------------------------------------------------- /example/gogs_zh/statement.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 致谢 - 书栈(BookStack.CN) 8 | 9 | 14 | 15 | 16 |

致谢

17 |
18 |

当前文档 《Gogs中文文档》 由 进击的皇虫 使用 书栈(BookStack.CN) 进行构建,生成于 2018-01-21。

19 |

书栈(BookStack.CN) 仅提供文档编写、整理、归类等功能,以及对文档内容的生成和导出工具。

20 |

文档内容由网友们编写和整理,书栈(BookStack.CN) 难以确认文档内容知识点是否错漏。如果您在阅读文档获取知识的时候,发现文档内容有不恰当的地方,请向我们反馈,让我们共同携手,将知识准确、高效且有效地传递给每一个人。

21 |

同时,如果您在日常生活、工作和学习中遇到有价值有营养的知识文档,欢迎分享到 书栈(BookStack.CN) ,为知识的传承献上您的一份力量!

22 |

如果当前文档生成时间太久,请到 书栈(BookStack.CN) 获取最新的文档,以跟上知识更新换代的步伐。

23 |

文档地址:http://www.bookstack.cn/books/gogs_zh

24 |

书栈官网:http://www.bookstack.cn

25 |

书栈开源:https://github.com/TruthHun

26 |

分享,让知识传承更久远! 感谢知识的创造者,感谢知识的分享者,也感谢每一位阅读到此处的读者,因为我们都将成为知识的传承者。

27 |
28 | 29 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/TruthHun/converter 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/TruthHun/gotil v0.0.0-20221201022546-19fe8ec6ef40 7 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= 2 | github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM= 3 | github.com/TruthHun/gotil v0.0.0-20221201022546-19fe8ec6ef40 h1:wLKVlwymHUF3EoYxIzqR/bpvE/wXAcuX0jZCDUlf6N8= 4 | github.com/TruthHun/gotil v0.0.0-20221201022546-19fe8ec6ef40/go.mod h1:i5tqOvH+rsm0voXHnKkzayNkWnv8L/F7wVv+mBdrAL0= 5 | github.com/astaxie/beego v1.12.0/go.mod h1:fysx+LZNZKnvh4GED/xND7jWtjCR6HzydR2Hh2Im57o= 6 | github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ= 7 | github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg= 8 | github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= 9 | github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU= 10 | github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= 11 | github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE= 12 | github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= 13 | github.com/couchbase/go-couchbase v0.0.0-20181122212707-3e9b6e1258bb/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U= 14 | github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= 15 | github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= 16 | github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY= 17 | github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= 18 | github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= 19 | github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= 20 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 21 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 22 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 23 | github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= 24 | github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 25 | github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 26 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 27 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 28 | github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 29 | github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI= 30 | github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= 31 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 32 | github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= 33 | github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg= 34 | github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA= 35 | github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE= 36 | github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= 37 | github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc= 38 | golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 39 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 40 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 41 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= 42 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 43 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 44 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 45 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 46 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 47 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 48 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 49 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 50 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | //Author:TruthHun 2 | //Email:TruthHun@QQ.COM 3 | //Date:2018-01-21 4 | package main 5 | 6 | import ( 7 | "os" 8 | 9 | "fmt" 10 | 11 | "github.com/TruthHun/converter/converter" 12 | ) 13 | 14 | func main() { 15 | args := os.Args[1:] 16 | if len(args) == 0 { 17 | fmt.Println("错误:缺少指定的json配置文件") 18 | } else { 19 | if converter, err := converter.NewConverter(args[0]); err != nil { 20 | fmt.Println(err.Error()) 21 | } else { 22 | if err = converter.Convert(); err != nil { 23 | fmt.Println(err.Error()) 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 目录 2 | - [缘由](#intro) 3 | - [安装calibre](#intro) 4 | - [文档导出效果](#effect) 5 | - [快速体验](#quick) 6 | - [使用案例](#example) 7 | - [配置文件](#config) 8 | - [json配置示例](#config-example) 9 | - [json配置项说明](#config-statement) 10 | - [使用教程](#tutorial) 11 | - [Go语言使用](#tutorial-go) 12 | - [其它语言](#tutorial-other) 13 | - [原理](#principle) 14 | - [注意事项](#attention) 15 | - [精神上支持我](#support) 16 | - [markdown文档如何转成pdf、epub、mobi](#markdown) 17 | 18 | 通过calibre,将markdown和html转成epub、mobi、pdf等格式文档。 19 | 20 | > 说明(于2018-06-02):calibre将HTML转成mobi等格式时请注意配置好各项配置参数到合理值,同时注意自己的HTML的样式调整,特别是在mobi格式的时候,html的CSS样式,如`background:#dddddd`设置背景色,颜色不生效,需要用`background-color:#dddddd`才会生效。 21 | 目前经过多次测试,生成文档效果不佳的问题,主要是配置参数如字体大小和CSS样式问题造成的。同时,为了方便在epub等阅读器上的阅读体验,可以将body标签的CSS背景色设置为透明。 22 | 23 | 24 | 25 | 26 | ## 缘由 27 | 28 | 事情是这样的:我们公司 [掘金量化](https://www.myquant.cn)(跟[掘金](https://juejin.im)是`javascript`和`java`的关系) 让我开发公司官网,官网的帮助中心文档,需要生成pdf离线文档以方便用户阅读和使用,但是使用`wkhtmltopdf`生成PDF文档,效果不是很理想。 29 | 30 | 看着gitbook和看云生成的PDF文档,非常完美,然后把从两个站点下载的PDF文档的后缀改成了`.xml`格式,文本编辑器打开一看,用的居然是`calibre`,然后当时捣鼓了半个月,终于把问题解决。 31 | 32 | 感觉很多企业和个人可能也会有同样的需求,所以干脆将`calibre`的使用封装一下,开源出来,以方便更多的人。 33 | 34 | > 当前文档,会告诉你使用方式和生成原理,以便你也可以根据自己掌握的编程语言封装一个工具类 35 | 36 | 37 | ## 安装calibre 38 | - 下载地址:https://calibre-ebook.com/download 39 | - 根据自己的系统安装对应的calibre(需要注意的是,calibre要安装3.x版本的,2.x版本的功能不是很强大。反正安装最新的就好。) 40 | - 安装完calibre之后,将calibre加入到系统环境变量中,执行下面的命令之后显示3.x的版本即表示安装成功。 41 | ``` 42 | ebook-convert --version 43 | ``` 44 | 45 | ## 文档导出效果 46 | 案例使用的是无闻的《Gogs中文文档》,文档地址:https://www.bookstack.cn/books/gogs_zh ,可以访问该地址查看文档导出的实际效果。 47 | 48 | 截图: 49 | ![文档导出效果](effect.png) 50 | 51 | 52 | ## 快速体验 53 | 如果成功安装了calibre,并配置了环境变量,则可以按照下面的方式进行快速体验。(bin目录下是各系统64位的二进制可执行程序,限64位系统) 54 | - Windows用户,进入`bin/win`目录,执行命令: 55 | ``` 56 | ./converter.exe ../../example/gogs_zh/config.json 57 | ``` 58 | - Mac用户,进入`bin/mac`目录,执行命令: 59 | ``` 60 | ./converter ../../example/gogs_zh/config.json 61 | ``` 62 | - Linux用户,进入`bin/linux`目录,执行命令: 63 | ``` 64 | ./converter ../../example/gogs_zh/config.json 65 | ``` 66 | 执行成功之后,在`example/gogs_zh/output`下可以看到导出的文档 67 | 68 | 69 | ## 使用案例 70 | - 掘金量化 https://www.myquant.cn (这是我们公司的官网,做量化投资的。戳进去,"帮助中心"里面可以看到文档导出效果) 71 | - 书栈网(BookStack) https://www.bookstack.cn (基于MinDoc做的二次开发的站点,开源地址:https://github.com/TruthHun/BookStack) 72 | - MinDoc https://github.com/lifei6671/mindoc 73 | 74 | 75 | ## 配置文件 76 | 以json作为配置文件,配置文件的文件名不限制,在使用的时候指定一下配置文件的文件名即可。 77 | 需要注意的是,json配置文件需要放在项目的根目录下。比如示例项目,`example/gogz_zh`中,配置文件`config.json`就是放在项目的根目录 78 | 79 | 80 | ### json配置示例 81 | ```json 82 | { 83 | "charset": "utf-8", 84 | "cover": "", 85 | "date": "2018-01-21", 86 | "description": "Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发,并且支持 Go 语言支持的 所有平台,包括 Linux、Mac OS X、Windows 以及 ARM 平台。", 87 | "footer": "

本文档使用 书栈(BookStack.CN) 构建 - _PAGENUM_ -

", 88 | "header": "

_SECTION_

", 89 | "identifier": "", 90 | "language": "zh-CN", 91 | "creator": "书栈(BookStack.CN)", 92 | "publisher": "书栈(BookStack.CN)", 93 | "contributor": "书栈(BookStack.CN)", 94 | "title": "Gogs中文文档", 95 | "format": ["epub", "mobi", "pdf"], 96 | "font_size": "14", 97 | "paper_size": "a4", 98 | "margin_left": "72", 99 | "margin_right": "72", 100 | "margin_top": "72", 101 | "margin_bottom": "72", 102 | "more": [], 103 | "toc": [{ 104 | "id": 709800000, 105 | "link": "statement.html", 106 | "pid": 0, 107 | "title": "致谢" 108 | }, { 109 | "id": 539, 110 | "link": "539.html", 111 | "pid": 538, 112 | "title": "5.1 配置文件手册" 113 | }, { 114 | "id": 545, 115 | "link": "545.html", 116 | "pid": 543, 117 | "title": "4.1 自定义模板" 118 | }, { 119 | "id": 549, 120 | "link": "549.html", 121 | "pid": 548, 122 | "title": "2.1 注册 Windows 服务" 123 | }, { 124 | "id": 554, 125 | "link": "554.html", 126 | "pid": 0, 127 | "title": "1. 简介" 128 | }, { 129 | "id": 555, 130 | "link": "555.html", 131 | "pid": 554, 132 | "title": "1.1 变更日志" 133 | }, { 134 | "id": 540, 135 | "link": "540.html", 136 | "pid": 538, 137 | "title": "5.2 公告与高阶指南" 138 | }, { 139 | "id": 547, 140 | "link": "547.html", 141 | "pid": 543, 142 | "title": "4.2 Web 钩子" 143 | }, { 144 | "id": 548, 145 | "link": "548.html", 146 | "pid": 0, 147 | "title": "2. 下载安装" 148 | }, { 149 | "id": 556, 150 | "link": "556.html", 151 | "pid": 554, 152 | "title": "1.2 常见问题" 153 | }, { 154 | "id": 559, 155 | "link": "559.html", 156 | "pid": 558, 157 | "title": "3.1 二进制升级" 158 | }, { 159 | "id": 546, 160 | "link": "546.html", 161 | "pid": 543, 162 | "title": "4.3 多国语言支持" 163 | }, { 164 | "id": 550, 165 | "link": "550.html", 166 | "pid": 548, 167 | "title": "2.2 配置与运行" 168 | }, { 169 | "id": 557, 170 | "link": "557.html", 171 | "pid": 554, 172 | "title": "1.3 故障排查" 173 | }, { 174 | "id": 558, 175 | "link": "558.html", 176 | "pid": 0, 177 | "title": "3. 版本升级" 178 | }, { 179 | "id": 560, 180 | "link": "560.html", 181 | "pid": 558, 182 | "title": "3.2 源码升级" 183 | }, { 184 | "id": 543, 185 | "link": "543.html", 186 | "pid": 0, 187 | "title": "4. 功能介绍" 188 | }, { 189 | "id": 544, 190 | "link": "544.html", 191 | "pid": 543, 192 | "title": "4.4 授权认证" 193 | }, { 194 | "id": 551, 195 | "link": "551.html", 196 | "pid": 548, 197 | "title": "2.3 二进制安装" 198 | }, { 199 | "id": 538, 200 | "link": "538.html", 201 | "pid": 0, 202 | "title": "5. 高级用法" 203 | }, { 204 | "id": 552, 205 | "link": "552.html", 206 | "pid": 548, 207 | "title": "2.4 包管理安装" 208 | }, { 209 | "id": 542, 210 | "link": "542.html", 211 | "pid": 0, 212 | "title": "6. 捐赠我们" 213 | }, { 214 | "id": 553, 215 | "link": "553.html", 216 | "pid": 548, 217 | "title": "2.5 源码安装" 218 | }] 219 | } 220 | ``` 221 | 222 | 223 | ### json配置项说明 224 | - `charset` 指定字符集,留空则默认为utf-8编码。选填。 225 | - `cover` 封面图片,一张`800x1068`像素或该尺寸比例的图片,jpg、png或gif格式。如果没有封面,请置空。选填。 226 | - `date` 文档生成日期,年月日时分秒都可以。默认当前日期时间。选填。 227 | - `title` 文档标题。必填。 228 | - `description` 文档描述、摘要。选填。 229 | - `footer`、`header` 生成PDF文档时,文档的底部(footer)和顶部(header)内容,仅对PDF文档有效。选填。 230 | - `identifier` 出版物的标识。留空即可。 231 | - `language` 语言。必填。可选值:zh、en、zh-CN、en-US等。 232 | - `creator`、`publisher`、`contributor` 如果你懒的话,三个都传同一个值,比如示例中的"书栈(BookStack.CN)"。如果真要区分的话,`creator`就是文档作者,比如"进击的皇虫",`publisher`、`contributor`理解为出版单位和构建人。三个配置项,建议填写。 233 | - `format` 导出的文档格式,不传值则默认导出PDF。可选值:epub、pdf、mobi。 234 | - `font_size` 数字,默认字体大小,仅对导出PDF有效。选填。 235 | - `paper_size` 导出文档的页面大小,不区分大小写。默认"A4",选填。可选值: `a0`, `a1`, `a2`, `a3`, `a4`, `a5`, `a6`, `b0`, `b1`, `b2`, `b3`, `b4`,`b5`, `b6`, `legal`, `letter` 236 | - `margin_left`、`margin_right`、`margin_top`、`margin_bottom` 数字,左边距、右边距、上边距、下边距,仅对PDF文档有效。选填,默认72,即表示72pt。 237 | - `more` 更多选项。仅对PDF有效。不建议使用。 238 | - `toc` 重要!!!这个是重中之重,用于生成文档目录的。`id`、`pid`是数字,`pid`表示上级的id。id的值不能重复。`link`表示html链接文件。toc里面的`title`表示目录章节标题。 239 | 240 | (参照示例的`config.json`去配置就好。) 241 | 242 | 243 | ## 使用教程 244 | bin目录下的是当前程序生成的64位的二进制可执行文件。Windows下使用示例: 245 | ``` 246 | converter.exe path/to/config.json 247 | ``` 248 | 执行成功之后,会自动在项目目录下创建个`output`文件夹,并将文件导出到里面。比如导出pdf格式,则会在`output`文件夹下面出现`book.pdf`文件。 249 | 250 | 251 | ### Go语言使用 252 | 引入当前包: 253 | `github.com/TruthHun/converter/converter` 254 | ```golang 255 | if Convert, err:= converter.NewConverter("path/to/config.json");err==nil{ 256 | Convert.Convert() 257 | } 258 | ``` 259 | 260 | 261 | ### 其它语言 262 | 由于目前没封装PHP、Python等的类和包,所以其它语言要使用的话,就是在项目下生成一个config.json(名字随便自己定义),然后调用各自语言的cmd执行: 263 | ``` 264 | /path/to/converter /path/to/config.json 265 | ``` 266 | 267 | ## 原理 268 | HTML导出PDF、epub等文档的原理很简单:根据config.json中的内容,生成epub电子书的基本结构,然后将当前目录下的文件压缩并重命名如`content.epub`,然后再使用`ebook-convert`进行转换,转换命令: 269 | ``` 270 | ebook-convert content.epub output/book.pdf [options] 271 | ``` 272 | 这样,你就可以使用自己熟悉的语言封装一个包,并调用calibre导出文档了。 273 | 274 | 275 | 276 | ## 注意事项 277 | - HTML中不要有使用js代码渲染文档内容,因为js是不会被执行的 278 | 279 | 280 | ## 精神上支持我 281 | 虽然我很缺钱... 282 | 但是得到他人的肯定和认可比什么都重要。 283 | 如果当前项目帮到了你,请给项目一个star,以鼓励我在开源的路上能走的更好、更远。 284 | 附自己业余时间搞的一些站点,支持我,可以点击访问一下: 285 | - IT文库 http://wenku.it 286 | - 书栈(BookStack) http://www.bookstack.cn 287 | 288 | 289 | ## markdown文档如何转成pdf、epub、mobi 290 | 说实话,这个我没仔细去研究过。思路就是将markdown文档转成HTML(毕竟这样比较好控制显示样式),然后再通过当前工具再转成PDF文档等。网上应该有更好的方法,如果大家找到了,麻烦也分享一下。 291 | 292 | 293 | 294 | --------------------------------------------------------------------------------