├── .gitattributes ├── .gitignore ├── LICENSE ├── NetCoreBBS.sln ├── NuGet.Config ├── README.md ├── src ├── ApplicationCore │ ├── ApplicationCore.csproj │ ├── Entities │ │ ├── BaseEntity.cs │ │ ├── Topic.cs │ │ ├── TopicNode.cs │ │ ├── TopicReply.cs │ │ ├── User.cs │ │ ├── UserCollection.cs │ │ └── UserMessage.cs │ ├── Interfaces │ │ ├── IRepository.cs │ │ ├── ITopicReplyRepository.cs │ │ └── ITopicRepository.cs │ └── Page.cs ├── Infrastructure │ ├── DataContext.cs │ ├── Infrastructure.csproj │ ├── Migrations │ │ ├── 20170606024516_InitMigration.Designer.cs │ │ ├── 20170606024516_InitMigration.cs │ │ └── DataContextModelSnapshot.cs │ └── Repositorys │ │ ├── Repository.cs │ │ ├── TopicReplyRepository.cs │ │ └── TopicRepository.cs └── NetCoreBBS │ ├── .bowerrc │ ├── .vscode │ ├── launch.json │ └── tasks.json │ ├── Areas │ └── Admin │ │ ├── Controllers │ │ ├── ManageController.cs │ │ ├── NodeController.cs │ │ ├── TopicController.cs │ │ ├── TopicRepliesController.cs │ │ └── UserController.cs │ │ ├── Views │ │ ├── Manage │ │ │ └── Index.cshtml │ │ ├── Node │ │ │ ├── Create.cshtml │ │ │ ├── Edit.cshtml │ │ │ └── Index.cshtml │ │ ├── Topic │ │ │ └── Index.cshtml │ │ ├── TopicReplies │ │ │ └── Index.cshtml │ │ └── User │ │ │ └── Index.cshtml │ │ ├── _ViewImports.cshtml │ │ └── _ViewStart.cshtml │ ├── Controllers │ ├── AccountController.cs │ ├── HomeController.cs │ ├── TopicController.cs │ └── UserController.cs │ ├── MessageServices.cs │ ├── Middleware │ └── RequestIPMiddleware.cs │ ├── NetCoreBBS.csproj │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Startup.cs │ ├── UserServices.cs │ ├── ViewComponents │ ├── Statistics.cs │ └── TopicRankList.cs │ ├── ViewModels │ ├── LoginViewModel.cs │ ├── TopicViewModel.cs │ └── UserViewModel.cs │ ├── Views │ ├── Account │ │ ├── ForgotPassword.cshtml │ │ ├── Login.cshtml │ │ ├── Register.cshtml │ │ └── _ExternalLoginsListPartial.cshtml │ ├── Home │ │ ├── About.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── Components │ │ │ ├── Statistics │ │ │ │ └── Default.cshtml │ │ │ └── TopicRankList │ │ │ │ └── Default.cshtml │ │ ├── Error.cshtml │ │ ├── _AdminLayout.cshtml │ │ ├── _Layout.cshtml │ │ ├── _LoginPartial.cshtml │ │ ├── _PagerPartial.cshtml │ │ └── _SidebarPartial.cshtml │ ├── Topic │ │ ├── Index.cshtml │ │ └── Node.cshtml │ ├── User │ │ ├── Edit.cshtml │ │ └── Index.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml │ ├── appsettings.json │ ├── bower.json │ ├── bundleconfig.json │ ├── nlog.config │ └── wwwroot │ ├── _references.js │ ├── css │ ├── dashboard.css │ └── site.css │ ├── images │ └── 96.png │ ├── js │ ├── markdown.js │ └── to-markdown.js │ └── lib │ ├── bootstrap-markdown │ ├── .bower.json │ ├── .editorconfig │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── bower.json │ ├── css │ │ └── bootstrap-markdown.min.css │ ├── js │ │ └── bootstrap-markdown.js │ ├── less │ │ └── bootstrap-markdown.less │ ├── locale │ │ ├── bootstrap-markdown.ar.js │ │ ├── bootstrap-markdown.cs.js │ │ ├── bootstrap-markdown.da.js │ │ ├── bootstrap-markdown.de.js │ │ ├── bootstrap-markdown.es.js │ │ ├── bootstrap-markdown.fa.js │ │ ├── bootstrap-markdown.fr.js │ │ ├── bootstrap-markdown.it.js │ │ ├── bootstrap-markdown.ja.js │ │ ├── bootstrap-markdown.kr.js │ │ ├── bootstrap-markdown.nb.js │ │ ├── bootstrap-markdown.nl.js │ │ ├── bootstrap-markdown.pl.js │ │ ├── bootstrap-markdown.ru.js │ │ ├── bootstrap-markdown.sl.js │ │ ├── bootstrap-markdown.sv.js │ │ ├── bootstrap-markdown.tr.js │ │ ├── bootstrap-markdown.ua.js │ │ └── bootstrap-markdown.zh.js │ ├── package.json │ └── scss │ │ └── bootstrap-markdown.scss │ ├── bootstrap │ ├── .bower.json │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── jquery-validation-unobtrusive │ ├── .bower.json │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ ├── .bower.json │ ├── LICENSE.md │ └── dist │ │ ├── additional-methods.js │ │ ├── additional-methods.min.js │ │ ├── jquery.validate.js │ │ └── jquery.validate.min.js │ └── jquery │ ├── .bower.json │ ├── LICENSE.txt │ └── dist │ ├── jquery.js │ ├── jquery.min.js │ └── jquery.min.map └── tests └── UnitTests └── UnitTests.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | *.js linguist-language=csharp -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Microsoft Azure ApplicationInsights config file 170 | ApplicationInsights.config 171 | 172 | # Windows Store app package directory 173 | AppPackages/ 174 | BundleArtifacts/ 175 | 176 | # Visual Studio cache files 177 | # files ending in .cache can be ignored 178 | *.[Cc]ache 179 | # but keep track of directories ending in .cache 180 | !*.[Cc]ache/ 181 | 182 | # Others 183 | ClientBin/ 184 | [Ss]tyle[Cc]op.* 185 | ~$* 186 | *~ 187 | *.dbmdl 188 | *.dbproj.schemaview 189 | *.pfx 190 | *.publishsettings 191 | node_modules/ 192 | orleans.codegen.cs 193 | 194 | # RIA/Silverlight projects 195 | Generated_Code/ 196 | 197 | # Backup & report files from converting an old project file 198 | # to a newer Visual Studio version. Backup files are not needed, 199 | # because we have git ;-) 200 | _UpgradeReport_Files/ 201 | Backup*/ 202 | UpgradeLog*.XML 203 | UpgradeLog*.htm 204 | 205 | # SQL Server files 206 | *.mdf 207 | *.ldf 208 | 209 | # Business Intelligence projects 210 | *.rdl.data 211 | *.bim.layout 212 | *.bim_*.settings 213 | 214 | # Microsoft Fakes 215 | FakesAssemblies/ 216 | 217 | # GhostDoc plugin setting file 218 | *.GhostDoc.xml 219 | 220 | # Node.js Tools for Visual Studio 221 | .ntvs_analysis.dat 222 | 223 | # Visual Studio 6 build log 224 | *.plg 225 | 226 | # Visual Studio 6 workspace options file 227 | *.opt 228 | 229 | # Visual Studio LightSwitch build output 230 | **/*.HTMLClient/GeneratedArtifacts 231 | **/*.DesktopClient/GeneratedArtifacts 232 | **/*.DesktopClient/ModelManifest.xml 233 | **/*.Server/GeneratedArtifacts 234 | **/*.Server/ModelManifest.xml 235 | _Pvt_Extensions 236 | 237 | # LightSwitch generated files 238 | GeneratedArtifacts/ 239 | ModelManifest.xml 240 | 241 | # Paket dependency manager 242 | .paket/paket.exe 243 | 244 | # FAKE - F# Make 245 | .fake/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 LineZero NETCoreBBS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /NetCoreBBS.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26403.7 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{94F5C8A4-D158-4A10-AD26-C635A376CC92}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E8623DEC-42D5-42AD-AF33-2A5540D09828}" 9 | ProjectSection(SolutionItems) = preProject 10 | NuGet.Config = NuGet.Config 11 | EndProjectSection 12 | EndProject 13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreBBS", "src\NetCoreBBS\NetCoreBBS.csproj", "{7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApplicationCore", "src\ApplicationCore\ApplicationCore.csproj", "{65AC78E9-500F-42B5-954D-93F841F5D0F1}" 18 | EndProject 19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D25B2B42-A638-4F40-B51C-DCF41A3C8F4C}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "tests\UnitTests\UnitTests.csproj", "{152AAF50-21A3-477D-BB56-A25E56D4B611}" 22 | EndProject 23 | Global 24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 25 | Debug|Any CPU = Debug|Any CPU 26 | Release|Any CPU = Release|Any CPU 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {65AC78E9-500F-42B5-954D-93F841F5D0F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {65AC78E9-500F-42B5-954D-93F841F5D0F1}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {65AC78E9-500F-42B5-954D-93F841F5D0F1}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {65AC78E9-500F-42B5-954D-93F841F5D0F1}.Release|Any CPU.Build.0 = Release|Any CPU 41 | {152AAF50-21A3-477D-BB56-A25E56D4B611}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {152AAF50-21A3-477D-BB56-A25E56D4B611}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {152AAF50-21A3-477D-BB56-A25E56D4B611}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {152AAF50-21A3-477D-BB56-A25E56D4B611}.Release|Any CPU.Build.0 = Release|Any CPU 45 | EndGlobalSection 46 | GlobalSection(SolutionProperties) = preSolution 47 | HideSolutionNode = FALSE 48 | EndGlobalSection 49 | GlobalSection(NestedProjects) = preSolution 50 | {7FEB182D-CFA4-4DA2-A9FF-0ABF794F8A4D} = {94F5C8A4-D158-4A10-AD26-C635A376CC92} 51 | {1AA24171-F5E6-4E7A-B227-A6ECD34DA2E7} = {94F5C8A4-D158-4A10-AD26-C635A376CC92} 52 | {65AC78E9-500F-42B5-954D-93F841F5D0F1} = {94F5C8A4-D158-4A10-AD26-C635A376CC92} 53 | {152AAF50-21A3-477D-BB56-A25E56D4B611} = {D25B2B42-A638-4F40-B51C-DCF41A3C8F4C} 54 | EndGlobalSection 55 | EndGlobal 56 | -------------------------------------------------------------------------------- /NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NETCoreBBS 2 | ASP.NET Core Light forum NETCoreBBS 3 | 4 | ASP.NET Core + EF Core Sqlite + Bootstrap 5 | 6 | .NET Core 跨平台轻论坛 7 | 8 | [使用技术点介绍](http://www.cnblogs.com/linezero/p/NETCoreBBS.html) 9 | 10 | ## 开发 11 | 12 | 1. `git clone https://github.com/linezero/NETCoreBBS.git` 13 | 2. 使用 Visual Studio 2019 打开 `NetCoreBBS.sln` 14 | 3. 点击 `调试->开始调试` 即可运行起来,或者直接点击工具栏上的`NetCoreBBS`即可。 15 | 16 | 注意:默认为80端口,可能会和本地端口冲突,可以到Program.cs 中更改 `.UseUrls("http://*:80")`,然后更改启动URL既可。 17 | 18 | ## 功能 19 | 20 | 1. 节点功能 21 | 1. 主题发布 22 | 2. 主题回复 23 | 3. 主题筛选 24 | 3. 用户登录注册 25 | 4. 主题置顶 26 | 5. 后台管理 27 | 6. 个人中心 28 | 29 | ## 后台管理 30 | 31 | 使用 admin 注册后默认即为管理员,登录后可以看到管理中心选项。 32 | 33 | ## License 34 | NETCoreBBS is licensed under [MIT](LICENSE). 35 | -------------------------------------------------------------------------------- /src/ApplicationCore/ApplicationCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.1 5 | NetCoreBBS 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/ApplicationCore/Entities/BaseEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NetCoreBBS.Entities 6 | { 7 | public class BaseEntity 8 | { 9 | public int Id { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/ApplicationCore/Entities/Topic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace NetCoreBBS.Entities 5 | { 6 | public class Topic:BaseEntity 7 | { 8 | public int NodeId { get; set; } 9 | public TopicNode Node { get; set; } 10 | public string UserId { get; set; } 11 | public User User { get; set; } 12 | public string Email { get; set; } 13 | public string Title { get; set; } 14 | public string Content { get; set; } 15 | /// 16 | /// 置顶权重 17 | /// 18 | public int Top { get; set; } 19 | public TopicType Type { get; set; } 20 | public int ViewCount { get; set; } 21 | public int ReplyCount { get; set; } 22 | public string LastReplyUserId { get; set; } 23 | public User LastReplyUser { get; set; } 24 | public DateTime LastReplyTime { get; set; } 25 | public DateTime CreateOn { get; set; } 26 | public virtual List Replys { get; set; } 27 | } 28 | public enum TopicType 29 | { 30 | Delete=0, 31 | Normal = 1, 32 | Top=2, 33 | Good=3, 34 | Hot=4 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ApplicationCore/Entities/TopicNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NetCoreBBS.Entities 7 | { 8 | public class TopicNode:BaseEntity 9 | { 10 | public int ParentId { get; set; } 11 | public string NodeName { get; set; } 12 | public string Name { get; set; } 13 | public string Description { get; set; } 14 | public int Order { get; set; } 15 | public DateTime CreateOn { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/ApplicationCore/Entities/TopicReply.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetCoreBBS.Entities 8 | { 9 | public class TopicReply:BaseEntity 10 | { 11 | public int TopicId { get; set; } 12 | public string ReplyUserId { get; set; } 13 | public User ReplyUser { get; set; } 14 | public string ReplyEmail { get; set; } 15 | public string ReplyContent { get; set; } 16 | public DateTime CreateOn { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ApplicationCore/Entities/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Identity; 6 | 7 | namespace NetCoreBBS.Entities 8 | { 9 | public class User: IdentityUser 10 | { 11 | public string Avatar { get; set; } 12 | public string Profile { get; set; } 13 | public string Url { get; set; } 14 | public string GitHub { get; set; } 15 | public int TopicCount { get; set; } 16 | public int TopicReplyCount { get; set; } 17 | public int Score { get; set; } 18 | public DateTime CreateOn { get; set; } 19 | public DateTime LastTime { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/ApplicationCore/Entities/UserCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NetCoreBBS.Entities 7 | { 8 | public class UserCollection:BaseEntity 9 | { 10 | public string UserId { get; set; } 11 | public int TopicId { get; set; } 12 | public Topic Topic { get; set; } 13 | public int State { get; set; } 14 | public DateTime CreateOn { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ApplicationCore/Entities/UserMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NetCoreBBS.Entities 7 | { 8 | public class UserMessage:BaseEntity 9 | { 10 | public string SendUserId { get; set; } 11 | public User SendUser { get; set; } 12 | public string ReceiveUserId { get; set; } 13 | public User ReceiveUser { get; set; } 14 | public string Type { get; set; } 15 | public string Content { get; set; } 16 | public int State { get; set; } 17 | public DateTime CreateOn { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ApplicationCore/Interfaces/IRepository.cs: -------------------------------------------------------------------------------- 1 | using NetCoreBBS.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | 7 | namespace NetCoreBBS.Interfaces 8 | { 9 | public interface IRepository where T: BaseEntity 10 | { 11 | T GetById(int id); 12 | IEnumerable List(); 13 | IEnumerable List(Expression> predicate); 14 | void Add(T entity); 15 | void Delete(T entity); 16 | void Edit(T entity); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ApplicationCore/Interfaces/ITopicReplyRepository.cs: -------------------------------------------------------------------------------- 1 | using NetCoreBBS.Entities; 2 | 3 | namespace NetCoreBBS.Interfaces 4 | { 5 | public interface ITopicReplyRepository:IRepository 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/ApplicationCore/Interfaces/ITopicRepository.cs: -------------------------------------------------------------------------------- 1 | using NetCoreBBS.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | 7 | namespace NetCoreBBS.Interfaces 8 | { 9 | public interface ITopicRepository:IRepository 10 | { 11 | Page PageList(int pagesize,int pageindex); 12 | Page PageList(Expression> predicate, int pagesize, int pageindex); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ApplicationCore/Page.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NetCoreBBS.Entities 6 | { 7 | public class Page 8 | where T : class 9 | { 10 | public int Total { get; private set; } 11 | public int PageSize { get; private set; } 12 | public List List { get; private set; } 13 | public Page(List list, int pageSize, int total) 14 | { 15 | this.List = list; 16 | this.PageSize = pageSize; 17 | this.Total = total; 18 | } 19 | 20 | public int GetPageCount() 21 | { 22 | return (Total + PageSize - 1) / PageSize; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Infrastructure/DataContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using NetCoreBBS.Entities; 8 | 9 | namespace NetCoreBBS.Infrastructure 10 | { 11 | public class DataContext : IdentityDbContext 12 | { 13 | public DataContext(DbContextOptions options) 14 | : base(options) 15 | { 16 | } 17 | public DbSet Topics { get; set; } 18 | public DbSet TopicReplys { get; set; } 19 | public DbSet TopicNodes { get; set; } 20 | public DbSet UserMessages { get; set; } 21 | public DbSet UserTopics { get; set; } 22 | 23 | protected override void OnModelCreating(ModelBuilder modelBuilder) 24 | { 25 | base.OnModelCreating(modelBuilder); 26 | modelBuilder.Entity().ToTable("Topic"); 27 | modelBuilder.Entity().ToTable("TopicReply"); 28 | modelBuilder.Entity().ToTable("TopicNode"); 29 | modelBuilder.Entity().ToTable("User"); 30 | modelBuilder.Entity().ToTable("UserMessage"); 31 | modelBuilder.Entity().ToTable("UserCollection"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Infrastructure/Infrastructure.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.1 5 | NetCoreBBS.Infrastructure 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | all 15 | runtime; build; native; contentfiles; analyzers 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Infrastructure/Repositorys/Repository.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using NetCoreBBS.Entities; 3 | using NetCoreBBS.Interfaces; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | namespace NetCoreBBS.Infrastructure.Repositorys 10 | { 11 | public class Repository : IRepository where T : BaseEntity 12 | { 13 | private readonly DataContext _dbContext; 14 | 15 | public Repository(DataContext dbContext) 16 | { 17 | _dbContext = dbContext; 18 | } 19 | 20 | public virtual T GetById(int id) 21 | { 22 | return _dbContext.Set().Find(id); 23 | } 24 | 25 | public virtual IEnumerable List() 26 | { 27 | return _dbContext.Set().AsEnumerable(); 28 | } 29 | 30 | public virtual IEnumerable List(System.Linq.Expressions.Expression> predicate) 31 | { 32 | return _dbContext.Set() 33 | .Where(predicate) 34 | .AsEnumerable(); 35 | } 36 | 37 | public void Add(T entity) 38 | { 39 | _dbContext.Set().Add(entity); 40 | _dbContext.SaveChanges(); 41 | } 42 | 43 | public void Edit(T entity) 44 | { 45 | _dbContext.Entry(entity).State = EntityState.Modified; 46 | _dbContext.SaveChanges(); 47 | } 48 | 49 | public void Delete(T entity) 50 | { 51 | _dbContext.Set().Remove(entity); 52 | _dbContext.SaveChanges(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Infrastructure/Repositorys/TopicReplyRepository.cs: -------------------------------------------------------------------------------- 1 | using NetCoreBBS.Entities; 2 | using NetCoreBBS.Interfaces; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Linq.Expressions; 7 | using Microsoft.EntityFrameworkCore; 8 | using System.Linq; 9 | 10 | namespace NetCoreBBS.Infrastructure.Repositorys 11 | { 12 | public class TopicReplyRepository : Repository, ITopicReplyRepository 13 | { 14 | private readonly DataContext _dbContext; 15 | public TopicReplyRepository(DataContext dbContext) : base(dbContext) 16 | { 17 | _dbContext = dbContext; 18 | } 19 | 20 | public override IEnumerable List(Expression> predicate) 21 | { 22 | return _dbContext.TopicReplys.Include(r=>r.ReplyUser).Where(predicate); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Infrastructure/Repositorys/TopicRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using NetCoreBBS.Entities; 5 | using System.Linq.Expressions; 6 | using Microsoft.EntityFrameworkCore; 7 | using System.Linq; 8 | using NetCoreBBS.Interfaces; 9 | 10 | namespace NetCoreBBS.Infrastructure.Repositorys 11 | { 12 | public class TopicRepository : Repository,ITopicRepository 13 | { 14 | private readonly DataContext _dbContext; 15 | 16 | public TopicRepository(DataContext dbContext) 17 | :base(dbContext) 18 | { 19 | _dbContext = dbContext; 20 | } 21 | public override Topic GetById(int id) 22 | { 23 | return _dbContext.Topics.Include(r => r.User).Include(r => r.Node).Include(r => r.LastReplyUser).FirstOrDefault(r => r.Id == id); 24 | } 25 | public override IEnumerable List(Expression> predicate) 26 | { 27 | return _dbContext.Topics.Include(r => r.Node).Where(predicate); 28 | } 29 | 30 | public Page PageList(int pagesize=20, int pageindex=1) 31 | { 32 | return PageList(null, pagesize, pageindex); 33 | } 34 | 35 | public Page PageList(Expression> predicate, int pagesize=20, int pageindex=1) 36 | { 37 | var topics = _dbContext.Topics.Include(r=>r.User).Include(r=>r.Node).Include(r=>r.LastReplyUser).AsQueryable().AsNoTracking(); 38 | if (predicate != null) 39 | { 40 | topics=topics.Where(predicate); 41 | } 42 | var count = topics.Count(); 43 | topics = topics.OrderByDescending(r => r.CreateOn) 44 | .OrderByDescending(r => r.Top) 45 | .Skip((pageindex - 1) * pagesize).Take(pagesize); 46 | return new Page(topics.ToList(), pagesize, count); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NetCoreBBS/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "wwwroot/lib" 3 | } 4 | -------------------------------------------------------------------------------- /src/NetCoreBBS/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": ".NET Core Launch (web)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build", 9 | "program": "${workspaceRoot}\\bin\\Debug\\netcoreapp1.0\\NetCoreBBS.dll", 10 | "args": [], 11 | "cwd": "${workspaceRoot}", 12 | "stopAtEntry": false, 13 | "launchBrowser": { 14 | "enabled": true, 15 | "args": "${auto-detect-url}", 16 | "windows": { 17 | "command": "cmd.exe", 18 | "args": "/C start ${auto-detect-url}" 19 | }, 20 | "osx": { 21 | "command": "open" 22 | }, 23 | "linux": { 24 | "command": "xdg-open" 25 | } 26 | }, 27 | "env": { 28 | "ASPNETCORE_ENVIRONMENT": "Development" 29 | }, 30 | "sourceFileMap": { 31 | "/Views": "${workspaceRoot}/Views" 32 | } 33 | }, 34 | { 35 | "name": ".NET Core Attach", 36 | "type": "coreclr", 37 | "request": "attach", 38 | "processId": "${command.pickProcess}" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "dotnet", 4 | "isShellCommand": true, 5 | "args": [], 6 | "tasks": [ 7 | { 8 | "taskName": "build", 9 | "args": [ 10 | "${workspaceRoot}\\project.json" 11 | ], 12 | "isBuildCommand": true, 13 | "problemMatcher": "$msCompile" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Controllers/ManageController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Authorization; 7 | using NetCoreBBS.Infrastructure; 8 | 9 | // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 10 | 11 | namespace NetCoreBBS.Areas.Admin.Controllers 12 | { 13 | [Area("Admin")] 14 | [Authorize("Admin")] 15 | public class ManageController : Controller 16 | { 17 | private DataContext _context; 18 | public ManageController(DataContext context) 19 | { 20 | _context = context; 21 | } 22 | public IActionResult Index() 23 | { 24 | var usercount = _context.Users.Count(); 25 | var topiccount = _context.Topics.Count(); 26 | var replycount = _context.TopicReplys.Count(); 27 | var allstatistics = new Tuple(usercount, topiccount, replycount); 28 | ViewBag.Statistics = allstatistics; 29 | var topics = _context.Topics.OrderByDescending(r => r.CreateOn).Take(10).ToList(); 30 | return View(topics); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Controllers/NodeController.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linezero/NETCoreBBS/71ac2c572f8d25d79bad0fdfd695d7d6d7e2bcf6/src/NetCoreBBS/Areas/Admin/Controllers/NodeController.cs -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Controllers/TopicController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Authorization; 7 | using NetCoreBBS.Infrastructure; 8 | using NetCoreBBS.Entities; 9 | 10 | // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 11 | 12 | namespace NetCoreBBS.Areas.Admin.Controllers 13 | { 14 | [Area("Admin")] 15 | [Authorize("Admin")] 16 | public class TopicController : Controller 17 | { 18 | private DataContext _context; 19 | public TopicController(DataContext context) 20 | { 21 | _context = context; 22 | } 23 | public IActionResult Index() 24 | { 25 | var pagesize = 20; 26 | var pageindex = 1; 27 | if (!string.IsNullOrEmpty(Request.Query["page"])) 28 | pageindex = Convert.ToInt32(Request.Query["page"]); 29 | var topics = _context.Topics.AsQueryable(); 30 | var count = topics.Count(); 31 | var topiclist = topics 32 | .OrderByDescending(r => r.CreateOn) 33 | .OrderByDescending(r => r.Top) 34 | .Skip(pagesize * (pageindex - 1)) 35 | .Take(pagesize).ToList(); 36 | ViewBag.PageIndex = pageindex; 37 | ViewBag.PageCount = count % pagesize == 0 ? count / pagesize : count / pagesize + 1; 38 | return View(topiclist); 39 | } 40 | 41 | public IActionResult Delete(int id) 42 | { 43 | var topic = _context.Topics.FirstOrDefault(r => r.Id == id); 44 | if (topic != null) 45 | { 46 | _context.Topics.Remove(topic); 47 | var replys=_context.TopicReplys.Where(r => r.TopicId == id).ToList(); 48 | _context.TopicReplys.RemoveRange(replys); 49 | _context.SaveChanges(); 50 | return RedirectToAction("Index"); 51 | } 52 | return Content("出现异常"); 53 | } 54 | 55 | [HttpPost] 56 | [ValidateAntiForgeryToken] 57 | public IActionResult EditSave(Topic topic) 58 | { 59 | _context.Attach(topic); 60 | _context.Entry(topic).Property(r => r.Title).IsModified = true; 61 | _context.Entry(topic).Property(r => r.Content).IsModified = true; 62 | _context.SaveChanges(); 63 | return RedirectToAction("Index"); 64 | } 65 | 66 | public IActionResult Update(int id, string type) 67 | { 68 | var topic = _context.Topics.FirstOrDefault(r => r.Id == id); 69 | if (topic != null) 70 | { 71 | switch (type) 72 | { 73 | case "top": 74 | topic.Top = 1; 75 | break; 76 | //case "good": 77 | // topic.Good = true; 78 | // break; 79 | case "notop": 80 | topic.Top = 0; 81 | break; 82 | //case "nogood": 83 | // topic.Good = false; 84 | // break; 85 | } 86 | _context.Update(topic); 87 | _context.SaveChanges(); 88 | return RedirectToAction("Index"); 89 | } 90 | return Content("出现异常"); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Controllers/TopicRepliesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.Rendering; 7 | using Microsoft.EntityFrameworkCore; 8 | using NetCoreBBS.Infrastructure; 9 | using Microsoft.AspNetCore.Authorization; 10 | 11 | namespace NetCoreBBS.Areas.Admin.Controllers 12 | { 13 | [Area("Admin")] 14 | [Authorize("Admin")] 15 | public class TopicRepliesController : Controller 16 | { 17 | private readonly DataContext _context; 18 | 19 | public TopicRepliesController(DataContext context) 20 | { 21 | _context = context; 22 | } 23 | 24 | // GET: TopicReplies 25 | public async Task Index(int id) 26 | { 27 | var topicreplys = _context.TopicReplys.Where(r => r.TopicId == id).ToListAsync(); 28 | return View(await topicreplys); 29 | } 30 | // GET: TopicReplies/Delete/5 31 | public async Task Delete(int? id) 32 | { 33 | if (id == null) 34 | { 35 | return NotFound(); 36 | } 37 | 38 | var topicReply = await _context.TopicReplys.SingleOrDefaultAsync(m => m.Id == id); 39 | if (topicReply == null) 40 | { 41 | return NotFound(); 42 | } 43 | var topic = await _context.Topics.SingleOrDefaultAsync(r => r.Id == topicReply.TopicId); 44 | topic.ReplyCount -= 1; 45 | _context.Topics.Update(topic); 46 | _context.TopicReplys.Remove(topicReply); 47 | await _context.SaveChangesAsync(); 48 | return NoContent(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Controllers/UserController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Authorization; 8 | using NetCoreBBS.Infrastructure; 9 | 10 | namespace NetCoreBBS.Areas.Admin.Controllers 11 | { 12 | [Area("Admin")] 13 | [Authorize("Admin")] 14 | public class UserController : Controller 15 | { 16 | private readonly DataContext _context; 17 | 18 | public UserController(DataContext context) 19 | { 20 | _context = context; 21 | } 22 | // GET: User 23 | public ActionResult Index() 24 | { 25 | var pagesize = 20; 26 | var pageindex = 1; 27 | if (!string.IsNullOrEmpty(Request.Query["page"])) 28 | pageindex = Convert.ToInt32(Request.Query["page"]); 29 | var users = _context.Users.AsQueryable(); 30 | var count = users.Count(); 31 | var userlist = users 32 | .OrderByDescending(r => r.CreateOn) 33 | .Skip(pagesize * (pageindex - 1)) 34 | .Take(pagesize).ToList(); 35 | ViewBag.PageIndex = pageindex; 36 | ViewBag.PageCount = count % pagesize == 0 ? count / pagesize : count / pagesize + 1; 37 | return View(userlist); 38 | } 39 | 40 | // GET: User/Details/5 41 | public ActionResult Details(int id) 42 | { 43 | return View(); 44 | } 45 | 46 | // POST: User/Edit/5 47 | [HttpPost] 48 | [ValidateAntiForgeryToken] 49 | public ActionResult Edit(int id, IFormCollection collection) 50 | { 51 | try 52 | { 53 | // TODO: Add update logic here 54 | 55 | return RedirectToAction("Index"); 56 | } 57 | catch 58 | { 59 | return View(); 60 | } 61 | } 62 | 63 | // POST: User/Delete/5 64 | [HttpPost] 65 | [ValidateAntiForgeryToken] 66 | public ActionResult Delete(int id, IFormCollection collection) 67 | { 68 | try 69 | { 70 | // TODO: Add delete logic here 71 | 72 | return RedirectToAction("Index"); 73 | } 74 | catch 75 | { 76 | return View(); 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Views/Manage/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model List 2 | @{ 3 | ViewBag.Title = "首页"; 4 | var Statistics = ViewBag.Statistics as Tuple; 5 | } 6 | 7 |

后台管理

8 | 9 |
10 |
11 |

@Statistics.Item2

12 | 主题数 13 |
14 |
15 |

@Statistics.Item3

16 | 回复数 17 |
18 |
19 |

@Statistics.Item1

20 | 用户数 21 |
22 |
23 | 24 |

最新主题列表

25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | @foreach (var item in Model) 36 | { 37 | 38 | 39 | 40 | 41 | 42 | } 43 | 44 |
主题发布时间回复数
@item.Title@item.CreateOn@item.ReplyCount
45 |
46 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Views/Node/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model TopicNode 2 | 3 | @{ 4 | ViewData["Title"] = "新增节点"; 5 | Layout = "~/Views/Shared/_AdminLayout.cshtml"; 6 | } 7 | 8 |

新增节点

9 | 10 |
11 |
12 |

主题节点

13 |
14 |
15 |
16 | 17 |
18 | 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 | Back to List 60 |
61 | 62 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Views/Node/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model TopicNode 2 | 3 | @{ 4 | ViewData["Title"] = "Edit"; 5 | Layout = "~/Views/Shared/_AdminLayout.cshtml"; 6 | } 7 | 8 |

Edit

9 | 10 |
11 |
12 |

TopicNode

13 |
14 |
15 | 16 |
17 | 18 |
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 | Back to List 68 |
69 | 70 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Views/Node/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewData["Title"] = "节点管理"; 5 | Layout = "~/Views/Shared/_AdminLayout.cshtml"; 6 | } 7 | 8 |

节点管理

9 | 10 |

11 | 新增父节点 12 |

13 | 14 | 15 | 16 | 19 | 22 | 25 | 28 | 31 | 34 | 35 | 36 | 37 | 38 | @foreach (var item in Model.Where(r=>r.ParentId==0).OrderBy(r => r.Order)) { 39 | 40 | 43 | 46 | 49 | 52 | 55 | 58 | 63 | 64 | foreach (var node in Model.Where(r => r.ParentId == item.Id).OrderBy(r => r.Order)) 65 | { 66 | 67 | 70 | 73 | 76 | 79 | 82 | 85 | 89 | 90 | } 91 | } 92 | 93 |
17 | 名称 18 | 20 | 节点别名 21 | 23 | 排序 24 | 26 | 父节点 27 | 29 | 描述 30 | 32 | 创建时间 33 |
41 | @Html.DisplayFor(modelItem => item.Name) 42 | 44 | @Html.DisplayFor(modelItem => item.NodeName) 45 | 47 | @Html.DisplayFor(modelItem => item.Order) 48 | 50 | @Html.DisplayFor(modelItem => item.ParentId) 51 | 53 | @Html.DisplayFor(modelItem => item.Description) 54 | 56 | @Html.DisplayFor(modelItem => item.CreateOn) 57 | 59 | 新增子节点| 60 | 编辑 | 61 | 删除 62 |
68 | -->@Html.DisplayFor(modelItem => node.Name) 69 | 71 | @Html.DisplayFor(modelItem => node.NodeName) 72 | 74 | @Html.DisplayFor(modelItem => node.Order) 75 | 77 | @Html.DisplayFor(modelItem => node.ParentId) 78 | 80 | @Html.DisplayFor(modelItem => node.Description) 81 | 83 | @Html.DisplayFor(modelItem => node.CreateOn) 84 | 86 | 编辑 | 87 | 删除 88 |
94 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Views/Topic/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model List 2 | @{ 3 | ViewBag.Title = "主题列表"; 4 | } 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | @foreach (var item in Model) 22 | { 23 | 24 | 25 | 26 | 27 | 28 | 29 | 35 | 83 | 84 | } 85 | 86 |
主题发布时间回复数回复时间类型回复管理
@(item.Top == 1 ? "[置顶]" : "")@item.Title@item.CreateOn@item.ReplyCount@item.LastReplyTime@(item.Type) 30 | @if (item.ReplyCount > 0) 31 | { 32 | 查看 33 | } 34 | 36 | 63 | 编辑| 64 | 删除| 65 | @if (item.Top == 0) 66 | { 67 | 置顶 68 | } 69 | else 70 | { 71 | 取消置顶 72 | } 73 | | 74 | @if ((int)item.Type==1) 75 | { 76 | 优质 77 | } 78 | else 79 | { 80 | 取消优质 81 | } 82 |
87 | @await Html.PartialAsync("_PagerPartial", ViewData) 88 |
89 | 101 | @section scripts{ 102 | 118 | } 119 | 120 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Views/TopicReplies/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model List 2 | @{ 3 | Layout = ""; 4 | } 5 | 6 | @for (int i = 0; i < Model.Count; i++) 7 | { 8 | var item = Model[i]; 9 |
10 |
11 | 12 | @item.ReplyEmail 13 | · 14 | 15 | #@(i + 1) · @item.CreateOn.ToString("MM-dd HH:mm") 16 | 17 | 18 | 删除 19 | 20 |
21 |
22 |

@item.ReplyContent

23 |
24 |
25 | } 26 | 43 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/Views/User/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewData["Title"] = "用户管理"; 5 | Layout = "~/Views/Shared/_AdminLayout.cshtml"; 6 | } 7 | 8 |

用户管理

9 | 10 | 11 | 12 | 13 | 16 | 19 | 22 | 25 | 28 | 31 | 34 | 37 | 40 | 41 | 42 | 43 | 44 | @foreach (var item in Model) 45 | { 46 | 47 | 50 | 53 | 56 | 59 | 62 | 65 | 68 | 71 | 74 | 76 | 77 | } 78 | 79 |
14 | @Html.DisplayNameFor(model => model.Avatar) 15 | 17 | @Html.DisplayNameFor(model => model.UserName) 18 | 20 | @Html.DisplayNameFor(model => model.Email) 21 | 23 | @Html.DisplayNameFor(model => model.TopicCount) 24 | 26 | @Html.DisplayNameFor(model => model.TopicReplyCount) 27 | 29 | @Html.DisplayNameFor(model => model.Url) 30 | 32 | @Html.DisplayNameFor(model => model.GitHub) 33 | 35 | @Html.DisplayNameFor(model => model.CreateOn) 36 | 38 | @Html.DisplayNameFor(model => model.LastTime) 39 |
48 | @item.Avatar 49 | 51 | @item.UserName 52 | 54 | @item.Email 55 | 57 | @item.TopicCount 58 | 60 | @item.TopicReplyCount 61 | 63 | @item.Url 64 | 66 | @item.GitHub 67 | 69 | @item.CreateOn 70 | 72 | @item.LastTime 73 | 75 |
80 | @await Html.PartialAsync("_PagerPartial", ViewData) 81 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using NetCoreBBS 2 | @using NetCoreBBS.Entities 3 | @using NetCoreBBS.ViewModels 4 | @using Microsoft.AspNetCore.Identity 5 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 6 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Areas/Admin/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "/Views/Shared/_AdminLayout.cshtml"; 3 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Authorization; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.AspNetCore.Identity; 6 | using NetCoreBBS.Entities; 7 | using NetCoreBBS.ViewModels; 8 | using Microsoft.Extensions.Logging; 9 | using System.Security.Claims; 10 | 11 | // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 12 | 13 | namespace NetCoreBBS.Controllers 14 | { 15 | public class AccountController : Controller 16 | { 17 | private readonly ILogger _logger; 18 | 19 | public AccountController( 20 | UserManager userManager, 21 | SignInManager signInManager, 22 | ILogger logger) 23 | { 24 | UserManager = userManager; 25 | SignInManager = signInManager; 26 | _logger = logger; 27 | } 28 | 29 | public UserManager UserManager { get; } 30 | 31 | public SignInManager SignInManager { get; } 32 | 33 | // 34 | // GET: /Account/Login 35 | public IActionResult Login(string returnUrl = null) 36 | { 37 | ViewBag.ReturnUrl = returnUrl; 38 | return View(); 39 | } 40 | 41 | // 42 | // POST: /Account/Login 43 | [HttpPost] 44 | [ValidateAntiForgeryToken] 45 | public async Task Login(LoginViewModel model, string returnUrl = null) 46 | { 47 | if (!ModelState.IsValid) 48 | { 49 | return View(model); 50 | } 51 | 52 | var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false); 53 | if (result.Succeeded) 54 | { 55 | _logger.LogInformation("Logged in {userName}.", model.UserName); 56 | return RedirectToLocal(returnUrl); 57 | } 58 | else 59 | { 60 | _logger.LogWarning("Failed to log in {userName}.", model.UserName); 61 | ModelState.AddModelError("", "用户名或密码错误"); 62 | return View(model); 63 | } 64 | } 65 | 66 | // 67 | // GET: /Account/Register 68 | public IActionResult Register() 69 | { 70 | return View(); 71 | } 72 | 73 | // 74 | // POST: /Account/Register 75 | [HttpPost] 76 | [ValidateAntiForgeryToken] 77 | public async Task Register(RegisterViewModel model) 78 | { 79 | if (ModelState.IsValid) 80 | { 81 | var user = new User { UserName = model.UserName, Email = model.Email,CreateOn=DateTime.Now,LastTime=DateTime.Now }; 82 | var result = await UserManager.CreateAsync(user, model.Password); 83 | if (result.Succeeded) 84 | { 85 | _logger.LogInformation("User {userName} was created.", model.Email); 86 | string code = await UserManager.GenerateEmailConfirmationTokenAsync(user); 87 | var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme); 88 | await MessageServices.SendEmailAsync(model.Email, "Confirm your account", 89 | "Please confirm your account by clicking this link: link"); 90 | if (string.Equals(user.UserName, "admin", StringComparison.OrdinalIgnoreCase)) 91 | { 92 | await UserManager.AddClaimAsync(user, new Claim("Admin", "Allowed")); 93 | } 94 | return RedirectToAction("Login"); 95 | } 96 | AddErrors(result); 97 | } 98 | return View(model); 99 | } 100 | 101 | // 102 | // GET: /Account/ForgotPassword 103 | [AllowAnonymous] 104 | public ActionResult ForgotPassword() 105 | { 106 | return View(); 107 | } 108 | 109 | // 110 | // POST: /Account/LogOff 111 | [HttpPost] 112 | [ValidateAntiForgeryToken] 113 | public async Task LogOff() 114 | { 115 | var userName = HttpContext.User.Identity.Name; 116 | 117 | await SignInManager.SignOutAsync(); 118 | 119 | _logger.LogInformation("{userName} logged out.", userName); 120 | return RedirectToAction("Index", "Home"); 121 | } 122 | 123 | public ActionResult AccessDenied() 124 | { 125 | return RedirectToAction("Index", "Home"); 126 | } 127 | 128 | #region 辅助方法 129 | 130 | private void AddErrors(IdentityResult result) 131 | { 132 | foreach (var error in result.Errors) 133 | { 134 | ModelState.AddModelError("", error.Description); 135 | _logger.LogWarning("Error in creating user: {error}", error.Description); 136 | } 137 | } 138 | 139 | private Task GetCurrentUserAsync() 140 | { 141 | return UserManager.GetUserAsync(HttpContext.User); 142 | } 143 | 144 | private ActionResult RedirectToLocal(string returnUrl) 145 | { 146 | if (Url.IsLocalUrl(returnUrl)) 147 | { 148 | return Redirect(returnUrl); 149 | } 150 | else 151 | { 152 | return RedirectToAction("Index", "Home"); 153 | } 154 | } 155 | 156 | #endregion 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Microsoft.AspNetCore.Mvc; 4 | using NetCoreBBS.Infrastructure; 5 | using Microsoft.AspNetCore.Identity; 6 | using System.Threading.Tasks; 7 | using NetCoreBBS.ViewModels; 8 | using Microsoft.AspNetCore.Mvc.Rendering; 9 | using NetCoreBBS.Entities; 10 | using NetCoreBBS.Interfaces; 11 | 12 | namespace NetCoreBBS.Controllers 13 | { 14 | public class HomeController : Controller 15 | { 16 | private ITopicRepository _topic; 17 | private IRepository _node; 18 | public UserManager UserManager { get; } 19 | public HomeController(ITopicRepository topic, IRepository node, UserManager userManager) 20 | { 21 | _topic = topic; 22 | _node = node; 23 | UserManager = userManager; 24 | } 25 | public IActionResult Index([FromServices]IUserServices userServices) 26 | { 27 | var pagesize = 20; 28 | var pageindex = 1; 29 | Page result = null ; 30 | if (!string.IsNullOrEmpty(Request.Query["page"])) 31 | pageindex = Convert.ToInt32(Request.Query["page"]); 32 | if (!string.IsNullOrEmpty(Request.Query["s"])) 33 | result = _topic.PageList(r => r.Title.Contains(Request.Query["s"]), pagesize, pageindex); 34 | else 35 | result = _topic.PageList(pagesize, pageindex); 36 | ViewBag.Topics = result.List.Select(r=>new TopicViewModel 37 | { 38 | Id = r.Id, 39 | NodeId = r.Node.Id, 40 | NodeName = r.Node.Name, 41 | UserName = r.User.UserName, 42 | Avatar=r.User.Avatar, 43 | Title = r.Title, 44 | Top = r.Top, 45 | Type=r.Type, 46 | ReplyCount = r.ReplyCount, 47 | LastReplyTime = r.LastReplyTime, 48 | CreateOn = r.CreateOn 49 | }).ToList(); 50 | ViewBag.PageIndex = pageindex; 51 | ViewBag.PageCount = result.GetPageCount(); 52 | ViewBag.User = userServices.User.Result; 53 | var nodes = _node.List().ToList(); 54 | ViewBag.Nodes = nodes; 55 | ViewBag.NodeListItem = nodes.Where(r => r.ParentId != 0).Select(r => new SelectListItem { Value = r.Id.ToString(), Text = r.Name }); 56 | return View(); 57 | } 58 | 59 | [HttpPost] 60 | [ValidateAntiForgeryToken] 61 | public IActionResult Index(Topic topic) 62 | { 63 | if (ModelState.IsValid) 64 | { 65 | topic.CreateOn = DateTime.Now; 66 | topic.Type = TopicType.Normal; 67 | _topic.Add(topic); 68 | } 69 | return RedirectToAction("Index"); 70 | } 71 | 72 | public IActionResult About() 73 | { 74 | ViewData["Message"] = ".NET Core 版轻论坛"; 75 | return View(); 76 | } 77 | 78 | public IActionResult Error() 79 | { 80 | return View(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Controllers/TopicController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using NetCoreBBS.Infrastructure; 7 | using NetCoreBBS.Entities; 8 | using NetCoreBBS.Interfaces; 9 | using NetCoreBBS.ViewModels; 10 | 11 | // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 12 | 13 | namespace NetCoreBBS.Controllers 14 | { 15 | public class TopicController : Controller 16 | { 17 | private ITopicRepository _topic; 18 | private IRepository _node; 19 | private ITopicReplyRepository _reply; 20 | public TopicController(ITopicRepository topic, IRepository node, ITopicReplyRepository reply) 21 | { 22 | _topic = topic; 23 | _node = node; 24 | _reply = reply; 25 | } 26 | // GET: /Topic/1 27 | [Route("/Topic/{id}")] 28 | public IActionResult Index(int id) 29 | { 30 | if (id <= 0) return Redirect("/"); 31 | var topic = _topic.GetById(id); 32 | if (topic == null) return Redirect("/"); 33 | var replys = _reply.List(r => r.TopicId == id).ToList(); 34 | topic.ViewCount += 1; 35 | _topic.Edit(topic); 36 | ViewBag.Replys = replys; 37 | return View(topic); 38 | } 39 | [HttpPost] 40 | [ValidateAntiForgeryToken] 41 | [Route("/Topic/{id}")] 42 | public IActionResult Index([Bind("TopicId,ReplyUserId,ReplyEmail,ReplyContent")]TopicReply reply) 43 | { 44 | if (ModelState.IsValid&&!string.IsNullOrEmpty(reply.ReplyContent)) 45 | { 46 | reply.CreateOn = DateTime.Now; 47 | _reply.Add(reply); 48 | var topic = _topic.GetById(reply.TopicId); 49 | topic.LastReplyUserId = reply.ReplyUserId; 50 | topic.LastReplyTime = reply.CreateOn; 51 | topic.ReplyCount += 1; 52 | _topic.Edit(topic); 53 | } 54 | return RedirectToAction("Index", "Topic", new { Id = reply.TopicId }); 55 | } 56 | 57 | [Route("/Topic/Node/{name}")] 58 | public IActionResult Node(string name) 59 | { 60 | if (string.IsNullOrEmpty(name)) return Redirect("/"); 61 | var node = _node.List(r => r.NodeName == name).FirstOrDefault(); 62 | if (node == null) 63 | node= _node.GetById(Convert.ToInt32(name)); 64 | if (node == null) return Redirect("/"); 65 | var pagesize = 20; 66 | var pageindex = 1; 67 | Page result; 68 | if (!string.IsNullOrEmpty(Request.Query["page"])) 69 | pageindex = Convert.ToInt32(Request.Query["page"]); 70 | if (!string.IsNullOrEmpty(Request.Query["s"])) 71 | result = _topic.PageList(r => r.NodeId == node.Id && r.Title.Contains(Request.Query["s"]),pagesize,pageindex); 72 | else 73 | result = _topic.PageList(r => r.NodeId == node.Id, pagesize, pageindex); 74 | ViewBag.Topics = result.List.Select(r => new TopicViewModel 75 | { 76 | Id = r.Id, 77 | NodeId = r.Node.Id, 78 | NodeName = r.Node.Name, 79 | UserName = r.User.UserName, 80 | Avatar=r.User.Avatar, 81 | Title = r.Title, 82 | Top = r.Top, 83 | Type = r.Type, 84 | ReplyCount = r.ReplyCount, 85 | LastReplyTime = r.LastReplyTime, 86 | CreateOn = r.CreateOn 87 | }).ToList(); 88 | ViewBag.PageIndex = pageindex; 89 | ViewBag.PageCount = result.GetPageCount(); 90 | ViewBag.Node = node; 91 | ViewBag.Count = result.Total; 92 | return View(); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Controllers/UserController.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linezero/NETCoreBBS/71ac2c572f8d25d79bad0fdfd695d7d6d7e2bcf6/src/NetCoreBBS/Controllers/UserController.cs -------------------------------------------------------------------------------- /src/NetCoreBBS/MessageServices.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace NetCoreBBS 4 | { 5 | public static class MessageServices 6 | { 7 | public static Task SendEmailAsync(string email, string subject, string message) 8 | { 9 | // Plug in your email service 10 | return Task.FromResult(0); 11 | } 12 | 13 | public static Task SendSmsAsync(string number, string message) 14 | { 15 | // Plug in your sms service 16 | return Task.FromResult(0); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/Middleware/RequestIPMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Http; 7 | using NLog; 8 | 9 | namespace NetCoreBBS.Middleware 10 | { 11 | public class RequestIPMiddleware 12 | { 13 | private readonly RequestDelegate _next; 14 | private readonly ILogger _logger; 15 | 16 | public RequestIPMiddleware(RequestDelegate next) 17 | { 18 | _next = next; 19 | _logger = LogManager.GetCurrentClassLogger(); 20 | } 21 | 22 | public async Task Invoke(HttpContext httpContext) 23 | { 24 | var url = httpContext.Request.Path.ToString(); 25 | if (!(url.Contains("/css") || url.Contains("/js") || url.Contains("/images") || url.Contains("/lib"))) 26 | { 27 | _logger.Info($"Url:{url} IP:{httpContext.Connection.RemoteIpAddress.ToString()} 时间:{DateTime.Now}"); 28 | } 29 | await _next(httpContext); 30 | } 31 | } 32 | 33 | 34 | public static class RequestIPMiddlewareExtensions 35 | { 36 | public static IApplicationBuilder UseRequestIPMiddleware(this IApplicationBuilder builder) 37 | { 38 | return builder.UseMiddleware(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/NetCoreBBS/NetCoreBBS.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | NetCoreBBS 6 | NetCoreBBS 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | PreserveNewest 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | using NLog.Web; 10 | 11 | namespace NetCoreBBS 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | // NLog: setup the logger first to catch all errors 18 | var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); 19 | try 20 | { 21 | logger.Debug("init main"); 22 | BuildWebHost(args).Run(); 23 | } 24 | catch (Exception ex) 25 | { 26 | //NLog: catch setup errors 27 | logger.Error(ex, "Stopped program because of exception"); 28 | throw; 29 | } 30 | finally 31 | { 32 | // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) 33 | NLog.LogManager.Shutdown(); 34 | } 35 | } 36 | 37 | public static IWebHost BuildWebHost(string[] args) => 38 | WebHost.CreateDefaultBuilder(args) 39 | .UseStartup() 40 | .UseUrls("http://*:80") 41 | .ConfigureLogging(logging => 42 | { 43 | logging.ClearProviders(); 44 | logging.SetMinimumLevel(LogLevel.Trace); 45 | }) 46 | .UseNLog() // NLog: setup NLog for Dependency injection 47 | .Build(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54956/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "NetCoreBBS": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "launchUrl": "http://localhost", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Logging; 10 | using NetCoreBBS.Infrastructure; 11 | using Microsoft.EntityFrameworkCore; 12 | using NLog.Extensions.Logging; 13 | using NetCoreBBS.Middleware; 14 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 15 | using Microsoft.AspNetCore.Identity; 16 | using Microsoft.Extensions.WebEncoders; 17 | using System.Text.Unicode; 18 | using System.Text.Encodings.Web; 19 | using NetCoreBBS.Entities; 20 | using NetCoreBBS.Infrastructure.Repositorys; 21 | using NetCoreBBS.Interfaces; 22 | 23 | namespace NetCoreBBS 24 | { 25 | public class Startup 26 | { 27 | public Startup(IConfiguration configuration) 28 | { 29 | Configuration = configuration; 30 | } 31 | 32 | public IConfiguration Configuration { get; } 33 | 34 | // This method gets called by the runtime. Use this method to add services to the container. 35 | public void ConfigureServices(IServiceCollection services) 36 | { 37 | services.AddDbContext(options => options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); 38 | services.AddIdentity(options => 39 | { 40 | options.Password = new PasswordOptions() { 41 | RequireNonAlphanumeric = false, 42 | RequireUppercase=false 43 | }; 44 | }).AddEntityFrameworkStores().AddDefaultTokenProviders(); 45 | // Add framework services. 46 | services.AddMvc(); 47 | services.AddScoped, Repository>(); 48 | services.AddScoped(); 49 | services.AddScoped(); 50 | services.AddScoped(); 51 | services.AddScoped(); 52 | services.AddMemoryCache(); 53 | services.AddAuthorization(options => 54 | { 55 | options.AddPolicy( 56 | "Admin", 57 | authBuilder => 58 | { 59 | authBuilder.RequireClaim("Admin", "Allowed"); 60 | }); 61 | }); 62 | //文字被编码 https://github.com/aspnet/HttpAbstractions/issues/315 63 | services.Configure(options => 64 | { 65 | options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All); 66 | }); 67 | } 68 | 69 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 70 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) 71 | { 72 | app.UseRequestIPMiddleware(); 73 | 74 | InitializeNetCoreBBSDatabase(app.ApplicationServices); 75 | app.UseDeveloperExceptionPage(); 76 | 77 | app.UseStatusCodePages(); 78 | app.UseStaticFiles(); 79 | app.UseRouting(); 80 | app.UseAuthentication(); 81 | app.UseAuthorization(); 82 | 83 | app.UseEndpoints(endpoint => 84 | { 85 | endpoint.MapControllerRoute(name: "areaRoute", 86 | pattern: "{area:exists}/{controller}/{action}", 87 | defaults: new { action = "Index" }); 88 | endpoint.MapControllerRoute(name: "default", 89 | pattern: "{controller=Home}/{action=Index}/{id?}"); 90 | }); 91 | } 92 | 93 | private void InitializeNetCoreBBSDatabase(IServiceProvider serviceProvider) 94 | { 95 | using (var serviceScope = serviceProvider.GetRequiredService().CreateScope()) 96 | { 97 | var db = serviceScope.ServiceProvider.GetService(); 98 | db.Database.Migrate(); 99 | if (db.TopicNodes.Count() == 0) 100 | { 101 | db.TopicNodes.AddRange(GetTopicNodes()); 102 | db.SaveChanges(); 103 | } 104 | } 105 | } 106 | 107 | IEnumerable GetTopicNodes() 108 | { 109 | return new List() 110 | { 111 | new TopicNode() { Name=".NET Core", NodeName="", ParentId=0, Order=1, CreateOn=DateTime.Now, }, 112 | new TopicNode() { Name=".NET Core", NodeName="netcore", ParentId=1, Order=1, CreateOn=DateTime.Now, }, 113 | new TopicNode() { Name="ASP.NET Core", NodeName="aspnetcore", ParentId=1, Order=1, CreateOn=DateTime.Now, } 114 | }; 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/NetCoreBBS/UserServices.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using NetCoreBBS.Entities; 3 | using Microsoft.AspNetCore.Identity; 4 | using Microsoft.AspNetCore.Http; 5 | 6 | namespace NetCoreBBS 7 | { 8 | public interface IUserServices 9 | { 10 | Task User { get; } 11 | } 12 | public class UserServices : IUserServices 13 | { 14 | public UserManager UserManager { get; } 15 | private IHttpContextAccessor Context; 16 | public UserServices(UserManager userManager, IHttpContextAccessor context) 17 | { 18 | UserManager = userManager; 19 | Context = context; 20 | } 21 | public Task User 22 | { 23 | get 24 | { 25 | return UserManager.GetUserAsync(Context.HttpContext.User); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/NetCoreBBS/ViewComponents/Statistics.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Caching.Memory; 3 | using NetCoreBBS.Infrastructure; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace NetCoreBBS.ViewComponents 10 | { 11 | public class Statistics : ViewComponent 12 | { 13 | private readonly DataContext db; 14 | private IMemoryCache _memoryCache; 15 | private string cachekey = "statistics"; 16 | 17 | public Statistics(DataContext context, IMemoryCache memoryCache) 18 | { 19 | db = context; 20 | _memoryCache = memoryCache; 21 | } 22 | 23 | public IViewComponentResult Invoke() 24 | { 25 | var allstatistics = new Tuple(0, 0, 0); 26 | if (!_memoryCache.TryGetValue(cachekey, out allstatistics)) 27 | { 28 | var usercount = db.Users.Count(); 29 | var topiccount = db.Topics.Count(); 30 | var replycount = db.TopicReplys.Count(); 31 | allstatistics = new Tuple(usercount, topiccount, replycount); 32 | _memoryCache.Set(cachekey, allstatistics, TimeSpan.FromMinutes(1)); 33 | } 34 | return View(allstatistics); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/NetCoreBBS/ViewComponents/TopicRankList.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.Extensions.Caching.Memory; 7 | using NetCoreBBS.Infrastructure; 8 | using NetCoreBBS.Entities; 9 | 10 | namespace NetCoreBBS.ViewComponents 11 | { 12 | public class TopicRankList: ViewComponent 13 | { 14 | private readonly DataContext db; 15 | private IMemoryCache _memoryCache; 16 | private string cachekey = "topicrank"; 17 | 18 | public TopicRankList(DataContext context, IMemoryCache memoryCache) 19 | { 20 | db = context; 21 | _memoryCache = memoryCache; 22 | } 23 | 24 | public IViewComponentResult Invoke(int days) 25 | { 26 | var items = new List(); 27 | if (!_memoryCache.TryGetValue(cachekey, out items)) 28 | { 29 | items = GetRankTopics(10, days); 30 | _memoryCache.Set(cachekey, items, TimeSpan.FromMinutes(10)); 31 | } 32 | return View(items); 33 | } 34 | /// 35 | /// 获取主题排行 36 | /// 37 | /// 38 | /// 39 | /// 40 | private List GetRankTopics(int top,int days) 41 | { 42 | return db.Topics.Where(r=>r.CreateOn>DateTime.Now.AddDays(-days)) 43 | .OrderByDescending(r=>r.ViewCount).Take(top).ToList(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/NetCoreBBS/ViewModels/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace NetCoreBBS.ViewModels 4 | { 5 | public class LoginViewModel 6 | { 7 | [Required] 8 | [Display(Name = "用户名")] 9 | public string UserName { get; set; } 10 | 11 | [Required] 12 | [DataType(DataType.Password)] 13 | [Display(Name = "密码")] 14 | public string Password { get; set; } 15 | 16 | [Display(Name = "记住登录状态")] 17 | public bool RememberMe { get; set; } 18 | } 19 | 20 | public class RegisterViewModel 21 | { 22 | [Required] 23 | [Display(Name = "用户名")] 24 | public string UserName { get; set; } 25 | 26 | [Required] 27 | [EmailAddress] 28 | [Display(Name = "Email")] 29 | public string Email { get; set; } 30 | 31 | [Required] 32 | [StringLength(16, ErrorMessage = "{0} 必须大于 {2} 位", MinimumLength = 6)] 33 | [DataType(DataType.Password)] 34 | [Display(Name = "密码")] 35 | public string Password { get; set; } 36 | 37 | [DataType(DataType.Password)] 38 | [Display(Name = "确认密码")] 39 | [Compare("Password", ErrorMessage = "两次密码不一致")] 40 | public string ConfirmPassword { get; set; } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/ViewModels/TopicViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace NetCoreBBS.ViewModels 7 | { 8 | public class TopicViewModel 9 | { 10 | public int Id { get; set; } 11 | public int NodeId { get; set; } 12 | public string NodeName { get; set; } 13 | public string UserName { get; set; } 14 | public string Avatar { get; set; } 15 | public string Title { get; set; } 16 | public int Top { get; set; } 17 | public Entities.TopicType Type { get; set; } 18 | public int ReplyCount { get; set; } 19 | public DateTime LastReplyTime { get; set; } 20 | public DateTime CreateOn { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NetCoreBBS/ViewModels/UserViewModel.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetCoreBBS.ViewModels 8 | { 9 | public class UserViewModel 10 | { 11 | public string Email { get; set; } 12 | public IFormFile Avatar { get; set; } 13 | public string Profile { get; set; } 14 | public string Url { get; set; } 15 | public string GitHub { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Account/ForgotPassword.cshtml: -------------------------------------------------------------------------------- 1 | @* 2 | For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 3 | *@ 4 | @{ 5 | } 6 | 暂未开发 -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @model LoginViewModel 2 | 3 | @{ 4 | ViewBag.Title = "用户登录"; 5 | } 6 | 7 |
8 |
9 |
10 |
11 |

用户登录

12 |
13 |
14 |
15 | 16 |
17 | 18 | 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 | @await Html.PartialAsync("_ExternalLoginsListPartial", new { ReturnUrl = ViewBag.ReturnUrl }) 53 |
54 |
55 |
56 | @section scripts{ 57 | 58 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Account/Register.cshtml: -------------------------------------------------------------------------------- 1 | @model RegisterViewModel 2 | @{ 3 | ViewBag.Title = "用户注册"; 4 | } 5 |
6 |
7 |
8 |

注册新用户

9 |
10 |
11 |
12 | 13 |
14 | 15 | 16 |
17 |
18 |
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 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Account/_ExternalLoginsListPartial.cshtml: -------------------------------------------------------------------------------- 1 | @inject SignInManager SignInManager 2 |

用其他平台的帐号登录

3 |
4 | @{ 5 | var loginProviders = await SignInManager.GetExternalAuthenticationSchemesAsync(); 6 | if (!loginProviders.Any()) 7 | { 8 |
9 |

10 | 需要添加其他平台 11 |

12 |
13 | } 14 | else 15 | { 16 |
17 |
18 |

19 | @foreach (var p in loginProviders) 20 | { 21 | 22 | } 23 |

24 |
25 |
26 | } 27 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = ".NET Core 跨平台论坛介绍"; 3 | } 4 |

@ViewData["Title"].

5 |

@ViewData["Message"]

6 | 7 |

8 | .NET Core 开发
9 | VS Code 或者 VS 2019
10 |

论坛系统介绍:

11 | 系统开发:
12 | ASP.NET Core + EF Core Sqlite + Bootstrap
13 | 运行环境:
14 | Ubuntu 16.04 + Kestrel+Nginx

15 | 博客介绍: 16 | 17 | LineZero's Blog 18 |
19 | 服务器时间:@DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") 20 |

21 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = ".NET Core 跨平台论坛"; 3 | var list = ViewBag.Topics as List; 4 | var user = ViewBag.User as User; 5 | var nodes = ViewBag.Nodes as List; 6 | } 7 | @model Topic 8 |
9 |
10 |
11 |
12 |
13 | 查看: 14 | 默认 / 15 | 优质帖子 / 16 | 无人问津 / 17 | 最新创建 18 |
19 |
20 |
21 | @foreach (var item in list) 22 | { 23 |
24 |
25 | 96 26 |
27 |
28 | 33 |
34 | @item.NodeName   发布于 @item.CreateOn.ToString("MM-dd HH:mm") 35 | @if (item.LastReplyTime != DateTime.MinValue) 36 | { 37 | 38 | } 39 |
40 |
41 |
42 | @if (item.ReplyCount > 0) 43 | { 44 | @item.ReplyCount 45 | } 46 |
47 |
48 | } 49 | 50 |
51 | 54 |
55 |
56 | @if (user != null) 57 | { 58 |
59 |
60 | 61 |
62 | 64 |
65 |
66 |
67 | 68 |
69 | 70 |
71 |
72 |
73 | 74 |
75 | 76 |
77 |
78 |
79 | 80 | 81 |
82 | 83 |
84 |
85 |
86 | } 87 | else 88 | { 89 | 发布新话题 90 | } 91 |
92 |
93 |
讨论节点分类导航
94 |
95 |
96 | @foreach (var item in nodes.Where(r => r.ParentId == 0).OrderBy(r => r.Order)) 97 | { 98 |
99 | 100 | 101 | @foreach (var n in nodes.Where(r => r.ParentId == item.Id).OrderBy(r => r.Order)) 102 | { 103 | @n.Name 104 | } 105 | 106 |
107 | } 108 |
109 |
110 |
111 |
112 |
113 | @await Html.PartialAsync("_SidebarPartial") 114 |
115 |
-------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Shared/Components/Statistics/Default.cshtml: -------------------------------------------------------------------------------- 1 | @model Tuple 2 | 3 |
4 |
5 |

统计信息

6 |
7 |
    8 |
  • 社区会员: @Model.Item1 人
  • 9 |
  • 帖子数: @Model.Item2 个
  • 10 |
  • 回帖数: @Model.Item3 条
  • 11 |
12 |
-------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Shared/Components/TopicRankList/Default.cshtml: -------------------------------------------------------------------------------- 1 | @model List 2 | 3 |
4 |
5 |

主题排行

6 |
7 |
8 | @foreach (var item in Model) 9 | { 10 | 11 | @item.Title 12 | 13 | } 14 |
15 |
-------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Error"; 3 | } 4 | 5 |

Error.

6 |

An error occurred while processing your request.

7 | 8 |

Development Mode

9 |

10 | Swapping to Development environment will display more detailed information about the error that occurred. 11 |

12 |

13 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 14 |

15 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Shared/_AdminLayout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] -NetCoreBBS后台管理 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 40 |
41 |
42 | 50 |
51 | @RenderBody() 52 |
53 |
54 |
55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 68 | 72 | 73 | 74 | 75 | 76 | 84 | @RenderSection("scripts", required: false) 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - NetCoreBBS 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 42 |
43 | @RenderBody() 44 |
45 |
46 |

LineZero© @DateTime.Now.Year - NetCoreBBS

47 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 62 | 66 | 67 | 68 | 69 | 70 | 71 | @RenderSection("scripts", required: false) 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @inject SignInManager SignInManager 2 | @inject UserManager UserManager 3 | 4 | @if (SignInManager.IsSignedIn(User)) 5 | { 6 | 28 | } 29 | else 30 | { 31 | 36 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Shared/_PagerPartial.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | var pageindex = Convert.ToInt32(ViewBag.PageIndex); 3 | var pagecount = Convert.ToInt32(ViewBag.PageCount); 4 | pagecount = pagecount == 0 ? 1 : pagecount; 5 | pageindex = pageindex > pagecount ? pagecount : pageindex; 6 | var path = Context.Request.Path.Value; 7 | var query = string.Empty; 8 | var querys = Context.Request.Query; 9 | foreach (var item in querys) 10 | { 11 | if (!item.Key.Equals("page")) 12 | { 13 | query += $"{item.Key}={item.Value}&"; 14 | } 15 | } 16 | query = query == string.Empty ? "?" : "?" + query; 17 | path += query; 18 | var pagestart = pageindex - 2 > 0 ? pageindex - 2 : 1; 19 | var pageend = pagestart + 5 >= pagecount ? pagecount : pagestart + 5; 20 | } 21 |
    22 | 25 |
  • 1
  • 26 | @if (pagestart > 2) 27 | { 28 |
  • 29 | } 30 | @for (int i = pagestart; i < pageend; i++) 31 | { 32 | if (i > 1) 33 | { 34 |
  • 35 | } 36 | } 37 | @if (pageend < pagecount) 38 | { 39 |
  • 40 | } 41 | @if (pagecount > 1) 42 | { 43 |
  • @pagecount
  • 44 | } 45 | 48 |
-------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Shared/_SidebarPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using NetCoreBBS.ViewComponents 2 |
3 |
4 |

.NET Core 跨平台论坛介绍

5 |
6 |
7 | .NET Core 开发
8 | VS Code 或者 VS 2019
9 | 更多详细:dot.net
10 |

论坛系统介绍:

11 | 系统开发:
12 | ASP.NET Core + EF Core Sqlite + Bootstrap
13 | 运行环境:
14 | Ubuntu 16.04 + Kestrel

15 | 博客介绍: 16 | 17 | LineZero's Blog 18 |
19 | GitHub: 20 | 21 | NETCoreBBS 22 |
23 | 服务器时间:@DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") 24 |
25 |
26 | @(await Component.InvokeAsync(new { days = 30 })) 27 | @(await Component.InvokeAsync()) -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Topic/Index.cshtml: -------------------------------------------------------------------------------- 1 | @inject UserServices services 2 | @model Topic 3 | @{ 4 | ViewData["Title"] = Model.Title; 5 | var list = ViewBag.Replys as List; 6 | var user = await services.User; 7 | } 8 |
9 |
10 |
11 |
12 |
13 |

@(Model.Top == 1 ? "[置顶]" : "")@Model.Title

14 |
15 | @Model.Node.Name 16 | · 17 | @Model.User.UserName 18 | · 19 | 于 @Model.CreateOn.ToString("MM-dd HH:mm")发布 20 | · 21 | @Model.ViewCount 次阅读 22 |
23 |
24 |
25 | 26 |
27 |
28 |
29 |

@Model.Content

30 |
31 |
32 |
33 |
34 |

共收到 @list.Count 条回复:

35 |
36 |
37 | @for (int i = 0; i < list.Count; i++) 38 | { 39 | var item = list[i]; 40 |
41 |
42 | 43 | 44 | 45 |
46 |
47 |
48 | 49 | @item.ReplyUser.UserName 50 | · 51 | 52 | #@(i + 1) · @item.CreateOn.ToString("MM-dd HH:mm") 53 | 54 | 55 | 56 | 57 | 58 |
59 |
60 |

@item.ReplyContent

61 |
62 |
63 |
64 | } 65 |
66 |
67 |
68 | @if (user != null) 69 | { 70 |
71 | 72 | 73 | 74 |
75 | 76 |
77 | 78 |
79 |
80 |
81 |
82 | 83 |
84 |
85 |
86 | } 87 | else 88 | { 89 |

90 | 需要登录发表回复, 91 | 如果你还没有账号请点击这里 注册。 92 |

93 | } 94 |
95 |
96 |
97 | @await Html.PartialAsync("_SidebarPartial") 98 |
99 |
100 | @section scripts{ 101 | 107 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/Topic/Node.cshtml: -------------------------------------------------------------------------------- 1 | @inject UserServices services 2 | @{ 3 | var node = ViewBag.Node as TopicNode; 4 | ViewData["Title"] = node.Name + "-.NET Core 跨平台论坛"; 5 | var list = ViewBag.Topics as List; 6 | var user = await services.User; 7 | } 8 | @model Topic 9 | 10 |
11 |
12 |
13 |
14 |
15 |
16 | @node.Name 共有 @ViewBag.Count 个讨论主题 17 |
18 |
19 |

@node.Name 讨论区

20 |
21 |
22 |
23 |
24 | @foreach (var item in list) 25 | { 26 |
27 |
28 | 96 29 |
30 |
31 | 36 |
37 | @node.Name】发布于 @item.CreateOn.ToString("MM-dd HH:mm") 38 | @if (item.LastReplyTime != DateTime.MinValue) 39 | { 40 | 41 | } 42 |
43 |
44 |
45 | @if (item.ReplyCount > 0) 46 | { 47 | @item.ReplyCount 48 | } 49 |
50 |
51 | } 52 |
53 | 56 |
57 |
58 | @if (user != null) 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 | else 84 | { 85 |

86 | 需要登录发布新话题, 87 | 如果你还没有账号请点击这里 注册。 88 |

89 | } 90 |
91 |
92 |
93 | @await Html.PartialAsync("_SidebarPartial") 94 |
95 |
96 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/User/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model User 2 | @{ 3 | ViewData["Title"] = "Edit"; 4 | } 5 | 6 |

修改个人信息

7 | 8 |
9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 | 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 |
-------------------------------------------------------------------------------- /src/NetCoreBBS/Views/User/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model User 2 | @{ 3 | ViewData["Title"] = "个人主页"; 4 | var topics = ViewBag.Topics as List; 5 | var replys = ViewBag.Replys as List; 6 | } 7 | 8 |
9 |
10 | 49 |
50 |
51 | 56 |
57 |
58 |
59 |
    60 | @foreach (var item in topics) 61 | { 62 |
  • 63 |
    64 | @item.Node.Name 65 | @item.Title 66 |
    67 |
    68 | @item.ReplyCount 条回复 69 |
    70 |
  • 71 | } 72 |
73 |
74 |
75 |
76 |
77 |
    78 | @foreach (var item in replys) 79 | { 80 |
  • 81 |
    82 | @item.ReplyContent 83 | at @(DateTime.Now.Subtract(item.CreateOn).Days) 天前 84 |
    85 |
  • 86 | } 87 |
88 |
89 |
90 |
91 |
92 | @Model.Profile 93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using NetCoreBBS 2 | @using NetCoreBBS.Entities 3 | @using NetCoreBBS.ViewModels 4 | @using Microsoft.AspNetCore.Identity 5 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 6 | -------------------------------------------------------------------------------- /src/NetCoreBBS/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/NetCoreBBS/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Filename=netcorebbs.db" 4 | }, 5 | "Logging": { 6 | "IncludeScopes": false, 7 | "LogLevel": { 8 | "Default": "Debug", 9 | "System": "Information", 10 | "Microsoft": "Information" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NetCoreBBS/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asp.net", 3 | "private": true, 4 | "dependencies": { 5 | "bootstrap": "3.3.6", 6 | "jquery": "2.2.0", 7 | "jquery-validation": "1.14.0", 8 | "jquery-validation-unobtrusive": "3.2.6", 9 | "bootstrap-markdown": "2.10.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/NetCoreBBS/bundleconfig.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "outputFileName": "wwwroot/css/site.min.css", 4 | "inputFiles": [ 5 | "wwwroot/css/site.css" 6 | ] 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /src/NetCoreBBS/nlog.config: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/_references.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | /// 8 | /// 9 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Base structure 3 | */ 4 | 5 | /* Move down content because we have a fixed navbar that is 50px tall */ 6 | body { 7 | padding-top: 50px; 8 | } 9 | 10 | 11 | /* 12 | * Global add-ons 13 | */ 14 | 15 | .sub-header { 16 | padding-bottom: 10px; 17 | border-bottom: 1px solid #eee; 18 | } 19 | 20 | /* 21 | * Top navigation 22 | * Hide default border to remove 1px line. 23 | */ 24 | .navbar-fixed-top { 25 | border: 0; 26 | } 27 | 28 | /* 29 | * Sidebar 30 | */ 31 | 32 | /* Hide for mobile, show later */ 33 | .sidebar { 34 | display: none; 35 | } 36 | @media (min-width: 768px) { 37 | .sidebar { 38 | position: fixed; 39 | top: 51px; 40 | bottom: 0; 41 | left: 0; 42 | z-index: 1000; 43 | display: block; 44 | padding: 20px; 45 | overflow-x: hidden; 46 | overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ 47 | background-color: #f5f5f5; 48 | border-right: 1px solid #eee; 49 | } 50 | } 51 | 52 | /* Sidebar navigation */ 53 | .nav-sidebar { 54 | margin-right: -21px; /* 20px padding + 1px border */ 55 | margin-bottom: 20px; 56 | margin-left: -20px; 57 | } 58 | .nav-sidebar > li > a { 59 | padding-right: 20px; 60 | padding-left: 20px; 61 | } 62 | .nav-sidebar > .active > a, 63 | .nav-sidebar > .active > a:hover, 64 | .nav-sidebar > .active > a:focus { 65 | color: #fff; 66 | background-color: #428bca; 67 | } 68 | 69 | 70 | /* 71 | * Main content 72 | */ 73 | 74 | .main { 75 | padding: 20px; 76 | } 77 | @media (min-width: 768px) { 78 | .main { 79 | padding-right: 40px; 80 | padding-left: 40px; 81 | } 82 | } 83 | .main .page-header { 84 | margin-top: 0; 85 | } 86 | 87 | 88 | /* 89 | * Placeholder dashboard ideas 90 | */ 91 | 92 | .placeholders { 93 | margin-bottom: 30px; 94 | text-align: center; 95 | } 96 | .placeholders h4 { 97 | margin-bottom: 0; 98 | } 99 | .placeholder { 100 | margin-bottom: 20px; 101 | } 102 | .placeholder img { 103 | display: inline-block; 104 | border-radius: 50%; 105 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | font-family:"微软雅黑",'Microsoft YaHei'; 5 | background:#e9eaed; 6 | } 7 | 8 | /* Wrapping element */ 9 | /* Set some basic padding to keep content from hitting the edges */ 10 | .body-content { 11 | padding-left: 15px; 12 | padding-right: 15px; 13 | } 14 | 15 | /* Carousel */ 16 | .carousel-caption p { 17 | font-size: 20px; 18 | line-height: 1.4; 19 | } 20 | /* Hide/rearrange for smaller screens */ 21 | @media screen and (max-width: 767px) { 22 | /* Hide captions */ 23 | .carousel-caption { 24 | display: none 25 | } 26 | } 27 | .navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav > li > a{color:#333;} 28 | .navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus.navbar-inverse .navbar-nav > li > a:hover{color:#333;} 29 | .navbar-inverse .navbar-nav > li > a:hover, 30 | .navbar-inverse .navbar-nav > li > a:focus { 31 | color:#333; 32 | background-color: transparent; 33 | } 34 | .navbar-inverse{background-color:#fff;box-shadow:0 1px 1px rgba(0,0,0,0.11);border:0px;} 35 | .topics{margin-top:20px;} 36 | .topics .panel-body{padding:0px 10px;} 37 | .topic{min-height:68px;border-bottom:1px solid #F0F0F0;padding:10px 15px;} 38 | .topic .count{width:100px;padding-top:15px;text-align:center;} 39 | .topic .count a{min-width:32px;line-height:11px;padding:3px 8px;background-color:#337ab7;color:#fff;border-radius:60px;text-decoration:none;display:inline-block;} 40 | .avatar{float:left;} 41 | .avatar-48 { 42 | height:48px; 43 | width:48px; 44 | max-width:48px; 45 | border-radius:120px; 46 | } 47 | .title{font-size:18px;margin-bottom:0px;margin-top:0px;} 48 | .title a{line-height:28px;} 49 | .info{color:#ABA8A6;margin-bottom:0px;margin-top:0px;font-size:13px;} 50 | .node-list .node{margin-bottom:10px;margin-top:0px;} 51 | .node-list .node .media-left{min-width:130px;font-weight:normal;text-align:right;color:#aaa;float:left;} 52 | .node-list .node .name {margin-bottom:10px;width:100px;display:block;float:left;text-align:left;} 53 | #sections .panel-body{padding:15px;} 54 | .topic-detail{margin-bottom:15px;} 55 | .topic-detail h1{font-size:24px;} 56 | .topic-detail .avatar{float:right;} 57 | .items.panel-body{padding:0px 15px;} 58 | .reply:last-child{border-bottom:0px;} 59 | .reply{border-bottom:1px solid #eee;} 60 | .reply{margin:0px -15px;padding:15px 15px;position:relative;padding-left:74px;} 61 | .reply .avatar{position:absolute;top:15px;left:15px;} 62 | .reply .infos{min-height:48px;} 63 | .reply .info{margin-bottom:6px;} 64 | .reply .markdown{position:relative;line-height:1.8em;text-overflow:ellipsis;word-wrap:break-word;} 65 | .panel-footer{padding:6px 15px;} 66 | .pagination{margin:0px;} 67 | img { 68 | max-width:100%;height:auto; 69 | } 70 | .avatar-96 { 71 | height: 96px; 72 | width: 96px; 73 | border-radius: 120px; 74 | } 75 | 76 | .recent-topics ul li .title, 77 | .recent-replies ul li .title { 78 | font-size: 14px; 79 | } 80 | 81 | .recent-topics ul li .info { 82 | font-size: 12px; 83 | } 84 | 85 | .recent-topics ul li .node { 86 | color: #777; 87 | margin-right: 3px; 88 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/images/96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linezero/NETCoreBBS/71ac2c572f8d25d79bad0fdfd695d7d6d7e2bcf6/src/NetCoreBBS/wwwroot/images/96.png -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/js/to-markdown.js: -------------------------------------------------------------------------------- 1 | /* 2 | * to-markdown - an HTML to Markdown converter 3 | * 4 | * Copyright 2011, Dom Christie 5 | * Licenced under the MIT licence 6 | * 7 | */ 8 | 9 | var toMarkdown = function(string) { 10 | 11 | var ELEMENTS = [ 12 | { 13 | patterns: 'p', 14 | replacement: function(str, attrs, innerHTML) { 15 | return innerHTML ? '\n\n' + innerHTML + '\n' : ''; 16 | } 17 | }, 18 | { 19 | patterns: 'br', 20 | type: 'void', 21 | replacement: '\n' 22 | }, 23 | { 24 | patterns: 'h([1-6])', 25 | replacement: function(str, hLevel, attrs, innerHTML) { 26 | var hPrefix = ''; 27 | for(var i = 0; i < hLevel; i++) { 28 | hPrefix += '#'; 29 | } 30 | return '\n\n' + hPrefix + ' ' + innerHTML + '\n'; 31 | } 32 | }, 33 | { 34 | patterns: 'hr', 35 | type: 'void', 36 | replacement: '\n\n* * *\n' 37 | }, 38 | { 39 | patterns: 'a', 40 | replacement: function(str, attrs, innerHTML) { 41 | var href = attrs.match(attrRegExp('href')), 42 | title = attrs.match(attrRegExp('title')); 43 | return href ? '[' + innerHTML + ']' + '(' + href[1] + (title && title[1] ? ' "' + title[1] + '"' : '') + ')' : str; 44 | } 45 | }, 46 | { 47 | patterns: ['b', 'strong'], 48 | replacement: function(str, attrs, innerHTML) { 49 | return innerHTML ? '**' + innerHTML + '**' : ''; 50 | } 51 | }, 52 | { 53 | patterns: ['i', 'em'], 54 | replacement: function(str, attrs, innerHTML) { 55 | return innerHTML ? '_' + innerHTML + '_' : ''; 56 | } 57 | }, 58 | { 59 | patterns: 'code', 60 | replacement: function(str, attrs, innerHTML) { 61 | return innerHTML ? '`' + innerHTML + '`' : ''; 62 | } 63 | }, 64 | { 65 | patterns: 'img', 66 | type: 'void', 67 | replacement: function(str, attrs, innerHTML) { 68 | var src = attrs.match(attrRegExp('src')), 69 | alt = attrs.match(attrRegExp('alt')), 70 | title = attrs.match(attrRegExp('title')); 71 | return '![' + (alt && alt[1] ? alt[1] : '') + ']' + '(' + src[1] + (title && title[1] ? ' "' + title[1] + '"' : '') + ')'; 72 | } 73 | } 74 | ]; 75 | 76 | for(var i = 0, len = ELEMENTS.length; i < len; i++) { 77 | if(typeof ELEMENTS[i].patterns === 'string') { 78 | string = replaceEls(string, { tag: ELEMENTS[i].patterns, replacement: ELEMENTS[i].replacement, type: ELEMENTS[i].type }); 79 | } 80 | else { 81 | for(var j = 0, pLen = ELEMENTS[i].patterns.length; j < pLen; j++) { 82 | string = replaceEls(string, { tag: ELEMENTS[i].patterns[j], replacement: ELEMENTS[i].replacement, type: ELEMENTS[i].type }); 83 | } 84 | } 85 | } 86 | 87 | function replaceEls(html, elProperties) { 88 | var pattern = elProperties.type === 'void' ? '<' + elProperties.tag + '\\b([^>]*)\\/?>' : '<' + elProperties.tag + '\\b([^>]*)>([\\s\\S]*?)<\\/' + elProperties.tag + '>', 89 | regex = new RegExp(pattern, 'gi'), 90 | markdown = ''; 91 | if(typeof elProperties.replacement === 'string') { 92 | markdown = html.replace(regex, elProperties.replacement); 93 | } 94 | else { 95 | markdown = html.replace(regex, function(str, p1, p2, p3) { 96 | return elProperties.replacement.call(this, str, p1, p2, p3); 97 | }); 98 | } 99 | return markdown; 100 | } 101 | 102 | function attrRegExp(attr) { 103 | return new RegExp(attr + '\\s*=\\s*["\']?([^"\']*)["\']?', 'i'); 104 | } 105 | 106 | // Pre code blocks 107 | 108 | string = string.replace(/]*>`([\s\S]*)`<\/pre>/gi, function(str, innerHTML) { 109 | innerHTML = innerHTML.replace(/^\t+/g, ' '); // convert tabs to spaces (you know it makes sense) 110 | innerHTML = innerHTML.replace(/\n/g, '\n '); 111 | return '\n\n ' + innerHTML + '\n'; 112 | }); 113 | 114 | // Lists 115 | 116 | // Escape numbers that could trigger an ol 117 | // If there are more than three spaces before the code, it would be in a pre tag 118 | // Make sure we are escaping the period not matching any character 119 | string = string.replace(/^(\s{0,3}\d+)\. /g, '$1\\. '); 120 | 121 | // Converts lists that have no child lists (of same type) first, then works it's way up 122 | var noChildrenRegex = /<(ul|ol)\b[^>]*>(?:(?!/gi; 123 | while(string.match(noChildrenRegex)) { 124 | string = string.replace(noChildrenRegex, function(str) { 125 | return replaceLists(str); 126 | }); 127 | } 128 | 129 | function replaceLists(html) { 130 | 131 | html = html.replace(/<(ul|ol)\b[^>]*>([\s\S]*?)<\/\1>/gi, function(str, listType, innerHTML) { 132 | var lis = innerHTML.split(''); 133 | lis.splice(lis.length - 1, 1); 134 | 135 | for(i = 0, len = lis.length; i < len; i++) { 136 | if(lis[i]) { 137 | var prefix = (listType === 'ol') ? (i + 1) + ". " : "* "; 138 | lis[i] = lis[i].replace(/\s*]*>([\s\S]*)/i, function(str, innerHTML) { 139 | 140 | innerHTML = innerHTML.replace(/^\s+/, ''); 141 | innerHTML = innerHTML.replace(/\n\n/g, '\n\n '); 142 | // indent nested lists 143 | innerHTML = innerHTML.replace(/\n([ ]*)+(\*|\d+\.) /g, '\n$1 $2 '); 144 | return prefix + innerHTML; 145 | }); 146 | } 147 | } 148 | return lis.join('\n'); 149 | }); 150 | return '\n\n' + html.replace(/[ \t]+\n|\s+$/g, ''); 151 | } 152 | 153 | // Blockquotes 154 | var deepest = /]*>((?:(?!/gi; 155 | while(string.match(deepest)) { 156 | string = string.replace(deepest, function(str) { 157 | return replaceBlockquotes(str); 158 | }); 159 | } 160 | 161 | function replaceBlockquotes(html) { 162 | html = html.replace(/]*>([\s\S]*?)<\/blockquote>/gi, function(str, inner) { 163 | inner = inner.replace(/^\s+|\s+$/g, ''); 164 | inner = cleanUp(inner); 165 | inner = inner.replace(/^/gm, '> '); 166 | inner = inner.replace(/^(>([ \t]{2,}>)+)/gm, '> >'); 167 | return inner; 168 | }); 169 | return html; 170 | } 171 | 172 | function cleanUp(string) { 173 | string = string.replace(/^[\t\r\n]+|[\t\r\n]+$/g, ''); // trim leading/trailing whitespace 174 | string = string.replace(/\n\s+\n/g, '\n\n'); 175 | string = string.replace(/\n{3,}/g, '\n\n'); // limit consecutive linebreaks to 2 176 | return string; 177 | } 178 | 179 | return cleanUp(string); 180 | }; 181 | 182 | if (typeof exports === 'object') { 183 | exports.toMarkdown = toMarkdown; 184 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-markdown", 3 | "version": "2.10.0", 4 | "main": [ 5 | "./js/bootstrap-markdown.js", 6 | "./css/bootstrap-markdown.min.css" 7 | ], 8 | "license": "Apache-2.0", 9 | "dependencies": { 10 | "bootstrap": "~3" 11 | }, 12 | "devDependencies": { 13 | "markdown": "~0.4.0" 14 | }, 15 | "homepage": "https://github.com/toopay/bootstrap-markdown", 16 | "_release": "2.10.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "v2.10.0", 20 | "commit": "3f69bb3db5020d29182c2092040f0ad8d390bda7" 21 | }, 22 | "_source": "https://github.com/toopay/bootstrap-markdown.git", 23 | "_target": "2.10.0", 24 | "_originalSource": "bootstrap-markdown", 25 | "_direct": true 26 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | indent_style = space 9 | indent_size = 2 10 | end_of_line = lf 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | .DS_Store 3 | node_modules/* 4 | .idea 5 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/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. 202 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/README.md: -------------------------------------------------------------------------------- 1 | ## Bootstrap Markdown 2 | 3 | Markdown editing meet Bootstrap. 4 | 5 | | Version | Compatibility with Bootstrap | 6 | | :---: | :---: | 7 | | Bootstrap Markdown v2.x | **only** compatible with Bootstrap 3.x | 8 | | Bootstrap Markdown v1.x | **only** compatible with Bootstrap 2.x | 9 | 10 | Demo and documentation on [http://toopay.github.io/bootstrap-markdown/](http://toopay.github.io/bootstrap-markdown/) 11 | 12 | ### LICENSE 13 | 14 | > Copyright 2013-2016 Taufan Aditya 15 | > 16 | > Licensed under the Apache License, Version 2.0 (the "License"); 17 | > you may not use this file except in compliance with the License. 18 | > You may obtain a copy of the License at 19 | > 20 | > http://www.apache.org/licenses/LICENSE-2.0 21 | > 22 | > Unless required by applicable law or agreed to in writing, software 23 | > distributed under the License is distributed on an "AS IS" BASIS, 24 | > WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25 | > See the License for the specific language governing permissions and 26 | > limitations under the License. 27 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-markdown", 3 | "version": "2.10.0", 4 | "main": ["./js/bootstrap-markdown.js", "./css/bootstrap-markdown.min.css"], 5 | "license": "Apache-2.0", 6 | "dependencies": { 7 | "bootstrap": "~3" 8 | }, 9 | "devDependencies": { 10 | "markdown":"~0.4.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/css/bootstrap-markdown.min.css: -------------------------------------------------------------------------------- 1 | .md-editor{display:block;border:1px solid #ddd}.md-editor .md-footer,.md-editor>.md-header{display:block;padding:6px 4px;background:#f5f5f5}.md-editor>.md-header{margin:0}.md-editor>.md-preview{background:#fff;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;min-height:10px;overflow:auto}.md-editor>textarea{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:14px;outline:0;margin:0;display:block;padding:0;width:100%;border:0;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;border-radius:0;box-shadow:none;background:#eee}.md-editor>textarea:focus{box-shadow:none;background:#fff}.md-editor.active{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.md-editor .md-controls{float:right;padding:3px}.md-editor .md-controls .md-control{right:5px;color:#bebebe;padding:3px 3px 3px 10px}.md-editor .md-controls .md-control:hover{color:#333}.md-editor.md-fullscreen-mode{width:100%;height:100%;position:fixed;top:0;left:0;z-index:99999;padding:60px 30px 15px;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-footer{display:none}.md-editor.md-fullscreen-mode .md-input,.md-editor.md-fullscreen-mode .md-preview{margin:0 auto!important;height:100%!important;font-size:20px!important;padding:20px!important;color:#999;line-height:1.6em!important;resize:none!important;box-shadow:none!important;background:#fff!important;border:0!important}.md-editor.md-fullscreen-mode .md-preview{color:#333;overflow:auto}.md-editor.md-fullscreen-mode .md-input:focus,.md-editor.md-fullscreen-mode .md-input:hover{color:#333;background:#fff!important}.md-editor.md-fullscreen-mode .md-header{background:0 0;text-align:center;position:fixed;width:100%;top:20px}.md-editor.md-fullscreen-mode .btn-group{float:none}.md-editor.md-fullscreen-mode .btn{border:0;background:0 0;color:#b3b3b3}.md-editor.md-fullscreen-mode .btn.active,.md-editor.md-fullscreen-mode .btn:active,.md-editor.md-fullscreen-mode .btn:focus,.md-editor.md-fullscreen-mode .btn:hover{box-shadow:none;color:#333}.md-editor.md-fullscreen-mode .md-fullscreen-controls{position:absolute;top:20px;right:20px;text-align:right;z-index:1002;display:block}.md-editor.md-fullscreen-mode .md-fullscreen-controls a{color:#b3b3b3;clear:right;margin:10px;width:30px;height:30px;text-align:center}.md-editor.md-fullscreen-mode .md-fullscreen-controls a:hover{color:#333;text-decoration:none}.md-editor.md-fullscreen-mode .md-editor{height:100%!important;position:relative}.md-editor .md-fullscreen-controls{display:none}.md-nooverflow{overflow:hidden;position:fixed;width:100%} -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/less/bootstrap-markdown.less: -------------------------------------------------------------------------------- 1 | /** 2 | * Bootstrap-Markdown.less 3 | * 4 | * @author Taufan Aditya @taufanaditya 5 | * @copyright 2013-2016 Taufan Aditya 6 | */ 7 | 8 | @table-border-color: #ddd; 9 | @panel-default-heading-bg: #f5f5f5; 10 | @panel-bg: #fff; 11 | @font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; 12 | @font-size-base: 14px; 13 | @input-bg-disabled: #eeeeee; 14 | @input-bg: #fff; 15 | @input-border-focus: #66afe9; 16 | 17 | .md-editor { 18 | display: block; 19 | border: 1px solid @table-border-color; 20 | 21 | > .md-header, .md-footer { 22 | display: block; 23 | padding: 6px 4px; 24 | background: @panel-default-heading-bg; 25 | } 26 | 27 | > .md-header { 28 | margin: 0; 29 | } 30 | 31 | > .md-preview { 32 | background: @panel-bg; 33 | border-top: 1px dashed @table-border-color; 34 | border-bottom: 1px dashed @table-border-color; 35 | min-height: 10px; 36 | overflow: auto; 37 | } 38 | 39 | > textarea { 40 | font-family: @font-family-monospace; 41 | font-size: @font-size-base; 42 | outline: 0; 43 | outline: thin dotted \9; /* IE6-9 */ 44 | margin: 0; 45 | display: block; 46 | padding: 0; 47 | width: 100%; 48 | border: 0; 49 | border-top: 1px dashed @table-border-color; 50 | border-bottom: 1px dashed @table-border-color; 51 | border-radius: 0; 52 | box-shadow: none; 53 | background: @input-bg-disabled; 54 | &:focus { 55 | box-shadow: none; 56 | background: @input-bg; 57 | } 58 | } 59 | 60 | // Hover state 61 | @color: @input-border-focus; 62 | @color-rgba: rgba(red(@color), green(@color), blue(@color), .6); 63 | &.active { 64 | border-color: @color; 65 | outline: 0; 66 | .box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}"); 67 | } 68 | 69 | .md-controls { 70 | float: right; 71 | padding: 3px; 72 | 73 | .md-control { 74 | right: 5px; 75 | color: #bebebe; 76 | padding: 3px 3px 3px 10px; 77 | &:hover { 78 | color: #333; 79 | } 80 | } 81 | } 82 | 83 | // fullscreen mode styles 84 | &.md-fullscreen-mode { 85 | width: 100%; 86 | height: 100%; 87 | position: fixed; 88 | top: 0; 89 | left: 0; 90 | z-index: 99999; 91 | padding: 60px 30px 15px; 92 | background: #fff !important; 93 | border: 0 !important; 94 | 95 | .md-footer { 96 | display: none; 97 | } 98 | 99 | .md-input, 100 | .md-preview { 101 | margin: 0 auto !important; 102 | height: 100% !important; 103 | font-size: 20px !important; 104 | padding: 20px !important; 105 | color: #999; 106 | line-height: 1.6em !important; 107 | resize: none !important; 108 | box-shadow: none !important; 109 | background: #fff !important; 110 | border: 0 !important; 111 | } 112 | 113 | .md-preview { 114 | color: #333; 115 | overflow: auto; 116 | } 117 | 118 | .md-input { 119 | &:hover, 120 | &:focus { 121 | color: #333; 122 | background: #fff !important; 123 | } 124 | } 125 | 126 | .md-header { 127 | background: none; 128 | text-align: center; 129 | position: fixed; 130 | width: 100%; 131 | top: 20px; 132 | } 133 | 134 | .btn-group { 135 | float: none; 136 | } 137 | 138 | .btn { 139 | border: 0; 140 | background: none; 141 | color: #b3b3b3; 142 | 143 | &:hover, 144 | &:focus, 145 | &.active, 146 | &:active { 147 | box-shadow: none; 148 | color: #333; 149 | } 150 | } 151 | 152 | .md-fullscreen-controls { 153 | position: absolute; 154 | top: 20px; 155 | right: 20px; 156 | text-align: right; 157 | z-index: 1002; 158 | display: block; 159 | a { 160 | color: #b3b3b3; 161 | clear: right; 162 | margin: 10px; 163 | width: 30px; 164 | height: 30px; 165 | text-align: center; 166 | 167 | &:hover { 168 | color: #333; 169 | text-decoration: none; 170 | } 171 | } 172 | } 173 | 174 | .md-editor { 175 | height: 100% !important; 176 | position: relative; 177 | } 178 | } 179 | 180 | .md-fullscreen-controls { 181 | display: none; 182 | } 183 | } 184 | 185 | .md-nooverflow { 186 | overflow: hidden; 187 | position: fixed; 188 | width: 100%; 189 | } 190 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.ar.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Arabic translation for bootstrap-markdown 3 | * George Ajam 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.nl = { 7 | 'Bold': "غامق", 8 | 'Italic': "مائل", 9 | 'Heading': "عنوان", 10 | 'URL/Link': "URL/رابط", 11 | 'Image': "صورة", 12 | 'List': "قائمة", 13 | 'Preview': "استعراض", 14 | 'strong text': "نص غامق", 15 | 'emphasized text': "نص هام", 16 | 'heading text': "العنوان", 17 | 'enter link description here': "ادخل وصف الرابط هنا", 18 | 'Insert Hyperlink': "ادخل الرابط هنا", 19 | 'enter image description here': "ادخل وصف الصورة هنا", 20 | 'Insert Image Hyperlink': "ادخل رابط الصورة هنا", 21 | 'enter image title here': "ادخل عنوان الصورة هنا", 22 | 'list text here': "اكتب النص هنا" 23 | }; 24 | }(jQuery)); 25 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.cs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Czech translation for bootstrap-markdown 3 | * Vít Kabele 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.cs = { 7 | 'Bold': "Tučně", 8 | 'Italic': "Kurzíva", 9 | 'Heading': "Nadpis", 10 | 'URL/Link': "URL/Odkaz", 11 | 'Image': "Obrázek", 12 | 'Unordered List': "Seznam", 13 | 'Ordered List': "Seřazený seznam", 14 | 'Code': "Úsek kódu", 15 | 'Quote': "Citace", 16 | 'Preview': "Náhled", 17 | 'strong text': "tučný text", 18 | 'emphasized text': "zdůrazněný text", 19 | 'heading text': "text nadpisu", 20 | 'enter link description here': "sem vlož popis odkazu", 21 | 'Insert Hyperlink': "Vložit Hyperlink", 22 | 'enter image description here': "sem vlož popis obrázku", 23 | 'Insert Image Hyperlink': "Vlož adresu obrázku", 24 | 'enter image title here': "sem vlož popis obrázku", 25 | 'list text here': "položka seznamu" 26 | }; 27 | }(jQuery)); 28 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.da.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Danish translation for bootstrap-markdown 3 | * Dan Storm 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.nb = { 7 | 'Bold': 'Fed', 8 | 'Italic': 'Kursiv', 9 | 'Heading': 'Overskrift', 10 | 'URL/Link': 'URL/Link', 11 | 'Image': 'Billede', 12 | 'List': 'Liste', 13 | 'Preview': 'Forhåndsvisning', 14 | 'strong text': 'stærk tekst', 15 | 'emphasized text': 'fremhævet tekst', 16 | 'heading text': 'overskrift tekst', 17 | 'enter link description here': 'Skriv link beskrivelse her', 18 | 'Insert Hyperlink': 'Indsæt link', 19 | 'enter image description here': 'Indsæt billede beskrivelse her', 20 | 'Insert Image Hyperlink': 'Indsæt billede link', 21 | 'enter image title here': 'Indsæt billede titel', 22 | 'list text here': 'Indsæt liste tekst her', 23 | 'quote here': 'Indsæt citat her', 24 | 'code text here': 'Indsæt kode her' 25 | }; 26 | }(jQuery)); 27 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.de.js: -------------------------------------------------------------------------------- 1 | /** 2 | * German translation for bootstrap-markdown 3 | * Tobias Nitsche 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.de = { 7 | 'Bold': "Fett", 8 | 'Italic': "Kursiv", 9 | 'Heading': "Überschrift", 10 | 'URL/Link': "Link hinzufügen", 11 | 'Image': "Bild hinzufügen", 12 | 'Unordered List': "Unnummerierte Liste", 13 | 'Ordered List': "Nummerierte Liste", 14 | 'Code': "Quelltext", 15 | 'Quote': "Zitat", 16 | 'Preview': "Vorschau", 17 | 'strong text': "Sehr betonter Text", 18 | 'emphasized text': "Betonter Text", 19 | 'heading text': "Überschrift Text", 20 | 'enter link description here': "Linkbeschreibung", 21 | 'Insert Hyperlink': "URL", 22 | 'enter image description here': "Bildbeschreibung", 23 | 'Insert Image Hyperlink': "Bild-URL", 24 | 'enter image title here': "Titel des Bildes", 25 | 'list text here': "Aufzählungs-Text" 26 | }; 27 | }(jQuery)); 28 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.es.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Spanish translation for bootstrap-markdown 3 | * by Leandro Poblet 4 | */ 5 | ;(function($){ 6 | $.fn.markdown.messages['es'] = { 7 | 'Bold': "Negrita", 8 | 'Italic': "Itálica", 9 | 'Heading': "Título", 10 | 'URL/Link': "Inserte un link", 11 | 'Image': "Inserte una imagen", 12 | 'List': "Lista de items", 13 | 'Preview': "Previsualizar", 14 | 'strong text': "texto importante", 15 | 'emphasized text': "texto con énfasis", 16 | 'heading text': "texto titular", 17 | 'enter link description here': "descripción del link", 18 | 'Insert Hyperlink': "Inserte un hipervínculo", 19 | 'enter image description here': "descripción de la imagen", 20 | 'Insert Image Hyperlink': "Inserte una imagen con un hipervínculo", 21 | 'enter image title here': "Inserte una imagen con título", 22 | 'list text here': "lista con texto" 23 | }; 24 | }(jQuery)); 25 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.fa.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Persian(Farsi) translation for bootstrap-markdown 3 | * Sajad Dehshiri 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.fa = { 7 | 'Bold': "توپر", 8 | 'Italic': "مورب", 9 | 'Heading': "عنوان", 10 | 'URL/Link': "پیوند", 11 | 'Image': "تصویر", 12 | 'List': "فهرست", 13 | 'Preview': "پیش نمایش", 14 | 'strong text': "متن ضخیم", 15 | 'emphasized text': "نوشته تاکیدی", 16 | 'heading text': "عنوان", 17 | 'enter link description here': "توضیحات پیوند را بنویسید.", 18 | 'Insert Hyperlink': "پیوند را درج نمایید:", 19 | 'enter image description here': "توضیحی برای تصوی بنویسید.", 20 | 'Insert Image Hyperlink': "آدرس تصویر را بنویسید.", 21 | 'enter image title here': "عنوان تصویر را اینجا بنویسید", 22 | 'list text here': "محل متن فهرست" 23 | }; 24 | }(jQuery)); 25 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.fr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * French translation for bootstrap-markdown 3 | * Benoît Bourgeois 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.fr = { 7 | 'Bold': "Gras", 8 | 'Italic': "Italique", 9 | 'Heading': "Titre", 10 | 'URL/Link': "Insérer un lien HTTP", 11 | 'Image': "Insérer une image", 12 | 'List': "Liste à puces", 13 | 'Preview': "Prévisualiser", 14 | 'strong text': "texte important", 15 | 'emphasized text': "texte en italique", 16 | 'heading text': "texte d'entête", 17 | 'enter link description here': "entrez la description du lien ici", 18 | 'Insert Hyperlink': "Insérez le lien hypertexte", 19 | 'enter image description here': "entrez la description de l'image ici", 20 | 'Insert Image Hyperlink': "Insérez le lien hypertexte de l'image", 21 | 'enter image title here': "entrez le titre de l'image ici", 22 | 'list text here': "texte à puce ici", 23 | 'Save': "Sauvegarder", 24 | 'Ordered List': "Liste ordonnée", 25 | 'Unordered List': "Liste désordonnée", 26 | 'Quote': "Citation", 27 | 'quote here': "Votre citation", 28 | 'Code': "Code", 29 | 'code text here': "écrire du code ici" 30 | }; 31 | }(jQuery)); 32 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.it.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Italian translation for bootstrap-markdown 3 | * Michele Virgilio 4 | */ 5 | ;(function($){ 6 | $.fn.markdown.messages['it'] = { 7 | 'Bold': "Grassetto", 8 | 'Italic': "Corsivo", 9 | 'Heading': "Titolo", 10 | 'URL/Link': "URL/Collegamento", 11 | 'Image': "Inserisci un'immagine", 12 | 'List': "Lista", 13 | 'Preview': "Anteprima", 14 | 'strong text': "Testo grassetto", 15 | 'emphasized text': "Testo corsivo", 16 | 'heading text': "Titolo", 17 | 'enter link description here': "Inserisci la descrizione del link", 18 | 'Insert Hyperlink': "Inserisci Hyperlink", 19 | 'enter image description here': "Inserisci la descrizione dell'immagine", 20 | 'Insert Image Hyperlink': "Inserisci link per l'immagine", 21 | 'enter image title here': "Inserisci il titolo dell'immagine", 22 | 'list text here': "Testo della lista" 23 | }; 24 | }(jQuery)) 25 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.ja.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Japanese translation for bootstrap-markdown 3 | * Kenta Murakami 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages['ja'] = { 7 | 'Bold': "太字", 8 | 'Italic': "斜体", 9 | 'Heading': "見出し", 10 | 'URL/Link': "リンク", 11 | 'Image': "画像", 12 | 'Unordered List': "リスト", 13 | 'Ordered List': "数字リスト", 14 | 'Code': "コード", 15 | 'Quote': "引用", 16 | 'Preview': "プレビュー", 17 | 'strong text': "太字", 18 | 'emphasized text': "強調", 19 | 'heading text': "見出し", 20 | 'enter link description here': "リンク説明", 21 | 'Insert Hyperlink': "リンク挿入", 22 | 'enter image description here': "画像説明", 23 | 'Insert Image Hyperlink': "画像挿入", 24 | 'enter image title here': "画像タイトル", 25 | 'list text here': "リスト挿入", 26 | 'code text here': "コード", 27 | 'quote here': "引用挿入" 28 | }; 29 | }(jQuery)); 30 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.kr.js: -------------------------------------------------------------------------------- 1 | /** 2 | + * Korean translation for bootstrap-markdown 3 | + * WoongBi Kim 4 | + */ 5 | ;(function($){ 6 | $.fn.markdown.messages['kr'] = { 7 | 'Bold': "진하게", 8 | 'Italic': "이탤릭체", 9 | 'Heading': "머리글", 10 | 'URL/Link': "링크주소", 11 | 'Image': "이미지", 12 | 'List': "리스트", 13 | 'Preview': "미리보기", 14 | 'strong text': "강한 강조 텍스트", 15 | 'emphasized text': "강조 텍스트", 16 | 'heading text': "머리글 텍스트", 17 | 'enter link description here': "여기에 링크의 설명을 적으세요", 18 | 'Insert Hyperlink': "하이퍼링크 삽입", 19 | 'enter image description here': "여기세 이미지 설명을 적으세요", 20 | 'Insert Image Hyperlink': "이미지 링크 삽입", 21 | 'enter image title here': "여기에 이미지 제목을 적으세요", 22 | 'list text here': "리스트 텍스트" 23 | }; 24 | }(jQuery)); 25 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.nb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Norwegian bokmål translation for bootstrap-markdown 3 | * Tobias Bohwalli 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.nb = { 7 | 'Bold': 'Fet', 8 | 'Italic': 'Kursiv', 9 | 'Heading': 'Overskrift', 10 | 'URL/Link': 'URL/Lenke', 11 | 'Image': 'Bilde', 12 | 'List': 'Liste', 13 | 'Preview': 'Forhåndsvisning', 14 | 'strong text': 'sterk tekst', 15 | 'emphasized text': 'streket tekst', 16 | 'heading text': 'overskriften tekst', 17 | 'enter link description here': 'Skriv linken beskrivelse her', 18 | 'Insert Hyperlink': 'Sett inn lenke', 19 | 'enter image description here': 'Angi bildebeskrivelse her', 20 | 'Insert Image Hyperlink': 'Sett inn lenke for bilde', 21 | 'enter image title here': 'Angi bildetittel her', 22 | 'list text here': 'liste tekst her' 23 | }; 24 | }(jQuery)); 25 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.nl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dutch translation for bootstrap-markdown 3 | * Jeroen Thora 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.nl = { 7 | 'Bold': "Vet", 8 | 'Italic': "Cursief", 9 | 'Heading': "Titel", 10 | 'URL/Link': "URL/Link", 11 | 'Image': "Afbeelding", 12 | 'List': "Lijst", 13 | 'Preview': "Voorbeeld", 14 | 'strong text': "vet gedrukte tekst", 15 | 'emphasized text': "schuin gedrukte tekst", 16 | 'heading text': "Titel", 17 | 'enter link description here': "Voer een link beschrijving in", 18 | 'Insert Hyperlink': "Voer een http link in", 19 | 'enter image description here': "Voer een afbeelding beschrijving in", 20 | 'Insert Image Hyperlink': "Voer een afbeelding link in", 21 | 'enter image title here': "Voer de afbeelding titel in", 22 | 'list text here': "lijst item" 23 | }; 24 | }(jQuery)); 25 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.pl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Polish translation for bootstrap-markdown 3 | * Marek Kaput 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.pl = { 7 | 'Bold': "Pogrubienie", 8 | 'Italic': "Kursywa", 9 | 'Heading': "Nagłówek", 10 | 'URL/Link': "Wstaw link", 11 | 'Image': "Wstaw obrazek", 12 | 'Unordered List': "Lista punktowana", 13 | 'Ordered List': "Lista numerowana", 14 | 'Code': "Kod źródłowy", 15 | 'Quote': "Cytat", 16 | 'Preview': "Podgląd", 17 | 'strong text': "pogrubiony tekst", 18 | 'emphasized text': "pochylony tekst", 19 | 'heading text': "nagłówek", 20 | 'enter link description here': "opis linka", 21 | 'Insert Hyperlink': "Wstaw link", 22 | 'enter image description here': "opis obrazka", 23 | 'Insert Image Hyperlink': "Wstaw obrazek", 24 | 'enter image title here': "tytuł obrazka", 25 | 'list text here': "lista" 26 | }; 27 | }(jQuery)); 28 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.ru.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Russian translation for bootstrap-markdown 3 | * by Oleg Vivtash 4 | */ 5 | ;(function($){ 6 | $.fn.markdown.messages['ru'] = { 7 | 'Bold': "Жирный", 8 | 'strong text': "выделенный текст", 9 | 'Italic': "Курсив", 10 | 'emphasized text': "наклонный текст", 11 | 'Heading': "Заголовок", 12 | 'heading text': "текст заголовка", 13 | 'URL/Link': "Вставьте ссылку", 14 | 'Insert Hyperlink': "Введите гиперссылку", 15 | 'enter link description here': "введите описание ссылки", 16 | 'Image': "Изображение", 17 | 'enter image description here': "Введите описание изображения", 18 | 'Insert Image Hyperlink': "Вставьте ссылку на изображение", 19 | 'enter image title here': "Введите название изображения", 20 | 'List': "Список", 21 | 'Unordered List': "Неупорядоченный список", 22 | 'Ordered List': "Упорядоченный список", 23 | 'list text here': "текст списка", 24 | 'Code': "Код", 25 | 'code text here': "программный код", 26 | 'Quote': "Цитата", 27 | 'quote here': "цитируемый текст", 28 | 'Save': "Сохранить", 29 | 'Preview': "Предпросмотр" 30 | }; 31 | }(jQuery)) 32 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.sl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Slovenian translation for bootstrap-markdown 3 | * Davor Padovan 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.sl = { 7 | 'Bold': "Odebeljeno", 8 | 'Italic': "Poševno", 9 | 'Heading': "Naslov", 10 | 'URL/Link': "Povezava", 11 | 'Image': "Slika", 12 | 'Unordered List': "Neurejen seznam", 13 | 'Ordered List': "Urejen seznam", 14 | 'Code': "Koda", 15 | 'Quote': "Citat", 16 | 'Preview': "Predogled", 17 | 'strong text': "odebeljeno besedilo", 18 | 'emphasized text': "poševno besedilo", 19 | 'heading text': "naslov", 20 | 'enter link description here': "opis povezave", 21 | 'Insert Hyperlink': "Vstavi povezavo", 22 | 'enter image description here': "opis slike", 23 | 'Insert Image Hyperlink': "Vstavi povezavo do slike", 24 | 'enter image title here': "naslov slike", 25 | 'list text here': "seznam" 26 | }; 27 | }(jQuery)); 28 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.sv.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Swedish translation for bootstrap-markdown 3 | * Tobias Bohwalli 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.sv = { 7 | 'Bold': 'Fet', 8 | 'Italic': 'Kursiv', 9 | 'Heading': 'Rubrik', 10 | 'URL/Link': 'URL/Länk', 11 | 'Image': 'Bild', 12 | 'List': 'Lista', 13 | 'Preview': 'Förhandsgranska', 14 | 'strong text': 'fet text', 15 | 'emphasized text': 'överstruken text', 16 | 'heading text': 'Rubrik', 17 | 'enter link description here': 'Ange länk beskrivning här', 18 | 'Insert Hyperlink': 'Sätt in länk', 19 | 'enter image description here': 'Ange bild beskrivning här', 20 | 'Insert Image Hyperlink': 'Sätt in länk för bild', 21 | 'enter image title here': 'Ange bild rubrik här', 22 | 'list text here': 'list text' 23 | }; 24 | }(jQuery)); 25 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.tr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Turkish translation for bootstrap-markdown 3 | * Serkan Algur 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.tr = { 7 | 'Bold': "Kalın", 8 | 'Italic': "İtalik", 9 | 'Heading': "Başlık", 10 | 'URL/Link': "Link ekle", 11 | 'Image': "Resim ekle", 12 | 'List': "Liste Oluşturun", 13 | 'Preview': "Önizleme", 14 | 'strong text': "kalın yazı", 15 | 'emphasized text': "italik yazı", 16 | 'heading text': "Başlık Yazısı", 17 | 'enter link description here': "Link açıklamasını buraya girin", 18 | 'Insert Hyperlink': "İnternet adresi girin", 19 | 'enter image description here': "resim açıklamasını buraya ekleyin", 20 | 'Insert Image Hyperlink': "Resim linkini ekleyin", 21 | 'enter image title here': "resim başlığını buraya ekleyin", 22 | 'list text here': "liste yazısı", 23 | 'Save' : "Kaydet", 24 | 'Ordered List' : "Numaralı Liste", 25 | 'Unordered List' : "Madde imli liste", 26 | 'Quote' : "Alıntı", 27 | 'quote here' : "alıntıyı buraya ekleyin", 28 | 'Code' : "Kod", 29 | 'code text here' : "kodu buraya ekleyin" 30 | }; 31 | }(jQuery)); 32 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.ua.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Ukrainian translation for bootstrap-markdown 3 | * by Oleg Vivtash 4 | */ 5 | ;(function($){ 6 | $.fn.markdown.messages['ua'] = { 7 | 'Bold': "Жирний", 8 | 'Italic': "Курсів", 9 | 'Heading': "Заголовок", 10 | 'URL/Link': "Вставте посилання", 11 | 'Image': "Зображення", 12 | 'List': "Список", 13 | 'Preview': "Попередній перегляд", 14 | 'strong text': "виділений текст", 15 | 'emphasized text': "нахилений текст", 16 | 'heading text': "текст заголовку", 17 | 'enter link description here': "введіть опис посилання", 18 | 'Insert Hyperlink': "Введіть гіперпосилання", 19 | 'enter image description here': "Введіть опис зображення", 20 | 'Insert Image Hyperlink': "Вставте посилання на зображення", 21 | 'enter image title here': "Введіть назву зображення", 22 | 'list text here': "текст списку" 23 | }; 24 | }(jQuery)) 25 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/locale/bootstrap-markdown.zh.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Chinese translation for bootstrap-markdown 3 | * benhaile 4 | */ 5 | (function ($) { 6 | $.fn.markdown.messages.zh = { 7 | 'Bold': "粗体", 8 | 'Italic': "斜体", 9 | 'Heading': "标题", 10 | 'URL/Link': "链接", 11 | 'Image': "图片", 12 | 'List': "列表", 13 | 'Unordered List': "无序列表", 14 | 'Ordered List': "有序列表", 15 | 'Code': "代码", 16 | 'Quote': "引用", 17 | 'Preview': "预览", 18 | 'strong text': "粗体", 19 | 'emphasized text': "强调", 20 | 'heading text': "标题", 21 | 'enter link description here': "输入链接说明", 22 | 'Insert Hyperlink': "URL地址", 23 | 'enter image description here': "输入图片说明", 24 | 'Insert Image Hyperlink': "图片URL地址", 25 | 'enter image title here': "在这里输入图片标题", 26 | 'list text here': "这里是列表文本", 27 | 'code text here': "这里输入代码", 28 | 'quote here': "这里输入引用文本" 29 | 30 | 31 | }; 32 | }(jQuery)); 33 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap-markdown", 3 | "main": "js/bootstrap-markdown.js", 4 | "version": "2.10.0", 5 | "description": "A bootstrap plugin for markdown editing", 6 | "license" : "Apache-2.0", 7 | "homepage": "https://github.com/toopay/bootstrap-markdown", 8 | "keywords": [ 9 | "twitter", 10 | "bootstrap", 11 | "markdown", 12 | "editor" 13 | ], 14 | "maintainers": [{ 15 | "name": "Taufan Aditya", 16 | "web": "https://github.com/toopay" 17 | }], 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/toopay/bootstrap-markdown.git" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap-markdown/scss/bootstrap-markdown.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Bootstrap-Markdown.less 3 | * 4 | * @author Taufan Aditya @taufanaditya 5 | * @copyright 2013-2016 Taufan Aditya 6 | */ 7 | 8 | $table-border-color: #ddd; 9 | $panel-default-heading-bg: #f5f5f5; 10 | $panel-bg: #fff; 11 | $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; 12 | $font-size-base: 14px; 13 | $input-bg-disabled: #eeeeee; 14 | $input-bg: #fff; 15 | $input-border-focus: #66afe9; 16 | 17 | .md-editor { 18 | display: block; 19 | border: 1px solid $table-border-color; 20 | 21 | > .md-header, .md-footer { 22 | display: block; 23 | padding: 6px 4px; 24 | background: $panel-default-heading-bg; 25 | } 26 | 27 | > .md-header { 28 | margin: 0; 29 | } 30 | 31 | > .md-preview { 32 | background: $panel-bg; 33 | border-top: 1px dashed $table-border-color; 34 | border-bottom: 1px dashed $table-border-color; 35 | min-height: 10px; 36 | overflow: auto; 37 | } 38 | 39 | > textarea { 40 | font-family: $font-family-monospace; 41 | font-size: $font-size-base; 42 | outline: 0; 43 | outline: thin dotted \9; /* IE6-9 */ 44 | margin: 0; 45 | display: block; 46 | padding: 0; 47 | width: 100%; 48 | border: 0; 49 | border-top: 1px dashed $table-border-color; 50 | border-bottom: 1px dashed $table-border-color; 51 | border-radius: 0; 52 | box-shadow: none; 53 | background: $input-bg-disabled; 54 | &:focus { 55 | box-shadow: none; 56 | background: $input-bg; 57 | } 58 | } 59 | 60 | // Hover state 61 | $color: $input-border-focus; 62 | $color-rgba: rgba(red($color), green($color), blue($color), .6); 63 | &.active { 64 | border-color: $color; 65 | outline: 0; 66 | @include box-shadow(inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px $color-rgba); 67 | } 68 | 69 | .md-controls { 70 | float: right; 71 | padding: 3px; 72 | 73 | .md-control { 74 | right: 5px; 75 | color: #bebebe; 76 | padding: 3px 3px 3px 10px; 77 | &:hover { 78 | color: #333; 79 | } 80 | } 81 | } 82 | 83 | // fullscreen mode styles 84 | &.md-fullscreen-mode { 85 | width: 100%; 86 | height: 100%; 87 | position: fixed; 88 | top: 0; 89 | left: 0; 90 | z-index: 99999; 91 | padding: 60px 30px 15px; 92 | background: #fff !important; 93 | border: 0 !important; 94 | 95 | .md-footer { 96 | display: none; 97 | } 98 | 99 | .md-input, 100 | .md-preview { 101 | margin: 0 auto !important; 102 | height: 100% !important; 103 | font-size: 20px !important; 104 | padding: 20px !important; 105 | color: #999; 106 | line-height: 1.6em !important; 107 | resize: none !important; 108 | box-shadow: none !important; 109 | background: #fff !important; 110 | border: 0 !important; 111 | } 112 | 113 | .md-preview { 114 | color: #333; 115 | overflow: auto; 116 | } 117 | 118 | .md-input { 119 | &:hover, 120 | &:focus { 121 | color: #333; 122 | background: #fff !important; 123 | } 124 | } 125 | 126 | .md-header { 127 | background: none; 128 | text-align: center; 129 | position: fixed; 130 | width: 100%; 131 | top: 20px; 132 | } 133 | 134 | .btn-group { 135 | float: none; 136 | } 137 | 138 | .btn { 139 | border: 0; 140 | background: none; 141 | color: #b3b3b3; 142 | 143 | &:hover, 144 | &:focus, 145 | &.active, 146 | &:active { 147 | box-shadow: none; 148 | color: #333; 149 | } 150 | } 151 | 152 | .md-fullscreen-controls { 153 | position: absolute; 154 | top: 20px; 155 | right: 20px; 156 | text-align: right; 157 | z-index: 1002; 158 | display: block; 159 | a { 160 | color: #b3b3b3; 161 | clear: right; 162 | margin: 10px; 163 | width: 30px; 164 | height: 30px; 165 | text-align: center; 166 | 167 | &:hover { 168 | color: #333; 169 | text-decoration: none; 170 | } 171 | } 172 | } 173 | 174 | .md-editor { 175 | height: 100% !important; 176 | position: relative; 177 | } 178 | } 179 | 180 | .md-fullscreen-controls { 181 | display: none; 182 | } 183 | } 184 | 185 | .md-nooverflow { 186 | overflow: hidden; 187 | position: fixed; 188 | width: 100%; 189 | } 190 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 2" 33 | }, 34 | "version": "3.3.6", 35 | "_release": "3.3.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.6", 39 | "commit": "81df608a40bf0629a1dc08e584849bb1e43e0b7a" 40 | }, 41 | "_source": "git://github.com/twbs/bootstrap.git", 42 | "_target": "3.3.6", 43 | "_originalSource": "bootstrap" 44 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2015 Twitter, Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":";;;;AAmBA,YAAA,aAAA,UAAA,aAAA,aAAA,aAME,YAAA,EAAA,KAAA,EAAA,eC2CA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBDvCR,mBAAA,mBAAA,oBAAA,oBAAA,iBAAA,iBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBCsCA,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBDlCR,qBAAA,sBAAA,sBAAA,uBAAA,mBAAA,oBAAA,sBAAA,uBAAA,sBAAA,uBAAA,sBAAA,uBAAA,+BAAA,gCAAA,6BAAA,gCAAA,gCAAA,gCCiCA,mBAAA,KACQ,WAAA,KDlDV,mBAAA,oBAAA,iBAAA,oBAAA,oBAAA,oBAuBI,YAAA,KAyCF,YAAA,YAEE,iBAAA,KAKJ,aErEI,YAAA,EAAA,IAAA,EAAA,KACA,iBAAA,iDACA,iBAAA,4CAAA,iBAAA,qEAEA,iBAAA,+CCnBF,OAAA,+GH4CA,OAAA,0DACA,kBAAA,SAuC2C,aAAA,QAA2B,aAAA,KArCtE,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAgBN,aEtEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAiBN,aEvEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAkBN,UExEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,gBAAA,gBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,iBAAA,iBAEE,iBAAA,QACA,aAAA,QAMA,mBAAA,0BAAA,yBAAA,0BAAA,yBAAA,yBAAA,oBAAA,2BAAA,0BAAA,2BAAA,0BAAA,0BAAA,6BAAA,oCAAA,mCAAA,oCAAA,mCAAA,mCAME,iBAAA,QACA,iBAAA,KAmBN,aEzEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAoBN,YE1EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,kBAAA,kBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,mBAAA,mBAEE,iBAAA,QACA,aAAA,QAMA,qBAAA,4BAAA,2BAAA,4BAAA,2BAAA,2BAAA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,+BAAA,sCAAA,qCAAA,sCAAA,qCAAA,qCAME,iBAAA,QACA,iBAAA,KA2BN,eAAA,WClCE,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBD2CV,0BAAA,0BE3FI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GF0FF,kBAAA,SAEF,yBAAA,+BAAA,+BEhGI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GFgGF,kBAAA,SASF,gBE7GI,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SH+HA,cAAA,ICjEA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBD6DV,sCAAA,oCE7GI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBD0EV,cAAA,iBAEE,YAAA,EAAA,IAAA,EAAA,sBAIF,gBEhII,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SHkJA,cAAA,IAHF,sCAAA,oCEhII,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBDgFV,8BAAA,iCAYI,YAAA,EAAA,KAAA,EAAA,gBAKJ,qBAAA,kBAAA,mBAGE,cAAA,EAqBF,yBAfI,mDAAA,yDAAA,yDAGE,MAAA,KE7JF,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,UFqKJ,OACE,YAAA,EAAA,IAAA,EAAA,qBC3HA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBDsIV,eEtLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAKF,YEvLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAMF,eExLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAOF,cEzLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAeF,UEjMI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFuMJ,cE3MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFwMJ,sBE5MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyMJ,mBE7MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0MJ,sBE9MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2MJ,qBE/MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF+MJ,sBElLI,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKFyLJ,YACE,cAAA,IC9KA,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBDgLV,wBAAA,8BAAA,8BAGE,YAAA,EAAA,KAAA,EAAA,QEnOE,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFiOF,aAAA,QALF,+BAAA,qCAAA,qCAQI,YAAA,KAUJ,OCnME,mBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,EAAA,IAAA,IAAA,gBD4MV,8BE5PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyPJ,8BE7PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0PJ,8BE9PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2PJ,2BE/PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF4PJ,8BEhQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF6PJ,6BEjQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoQJ,MExQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFsQF,aAAA,QC3NA,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA"} -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linezero/NETCoreBBS/71ac2c572f8d25d79bad0fdfd695d7d6d7e2bcf6/src/NetCoreBBS/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linezero/NETCoreBBS/71ac2c572f8d25d79bad0fdfd695d7d6d7e2bcf6/src/NetCoreBBS/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linezero/NETCoreBBS/71ac2c572f8d25d79bad0fdfd695d7d6d7e2bcf6/src/NetCoreBBS/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linezero/NETCoreBBS/71ac2c572f8d25d79bad0fdfd695d7d6d7e2bcf6/src/NetCoreBBS/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "version": "3.2.6", 4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", 6 | "main": [ 7 | "jquery.validate.unobtrusive.js" 8 | ], 9 | "ignore": [ 10 | "**/.*", 11 | "*.json", 12 | "*.md", 13 | "*.txt", 14 | "gulpfile.js" 15 | ], 16 | "keywords": [ 17 | "jquery", 18 | "asp.net", 19 | "mvc", 20 | "validation", 21 | "unobtrusive" 22 | ], 23 | "authors": [ 24 | "Microsoft" 25 | ], 26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" 30 | }, 31 | "dependencies": { 32 | "jquery-validation": ">=1.8", 33 | "jquery": ">=1.8" 34 | }, 35 | "_release": "3.2.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.2.6", 39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" 40 | }, 41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", 42 | "_target": "3.2.6", 43 | "_originalSource": "jquery-validation-unobtrusive" 44 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | !function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "http://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jzaefferer/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.14.0", 31 | "_release": "1.14.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.14.0", 35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" 36 | }, 37 | "_source": "git://github.com/jzaefferer/jquery-validation.git", 38 | "_target": ">=1.8", 39 | "_originalSource": "jquery-validation" 40 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "2.2.0", 16 | "_release": "2.2.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "2.2.0", 20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5" 21 | }, 22 | "_source": "git://github.com/jquery/jquery-dist.git", 23 | "_target": "2.2.0", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /src/NetCoreBBS/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /tests/UnitTests/UnitTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | --------------------------------------------------------------------------------